]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/weapons/spawning.qc
Support count field on weapon pickups, fix 0 ammo with target_give and no count set...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / weapons / spawning.qc
1 #include "spawning.qh"
2
3 #include "weaponsystem.qh"
4 #include "../resources.qh"
5 #include <server/mutators/_mod.qh>
6 #include <server/items/items.qh>
7 #include <server/items/spawning.qh>
8 #include <common/weapons/_all.qh>
9
10 .bool m_isreplaced; ///< Holds whether the weapon has been replaced.
11
12 string W_Apply_Weaponreplace(string in)
13 {
14         string out = "";
15         FOREACH_WORD(in, true, {
16                 string replacement = "";
17                 Weapon w = Weapon_from_name(it);
18                 if (w)
19                 {
20             replacement = w.weaponreplace;
21             if (replacement == "") replacement = it;
22                 }
23                 if (replacement == "0") continue;
24                 out = cons(out, replacement);
25         });
26         return out;
27 }
28
29 void weapon_defaultspawnfunc(entity this, Weapon wpn)
30 {
31         wpn = wpn.m_spawnfunc_hookreplace(wpn, this);
32         this.classname = wpn.m_canonical_spawnfunc;
33         if (!Item_IsLoot(this) && !this.m_isreplaced)
34         {
35                 if (wpn.spawnflags & WEP_FLAG_MUTATORBLOCKED)
36                 {
37                         //LOG_WARNF("Attempted to spawn a mutator-blocked weapon rejected: prvm_edict server %i", this);
38                         startitem_failed = true;
39                         return;
40                 }
41
42                 string s = W_Apply_Weaponreplace(wpn.netname);
43                 MUTATOR_CALLHOOK(SetWeaponreplace, this, wpn, s);
44                 s = M_ARGV(2, string);
45                 if (s == "")
46                 {
47                         delete(this);
48                         startitem_failed = true;
49                         return;
50                 }
51                 int t = tokenize_console(s);
52                 if (t >= 2)
53                 {
54                         this.team = --internalteam;
55                         for (int i = 1; i < t; ++i)
56                         {
57                                 s = argv(i);
58                                 Weapon wep = Weapon_from_name(s);
59                                 if(wep != WEP_Null)
60                                 {
61                                         entity replacement = spawn();
62                                         copyentity(this, replacement);
63                                         replacement.m_isreplaced = true;
64                                         weapon_defaultspawnfunc(replacement, wep);
65                                 }
66                         }
67                 }
68                 if (t >= 1) // always the case!
69                 {
70                         s = argv(0);
71                         wpn = Weapon_from_name(s);
72                 }
73                 if (wpn == WEP_Null)
74                 {
75                         delete(this);
76                         startitem_failed = true;
77                         return;
78                 }
79         }
80
81         if(!Item_IsLoot(this))
82                 weaponsInMapAll |= WepSet_FromWeapon(wpn);
83
84         if (!Item_IsDefinitionAllowed(wpn.m_pickup))
85         {
86                 delete(this);
87                 startitem_failed = true;
88                 return;
89         }
90
91         if (!this.respawntime)
92         {
93                 if (wpn.spawnflags & WEP_FLAG_SUPERWEAPON)
94                 {
95                         this.respawntime = g_pickup_respawntime_superweapon;
96                         this.respawntimejitter = g_pickup_respawntimejitter_superweapon;
97                 }
98                 else
99                 {
100                         this.respawntime = g_pickup_respawntime_weapon;
101                         this.respawntimejitter = g_pickup_respawntimejitter_weapon;
102                 }
103         }
104
105         if (wpn.spawnflags & WEP_FLAG_SUPERWEAPON)
106                 if (!this.superweapons_finished)
107                         this.superweapons_finished = autocvar_g_balance_superweapons_time;
108
109         // if we don't already have ammo, give us some ammo
110         if ((wpn.ammo_type != RES_NONE) && !GetResource(this, wpn.ammo_type))
111         {
112                 int ammo = 0;
113                 if (this.count > 0)
114                 {
115                         switch (wpn.netname)
116                         {
117                                 case "arc":        ammo = cvar("g_balance_arc_beam_ammo");              break;
118                                 case "devastator": ammo = cvar("g_balance_devastator_ammo");            break;
119                                 case "machinegun": ammo = cvar("g_balance_machinegun_sustained_ammo");  break;
120                                 case "minelayer":  ammo = cvar("g_balance_minelayer_ammo");             break;
121                                 case "seeker":     ammo = cvar("g_balance_seeker_tag_ammo");            break;
122                                 default:           ammo = cvar(strcat("g_balance_", wpn.netname, "_primary_ammo"));
123                         }
124
125                         ammo *= this.count;
126                 }
127                 else
128                 {
129                         switch (wpn.ammo_type)
130                         {
131                                 case RES_SHELLS:  ammo = cvar("g_pickup_shells_weapon");  break;
132                                 case RES_BULLETS: ammo = cvar("g_pickup_nails_weapon");   break;
133                                 case RES_ROCKETS: ammo = cvar("g_pickup_rockets_weapon"); break;
134                                 case RES_CELLS:   ammo = cvar("g_pickup_cells_weapon");   break;
135                                 case RES_PLASMA:  ammo = cvar("g_pickup_plasma_weapon");  break;
136                                 case RES_FUEL:    ammo = cvar("g_pickup_fuel_weapon");    break;
137                         }
138                 }
139
140                 SetResource(this, wpn.ammo_type, ammo);
141         }
142
143         #if 0 // WEAPONTODO
144         if (wpn.items)
145         {
146                 for (int i = 0, j = 1; i < 24; ++i, j <<= 1)
147                 {
148                         if (wpn.items & j)
149                         {
150                                 ammotype = Item_CounterField(j);
151                                 if (!this.ammotype)
152                                         this.ammotype = cvar(strcat("g_pickup_", Item_CounterFieldName(j), "_weapon"));
153                         }
154                 }
155         }
156         #endif
157
158         // pickup anyway
159         if (g_pickup_weapons_anyway)
160                 this.pickup_anyway = true;
161
162         if(!this.owner)
163                 this.glowmod = wpn.wpcolor;
164
165         GameItem def = wpn.m_pickup;
166         _StartItem(
167                 this,
168                 this.itemdef = def,
169                 this.respawntime, // defaultrespawntime
170                 this.respawntimejitter // defaultrespawntimejitter
171         );
172         #if 0 // WEAPONTODO
173         if (this.modelindex) { // don't precache if this was removed
174                 wpn.wr_init(wpn);
175         }
176         #endif
177 }