]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
Merge remote-tracking branch 'origin/master' into fruitiex/animations
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nix.qc
1 float g_nix_with_laser;
2
3 float nix_weapon;
4 float nix_weapon_ammo;
5 float nix_nextchange;
6 float nix_nextweapon;
7 float nix_nextweapon_ammo;
8 .float nix_lastchange_id;
9 .float nix_lastinfotime;
10 .float nix_nextincr;
11
12 .float nix_save_cells;
13 .float nix_save_shells;
14 .float nix_save_nails;
15 .float nix_save_rockets;
16 .float nix_save_fuel;
17 .float nix_save_weapons;
18
19 float NIX_CanChooseWeapon(float wpn)
20 {
21         entity e;
22         e = get_weaponinfo(wpn);
23         if(!e.weapons) // skip dummies
24                 return FALSE;
25         if(g_weaponarena)
26         {
27                 if not(g_weaponarena & e.weapons)
28                         return FALSE;
29         }
30         else
31         {
32                 if(wpn == WEP_LASER && g_nix_with_laser)
33                         return FALSE;
34                 if not(e.spawnflags & WEP_FLAG_NORMAL)
35                         return FALSE;
36         }
37         return TRUE;
38 }
39 void NIX_ChooseNextWeapon()
40 {
41         float j;
42         RandomSelection_Init();
43         for(j = WEP_FIRST; j <= WEP_LAST; ++j)
44                 if(NIX_CanChooseWeapon(j))
45                         RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
46         nix_nextweapon = RandomSelection_chosen_float;
47         nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon);
48 }
49
50 void NIX_GiveCurrentWeapon()
51 {
52         float dt;
53
54         if(!nix_nextweapon)
55                 NIX_ChooseNextWeapon();
56
57         dt = ceil(nix_nextchange - time);
58
59         if(dt <= 0)
60         {
61                 nix_weapon = nix_nextweapon;
62                 nix_weapon_ammo = nix_nextweapon_ammo;
63                 nix_nextweapon = 0;
64                 if (!nix_nextchange) // no round played yet?
65                         nix_nextchange = time; // start the first round now!
66                 else
67                         nix_nextchange = time + autocvar_g_balance_nix_roundtime;
68                 //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow
69         }
70
71         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
72         {
73                 self.nix_lastchange_id = nix_nextchange;
74                 if (self.items & IT_UNLIMITED_WEAPON_AMMO)
75                 {
76                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
77                                 autocvar_g_pickup_shells_max : 0;
78                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
79                                 autocvar_g_pickup_nails_max : 0;
80                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
81                                 autocvar_g_pickup_rockets_max : 0;
82                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
83                                 autocvar_g_pickup_cells_max : 0;
84                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
85                                 autocvar_g_pickup_fuel_max : 0;
86                 }
87                 else
88                 {
89                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
90                                 autocvar_g_balance_nix_ammo_shells : 0;
91                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
92                                 autocvar_g_balance_nix_ammo_nails : 0;
93                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
94                                 autocvar_g_balance_nix_ammo_rockets : 0;
95                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
96                                 autocvar_g_balance_nix_ammo_cells : 0;
97                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
98                                 autocvar_g_balance_nix_ammo_fuel : 0;
99                 }
100                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
101                 if(dt >= 1 && dt <= 5)
102                         self.nix_lastinfotime = -42;
103                 else
104                         Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^2Active weapon: ^3", W_Name(nix_weapon)), 0, 0);
105
106                 weapon_action(nix_weapon, WR_RESETPLAYER);
107
108                 // all weapons must be fully loaded when we spawn
109                 entity e;
110                 e = get_weaponinfo(nix_weapon);
111                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
112                         self.weapon_load[nix_weapon] = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
113
114                 // nex too
115                 if(autocvar_g_balance_nex_charge)
116                 {
117                         if(autocvar_g_balance_nex_secondary_chargepool)
118                                 self.nex_chargepool_ammo = 1;
119                         self.nex_charge = autocvar_g_balance_nex_charge_start;
120                 }
121         }
122         if(self.nix_lastinfotime != dt)
123         {
124                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
125                 if(dt >= 1 && dt <= 5)
126                         Send_CSQC_Centerprint_Generic(self, CPID_NIX_WPNCHANGE, strcat("^3%d^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon)), 1, dt);
127         }
128
129         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
130         {
131                 if (nix_weapon_ammo & IT_SHELLS)
132                         self.ammo_shells = self.ammo_shells + autocvar_g_balance_nix_ammoincr_shells;
133                 else if (nix_weapon_ammo & IT_NAILS)
134                         self.ammo_nails = self.ammo_nails + autocvar_g_balance_nix_ammoincr_nails;
135                 else if (nix_weapon_ammo & IT_ROCKETS)
136                         self.ammo_rockets = self.ammo_rockets + autocvar_g_balance_nix_ammoincr_rockets;
137                 else if (nix_weapon_ammo & IT_CELLS)
138                         self.ammo_cells = self.ammo_cells + autocvar_g_balance_nix_ammoincr_cells;
139                 if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
140                         self.ammo_fuel = self.ammo_fuel + autocvar_g_balance_nix_ammoincr_fuel;
141                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
142         }
143
144         self.weapons = 0;
145         if(g_nix_with_laser)
146                 self.weapons = self.weapons | WEPBIT_LASER;
147         self.weapons = self.weapons | W_WeaponBit(nix_weapon);
148
149         if(self.switchweapon != nix_weapon)
150                 if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
151                         if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
152                                 W_SwitchWeapon(nix_weapon);
153 }
154
155 void NIX_precache()
156 {
157         float i;
158         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
159                 if (NIX_CanChooseWeapon(i))
160                         weapon_action(i, WR_PRECACHE);
161 }
162
163 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
164 {
165         return 1; // no throwing in NIX
166 }
167
168 MUTATOR_HOOKFUNCTION(nix_SetStartItems)
169 {
170         NIX_precache();
171         // we do NOT change the start weapons any more, so we can later turn off the mutator!
172         //   start_weapons = 0; // will be done later, when player spawns
173         //   warmup_start_weapons = 0; // will be done later, when player spawns
174         return 0;
175 }
176
177 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
178 {
179         ret_string = strcat(ret_string, ":NIX");
180         return 0;
181 }
182
183 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
184 {
185         ret_string = strcat(ret_string, ", NIX");
186         return 0;
187 }
188
189 MUTATOR_HOOKFUNCTION(nix_FilterItem)
190 {
191         switch (self.items)
192         {
193                 case IT_HEALTH:
194                 case IT_5HP:
195                 case IT_25HP:
196                 case IT_ARMOR:
197                 case IT_ARMOR_SHARD:
198                         if (autocvar_g_nix_with_healtharmor)
199                                 return 0;
200                         break;
201                 case IT_STRENGTH:
202                 case IT_INVINCIBLE:
203                         if (autocvar_g_nix_with_powerups)
204                                 return 0;
205                         break;
206         }
207
208         return 1; // delete all other items
209 }
210
211 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
212 {
213         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
214                 return 1;
215         return 0;
216 }
217
218 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
219 {
220         if(!intermission_running)
221         if(self.deadflag == DEAD_NO)
222         if(self.classname == "player")
223                 NIX_GiveCurrentWeapon();
224         return 0;
225 }
226
227 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
228 {
229         self.nix_lastchange_id = -1;
230         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
231         return 0;
232 }
233
234 MUTATOR_DEFINITION(mutator_nix)
235 {
236         entity e;
237
238         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
239         MUTATOR_HOOK(SetStartItems, nix_SetStartItems, CBC_ORDER_EXCLUSIVE);
240         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
241         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
242         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
243         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
244         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
245         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
246
247         MUTATOR_ONADD
248         {
249                 g_nix_with_laser = autocvar_g_nix_with_laser;
250
251                 nix_nextchange = 0;
252                 nix_nextweapon = 0;
253
254                 NIX_precache();
255
256                 FOR_EACH_PLAYER(e)
257                 {
258                         if(e.deadflag == DEAD_NO)
259                         {
260                                 e.nix_save_cells = e.ammo_cells;
261                                 e.nix_save_shells = e.ammo_shells;
262                                 e.nix_save_nails = e.ammo_nails;
263                                 e.nix_save_rockets = e.ammo_rockets;
264                                 e.nix_save_fuel = e.ammo_fuel;
265                                 e.nix_save_weapons = e.weapons;
266                         }
267                         else
268                         {
269                                 e.nix_save_cells = 0;
270                                 e.nix_save_shells = 0;
271                                 e.nix_save_nails = 0;
272                                 e.nix_save_rockets = 0;
273                                 e.nix_save_fuel = 0;
274                                 e.nix_save_weapons = 0;
275                         }
276                 }
277         }
278
279         MUTATOR_ONREMOVE
280         {
281                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
282
283                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
284                 {
285                         e.ammo_cells = max(start_ammo_cells, e.nix_save_cells);
286                         e.ammo_shells = max(start_ammo_shells, e.nix_save_shells);
287                         e.ammo_nails = max(start_ammo_nails, e.nix_save_nails);
288                         e.ammo_rockets = max(start_ammo_rockets, e.nix_save_rockets);
289                         e.ammo_fuel = max(start_ammo_fuel, e.nix_save_fuel);
290                         e.weapons = (start_weapons | e.nix_save_weapons);
291                         if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
292                                 e.switchweapon = w_getbestweapon(self);
293                 }
294         }
295
296         return 0;
297 }