]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
Weapons: fix impulses
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nix.qc
1 #include "../_all.qh"
2
3 #include "mutator.qh"
4
5 float g_nix_with_blaster;
6 // WEAPONTODO
7 int nix_weapon;
8 float nix_nextchange;
9 float nix_nextweapon;
10 .float nix_lastchange_id;
11 .float nix_lastinfotime;
12 .float nix_nextincr;
13
14 float NIX_CanChooseWeapon(float wpn)
15 {
16         entity e;
17         e = get_weaponinfo(wpn);
18         if(!e.weapon) // skip dummies
19                 return false;
20         if(g_weaponarena)
21         {
22                 if(!(g_weaponarena_weapons & WepSet_FromWeapon(wpn)))
23                         return false;
24         }
25         else
26         {
27                 if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster) // WEAPONTODO: rename to g_nix_with_blaster
28                         return false;
29                 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
30                         return false;
31                 if (!(e.spawnflags & WEP_FLAG_NORMAL))
32                         return false;
33         }
34         return true;
35 }
36 void NIX_ChooseNextWeapon()
37 {
38         float j;
39         RandomSelection_Init();
40         for(j = WEP_FIRST; j <= WEP_LAST; ++j)
41                 if(NIX_CanChooseWeapon(j))
42                         RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
43         nix_nextweapon = RandomSelection_chosen_float;
44 }
45
46 void NIX_GiveCurrentWeapon()
47 {SELFPARAM();
48         float dt;
49
50         if(!nix_nextweapon)
51                 NIX_ChooseNextWeapon();
52
53         dt = ceil(nix_nextchange - time);
54
55         if(dt <= 0)
56         {
57                 nix_weapon = nix_nextweapon;
58                 nix_nextweapon = 0;
59                 if (!nix_nextchange) // no round played yet?
60                         nix_nextchange = time; // start the first round now!
61                 else
62                         nix_nextchange = time + autocvar_g_balance_nix_roundtime;
63                 // Weapon w = get_weaponinfo(nix_weapon);
64                 // w.wr_init(w); // forget it, too slow
65         }
66
67         // get weapon info
68         entity e = get_weaponinfo(nix_weapon);
69
70         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
71         {
72                 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0;
73
74                 if(self.items & IT_UNLIMITED_WEAPON_AMMO)
75                 {
76                         switch(e.ammo_field)
77                         {
78                                 case ammo_shells:  self.ammo_shells  = autocvar_g_pickup_shells_max;  break;
79                                 case ammo_nails:   self.ammo_nails   = autocvar_g_pickup_nails_max;   break;
80                                 case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break;
81                                 case ammo_cells:   self.ammo_cells   = autocvar_g_pickup_cells_max;   break;
82                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_pickup_plasma_max;   break;
83                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_pickup_fuel_max;    break;
84                         }
85                 }
86                 else
87                 {
88                         switch(e.ammo_field)
89                         {
90                                 case ammo_shells:  self.ammo_shells  = autocvar_g_balance_nix_ammo_shells;  break;
91                                 case ammo_nails:   self.ammo_nails   = autocvar_g_balance_nix_ammo_nails;   break;
92                                 case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
93                                 case ammo_cells:   self.ammo_cells   = autocvar_g_balance_nix_ammo_cells;   break;
94                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_balance_nix_ammo_plasma;   break;
95                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_balance_nix_ammo_fuel;    break;
96                         }
97                 }
98
99                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
100                 if(dt >= 1 && dt <= 5)
101                         self.nix_lastinfotime = -42;
102                 else
103                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
104
105                 Weapon w = get_weaponinfo(nix_weapon);
106                 w.wr_resetplayer(w);
107
108                 // all weapons must be fully loaded when we spawn
109                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
110                         self.(weapon_load[nix_weapon]) = e.reloading_ammo;
111
112                 // vortex too
113                 if(WEP_CVAR(vortex, charge))
114                 {
115                         if(WEP_CVAR_SEC(vortex, chargepool))
116                                 self.vortex_chargepool_ammo = 1;
117                         self.vortex_charge = WEP_CVAR(vortex, charge_start);
118                 }
119
120                 // set last change info
121                 self.nix_lastchange_id = nix_nextchange;
122         }
123         if(self.nix_lastinfotime != dt)
124         {
125                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
126                 if(dt >= 1 && dt <= 5)
127                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
128         }
129
130         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
131         {
132                 switch(e.ammo_field)
133                 {
134                         case ammo_shells:  self.ammo_shells  += autocvar_g_balance_nix_ammoincr_shells;  break;
135                         case ammo_nails:   self.ammo_nails   += autocvar_g_balance_nix_ammoincr_nails;   break;
136                         case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
137                         case ammo_cells:   self.ammo_cells   += autocvar_g_balance_nix_ammoincr_cells;   break;
138                         case ammo_plasma:  self.ammo_plasma  += autocvar_g_balance_nix_ammoincr_plasma;   break;
139                         case ammo_fuel:    self.ammo_fuel    += autocvar_g_balance_nix_ammoincr_fuel;    break;
140                 }
141
142                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
143         }
144
145         self.weapons = '0 0 0';
146         if(g_nix_with_blaster)
147                 self.weapons |= WEPSET(BLASTER);
148         self.weapons |= WepSet_FromWeapon(nix_weapon);
149
150         if(self.switchweapon != nix_weapon)
151                 if(!client_hasweapon(self, self.switchweapon, true, false))
152                         if(client_hasweapon(self, nix_weapon, true, false))
153                                 W_SwitchWeapon(nix_weapon);
154 }
155
156 void NIX_precache()
157 {
158         float i;
159         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
160                 if (NIX_CanChooseWeapon(i)) {
161                         Weapon w = get_weaponinfo(i);
162                         w.wr_init(w);
163                 }
164 }
165
166 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
167 {
168         return 1; // no throwing in NIX
169 }
170
171 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
172 {
173         ret_string = strcat(ret_string, ":NIX");
174         return 0;
175 }
176
177 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
178 {
179         ret_string = strcat(ret_string, ", NIX");
180         return 0;
181 }
182
183 MUTATOR_HOOKFUNCTION(nix_FilterItem)
184 {SELFPARAM();
185         switch (self.items)
186         {
187                 case ITEM_HealthSmall.m_itemid:
188                 case ITEM_HealthMedium.m_itemid:
189                 case ITEM_HealthLarge.m_itemid:
190                 case ITEM_HealthMega.m_itemid:
191                 case ITEM_ArmorSmall.m_itemid:
192                 case ITEM_ArmorMedium.m_itemid:
193                 case ITEM_ArmorLarge.m_itemid:
194                 case ITEM_ArmorMega.m_itemid:
195                         if (autocvar_g_nix_with_healtharmor)
196                                 return 0;
197                         break;
198                 case ITEM_Strength.m_itemid:
199                 case ITEM_Shield.m_itemid:
200                         if (autocvar_g_nix_with_powerups)
201                                 return 0;
202                         break;
203         }
204
205         return 1; // delete all other items
206 }
207
208 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
209 {SELFPARAM();
210         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
211                 return 1;
212         return 0;
213 }
214
215 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
216 {SELFPARAM();
217         if(!intermission_running)
218         if(self.deadflag == DEAD_NO)
219         if(IS_PLAYER(self))
220                 NIX_GiveCurrentWeapon();
221         return 0;
222 }
223
224 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
225 {SELFPARAM();
226         self.nix_lastchange_id = -1;
227         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
228         self.items |= IT_UNLIMITED_SUPERWEAPONS;
229         return 0;
230 }
231
232 MUTATOR_HOOKFUNCTION(nix_SetModname)
233 {
234         modname = "NIX";
235         return 0;
236 }
237
238 MUTATOR_DEFINITION(mutator_nix)
239 {SELFPARAM();
240         entity e;
241
242         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
243         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
244         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
245         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
246         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
247         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
248         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
249         MUTATOR_HOOK(SetModname, nix_SetModname, CBC_ORDER_LAST);
250
251         MUTATOR_ONADD
252         {
253                 g_nix_with_blaster = autocvar_g_nix_with_blaster;
254
255                 nix_nextchange = 0;
256                 nix_nextweapon = 0;
257
258                 NIX_precache();
259         }
260
261         MUTATOR_ONROLLBACK_OR_REMOVE
262         {
263                 // nothing to roll back
264         }
265
266         MUTATOR_ONREMOVE
267         {
268                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
269
270                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
271                 {
272                         e.ammo_cells = start_ammo_cells;
273                         e.ammo_plasma = start_ammo_plasma;
274                         e.ammo_shells = start_ammo_shells;
275                         e.ammo_nails = start_ammo_nails;
276                         e.ammo_rockets = start_ammo_rockets;
277                         e.ammo_fuel = start_ammo_fuel;
278                         e.weapons = start_weapons;
279                         if(!client_hasweapon(e, e.weapon, true, false))
280                                 e.switchweapon = w_getbestweapon(self);
281                 }
282         }
283
284         return 0;
285 }