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