]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
eb7f8f75b6bc48338f4fbf5b29e6100cc4599ba6
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nix.qc
1 #include "../_.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 && 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 {
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                 //WEP_ACTION(nix_weapon, WR_INIT); // forget it, too slow
64         }
65
66         // get weapon info
67         entity e = get_weaponinfo(nix_weapon);
68
69         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
70         {
71                 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0;
72
73                 if(self.items & IT_UNLIMITED_WEAPON_AMMO)
74                 {
75                         switch(e.ammo_field)
76                         {
77                                 case ammo_shells:  self.ammo_shells  = autocvar_g_pickup_shells_max;  break;
78                                 case ammo_nails:   self.ammo_nails   = autocvar_g_pickup_nails_max;   break;
79                                 case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break;
80                                 case ammo_cells:   self.ammo_cells   = autocvar_g_pickup_cells_max;   break;
81                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_pickup_plasma_max;   break;
82                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_pickup_fuel_max;    break;
83                         }
84                 }
85                 else
86                 {
87                         switch(e.ammo_field)
88                         {
89                                 case ammo_shells:  self.ammo_shells  = autocvar_g_balance_nix_ammo_shells;  break;
90                                 case ammo_nails:   self.ammo_nails   = autocvar_g_balance_nix_ammo_nails;   break;
91                                 case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
92                                 case ammo_cells:   self.ammo_cells   = autocvar_g_balance_nix_ammo_cells;   break;
93                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_balance_nix_ammo_plasma;   break;
94                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_balance_nix_ammo_fuel;    break;
95                         }
96                 }
97
98                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
99                 if(dt >= 1 && dt <= 5)
100                         self.nix_lastinfotime = -42;
101                 else
102                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
103
104                 WEP_ACTION(nix_weapon, WR_RESETPLAYER);
105
106                 // all weapons must be fully loaded when we spawn
107                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
108                         self.(weapon_load[nix_weapon]) = e.reloading_ammo;
109
110                 // vortex too
111                 if(WEP_CVAR(vortex, charge))
112                 {
113                         if(WEP_CVAR_SEC(vortex, chargepool))
114                                 self.vortex_chargepool_ammo = 1;
115                         self.vortex_charge = WEP_CVAR(vortex, charge_start);
116                 }
117
118                 // set last change info
119                 self.nix_lastchange_id = nix_nextchange;
120         }
121         if(self.nix_lastinfotime != dt)
122         {
123                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
124                 if(dt >= 1 && dt <= 5)
125                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
126         }
127
128         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
129         {
130                 switch(e.ammo_field)
131                 {
132                         case ammo_shells:  self.ammo_shells  += autocvar_g_balance_nix_ammoincr_shells;  break;
133                         case ammo_nails:   self.ammo_nails   += autocvar_g_balance_nix_ammoincr_nails;   break;
134                         case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
135                         case ammo_cells:   self.ammo_cells   += autocvar_g_balance_nix_ammoincr_cells;   break;
136                         case ammo_plasma:  self.ammo_plasma  += autocvar_g_balance_nix_ammoincr_plasma;   break;
137                         case ammo_fuel:    self.ammo_fuel    += autocvar_g_balance_nix_ammoincr_fuel;    break;
138                 }
139
140                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
141         }
142
143         self.weapons = '0 0 0';
144         if(g_nix_with_blaster)
145                 self.weapons |= WEPSET_BLASTER;
146         self.weapons |= WepSet_FromWeapon(nix_weapon);
147
148         if(self.switchweapon != nix_weapon)
149                 if(!client_hasweapon(self, self.switchweapon, true, false))
150                         if(client_hasweapon(self, nix_weapon, true, false))
151                                 W_SwitchWeapon(nix_weapon);
152 }
153
154 void NIX_precache()
155 {
156         float i;
157         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
158                 if (NIX_CanChooseWeapon(i))
159                         WEP_ACTION(i, WR_INIT);
160 }
161
162 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
163 {
164         return 1; // no throwing in NIX
165 }
166
167 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
168 {
169         ret_string = strcat(ret_string, ":NIX");
170         return 0;
171 }
172
173 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
174 {
175         ret_string = strcat(ret_string, ", NIX");
176         return 0;
177 }
178
179 MUTATOR_HOOKFUNCTION(nix_FilterItem)
180 {
181         switch (self.items)
182         {
183                 case IT_HEALTH:
184                 case IT_5HP:
185                 case IT_25HP:
186                 case IT_ARMOR:
187                 case IT_ARMOR_SHARD:
188                         if (autocvar_g_nix_with_healtharmor)
189                                 return 0;
190                         break;
191                 case IT_STRENGTH:
192                 case IT_INVINCIBLE:
193                         if (autocvar_g_nix_with_powerups)
194                                 return 0;
195                         break;
196         }
197
198         return 1; // delete all other items
199 }
200
201 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
202 {
203         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
204                 return 1;
205         return 0;
206 }
207
208 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
209 {
210         if(!intermission_running)
211         if(self.deadflag == DEAD_NO)
212         if(IS_PLAYER(self))
213                 NIX_GiveCurrentWeapon();
214         return 0;
215 }
216
217 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
218 {
219         self.nix_lastchange_id = -1;
220         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
221         self.items |= IT_UNLIMITED_SUPERWEAPONS;
222         return 0;
223 }
224
225 MUTATOR_HOOKFUNCTION(nix_SetModname)
226 {
227         modname = "NIX";
228         return 0;
229 }
230
231 MUTATOR_DEFINITION(mutator_nix)
232 {
233         entity e;
234
235         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
236         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
237         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
238         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
239         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
240         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
241         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
242         MUTATOR_HOOK(SetModname, nix_SetModname, CBC_ORDER_LAST);
243
244         MUTATOR_ONADD
245         {
246                 g_nix_with_blaster = autocvar_g_nix_with_blaster;
247
248                 nix_nextchange = 0;
249                 nix_nextweapon = 0;
250
251                 NIX_precache();
252         }
253
254         MUTATOR_ONROLLBACK_OR_REMOVE
255         {
256                 // nothing to roll back
257         }
258
259         MUTATOR_ONREMOVE
260         {
261                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
262
263                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
264                 {
265                         e.ammo_cells = start_ammo_cells;
266                         e.ammo_plasma = start_ammo_plasma;
267                         e.ammo_shells = start_ammo_shells;
268                         e.ammo_nails = start_ammo_nails;
269                         e.ammo_rockets = start_ammo_rockets;
270                         e.ammo_fuel = start_ammo_fuel;
271                         e.weapons = start_weapons;
272                         if(!client_hasweapon(e, e.weapon, true, false))
273                                 e.switchweapon = w_getbestweapon(self);
274                 }
275         }
276
277         return 0;
278 }