]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
Merge remote branch 'origin/master' into samual/flyingspectators
[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                 nix_nextchange = time + autocvar_g_balance_nix_roundtime;
65                 //weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow
66         }
67         
68         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
69         {
70                 self.nix_lastchange_id = nix_nextchange;
71                 if (self.items & IT_UNLIMITED_WEAPON_AMMO)
72                 {
73                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
74                                 autocvar_g_pickup_shells_max : 0;
75                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
76                                 autocvar_g_pickup_nails_max : 0;
77                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
78                                 autocvar_g_pickup_rockets_max : 0;
79                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
80                                 autocvar_g_pickup_cells_max : 0;
81                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
82                                 autocvar_g_pickup_fuel_max : 0;
83                 }
84                 else
85                 {
86                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
87                                 autocvar_g_balance_nix_ammo_shells : 0;
88                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
89                                 autocvar_g_balance_nix_ammo_nails : 0;
90                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
91                                 autocvar_g_balance_nix_ammo_rockets : 0;
92                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
93                                 autocvar_g_balance_nix_ammo_cells : 0;
94                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
95                                 autocvar_g_balance_nix_ammo_fuel : 0;
96                 }
97                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
98                 if(dt >= 1 && dt <= 5)
99                         self.nix_lastinfotime = -42;
100                 else
101                         centerprint(self, strcat("\n\n^2Active weapon: ^3", W_Name(nix_weapon)));
102         }
103         if(self.nix_lastinfotime != dt)
104         {
105                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
106                 if(dt >= 1 && dt <= 5)
107                         centerprint(self, strcat("^3", ftos(dt), "^2 seconds until weapon change...\n\nNext weapon: ^3", W_Name(nix_nextweapon), "\n"));
108         }
109
110         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
111         {
112                 if (nix_weapon_ammo & IT_SHELLS)
113                         self.ammo_shells = self.ammo_shells + autocvar_g_balance_nix_ammoincr_shells;
114                 else if (nix_weapon_ammo & IT_NAILS)
115                         self.ammo_nails = self.ammo_nails + autocvar_g_balance_nix_ammoincr_nails;
116                 else if (nix_weapon_ammo & IT_ROCKETS)
117                         self.ammo_rockets = self.ammo_rockets + autocvar_g_balance_nix_ammoincr_rockets;
118                 else if (nix_weapon_ammo & IT_CELLS)
119                         self.ammo_cells = self.ammo_cells + autocvar_g_balance_nix_ammoincr_cells;
120                 if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
121                         self.ammo_fuel = self.ammo_fuel + autocvar_g_balance_nix_ammoincr_fuel;
122                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
123         }
124
125         self.weapons = 0;
126         if(g_nix_with_laser)
127                 self.weapons = self.weapons | WEPBIT_LASER;
128         self.weapons = self.weapons | W_WeaponBit(nix_weapon);
129
130         if(self.switchweapon != nix_weapon)
131                 if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
132                         if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
133                                 W_SwitchWeapon(nix_weapon);
134 }
135
136 void NIX_precache()
137 {
138         float i;
139         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
140                 if (NIX_CanChooseWeapon(i))
141                         weapon_action(i, WR_PRECACHE);
142 }
143
144 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
145 {
146         return 1; // no throwing in NIX
147 }
148
149 MUTATOR_HOOKFUNCTION(nix_SetStartItems)
150 {
151         NIX_precache();
152         // we do NOT change the start weapons any more, so we can later turn off the mutator!
153         //   start_weapons = 0; // will be done later, when player spawns
154         //   warmup_start_weapons = 0; // will be done later, when player spawns
155         return 0;
156 }
157
158 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
159 {
160         ret_string = strcat(ret_string, ":NIX");
161         return 0;
162 }
163
164 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
165 {
166         ret_string = strcat(ret_string, ", NIX");
167         return 0;
168 }
169
170 MUTATOR_HOOKFUNCTION(nix_FilterItem)
171 {
172         switch (self.items)
173         {
174                 case IT_HEALTH:
175                 case IT_5HP:
176                 case IT_25HP:
177                 case IT_ARMOR:
178                 case IT_ARMOR_SHARD:
179                         if (autocvar_g_nix_with_healtharmor)
180                                 return 0;
181                         break;
182                 case IT_STRENGTH:
183                 case IT_INVINCIBLE:
184                         if (autocvar_g_nix_with_powerups)
185                                 return 0;
186                         break;
187         }
188
189         return 1; // delete all other items
190 }
191
192 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
193 {
194         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
195                 return 1;
196         return 0;
197 }
198
199 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
200 {
201         if(!intermission_running)
202         if(self.deadflag == DEAD_NO)
203         if(self.classname == "player")
204                 NIX_GiveCurrentWeapon();
205         return 0;
206 }
207
208 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
209 {
210         self.nix_lastchange_id = -1;
211         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
212         return 0;
213 }
214
215 MUTATOR_DEFINITION(mutator_nix)
216 {
217         entity e;
218
219         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
220         MUTATOR_HOOK(SetStartItems, nix_SetStartItems, CBC_ORDER_EXCLUSIVE);
221         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
222         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
223         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
224         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
225         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
226         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
227
228         MUTATOR_ONADD
229         {
230                 g_nix_with_laser = autocvar_g_nix_with_laser;
231
232                 nix_nextchange = time;
233                 nix_nextweapon = 0;
234
235                 NIX_precache();
236
237                 FOR_EACH_PLAYER(e)
238                 {
239                         if(e.deadflag == DEAD_NO)
240                         {
241                                 e.nix_save_cells = e.ammo_cells;
242                                 e.nix_save_shells = e.ammo_shells;
243                                 e.nix_save_nails = e.ammo_nails;
244                                 e.nix_save_rockets = e.ammo_rockets;
245                                 e.nix_save_fuel = e.ammo_fuel;
246                                 e.nix_save_weapons = e.weapons;
247                         }
248                         else
249                         {
250                                 e.nix_save_cells = 0;
251                                 e.nix_save_shells = 0;
252                                 e.nix_save_nails = 0;
253                                 e.nix_save_rockets = 0;
254                                 e.nix_save_fuel = 0;
255                                 e.nix_save_weapons = 0;
256                         }
257                 }
258         }
259
260         MUTATOR_ONREMOVE
261         {
262                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
263
264                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
265                 {
266                         e.ammo_cells = max(start_ammo_cells, e.nix_save_cells);
267                         e.ammo_shells = max(start_ammo_shells, e.nix_save_shells);
268                         e.ammo_nails = max(start_ammo_nails, e.nix_save_nails);
269                         e.ammo_rockets = max(start_ammo_rockets, e.nix_save_rockets);
270                         e.ammo_fuel = max(start_ammo_fuel, e.nix_save_fuel);
271                         e.weapons = (start_weapons | e.nix_save_weapons);
272                         if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
273                                 e.switchweapon = w_getbestweapon(self);
274                 }
275         }
276
277         return 0;
278 }