]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/mutators/mutator_nix.qc
Add WEAPONTODO comments for some stuff I need to take care of later
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / mutators / mutator_nix.qc
1 float g_nix_with_laser;
2 // WEAPONTODO
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_CanChooseWeapon(float wpn)
13 {
14         entity e;
15         e = get_weaponinfo(wpn);
16         if(!e.weapon) // skip dummies
17                 return FALSE;
18         if(g_weaponarena)
19         {
20                 if not(WEPSET_CONTAINS_AW(g_weaponarena_weapons, wpn))
21                         return FALSE;
22         }
23         else
24         {
25                 if(wpn == WEP_LASER && g_nix_with_laser)
26                         return FALSE;
27                 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
28                         return FALSE;
29                 if not(e.spawnflags & WEP_FLAG_NORMAL)
30                         return FALSE;
31         }
32         return TRUE;
33 }
34 void NIX_ChooseNextWeapon()
35 {
36         float j;
37         RandomSelection_Init();
38         for(j = WEP_FIRST; j <= WEP_LAST; ++j)
39                 if(NIX_CanChooseWeapon(j))
40                         RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
41         nix_nextweapon = RandomSelection_chosen_float;
42         nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon);
43 }
44
45 void NIX_GiveCurrentWeapon()
46 {
47         float dt;
48
49         if(!nix_nextweapon)
50                 NIX_ChooseNextWeapon();
51
52         dt = ceil(nix_nextchange - time);
53
54         if(dt <= 0)
55         {
56                 nix_weapon = nix_nextweapon;
57                 nix_weapon_ammo = nix_nextweapon_ammo;
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_action(nix_weapon, WR_PRECACHE); // forget it, too slow
64         }
65
66         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
67         {
68                 self.nix_lastchange_id = nix_nextchange;
69                 if (self.items & IT_UNLIMITED_WEAPON_AMMO)
70                 {
71                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
72                                 autocvar_g_pickup_shells_max : 0;
73                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
74                                 autocvar_g_pickup_nails_max : 0;
75                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
76                                 autocvar_g_pickup_rockets_max : 0;
77                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
78                                 autocvar_g_pickup_cells_max : 0;
79                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
80                                 autocvar_g_pickup_fuel_max : 0;
81                 }
82                 else
83                 {
84                         self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
85                                 autocvar_g_balance_nix_ammo_shells : 0;
86                         self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
87                                 autocvar_g_balance_nix_ammo_nails : 0;
88                         self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
89                                 autocvar_g_balance_nix_ammo_rockets : 0;
90                         self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
91                                 autocvar_g_balance_nix_ammo_cells : 0;
92                         self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
93                                 autocvar_g_balance_nix_ammo_fuel : 0;
94                 }
95                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
96                 if(dt >= 1 && dt <= 5)
97                         self.nix_lastinfotime = -42;
98                 else
99                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
100
101                 weapon_action(nix_weapon, WR_RESETPLAYER);
102
103                 // all weapons must be fully loaded when we spawn
104                 entity e;
105                 e = get_weaponinfo(nix_weapon);
106                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
107                         self.(weapon_load[nix_weapon]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
108
109                 // nex too
110                 if(WEP_CVAR(nex, charge))
111                 {
112                         if(WEP_CVAR_SEC(nex, chargepool))
113                                 self.nex_chargepool_ammo = 1;
114                         self.nex_charge = WEP_CVAR(nex, charge_start);
115                 }
116         }
117         if(self.nix_lastinfotime != dt)
118         {
119                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
120                 if(dt >= 1 && dt <= 5)
121                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
122         }
123
124         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
125         {
126                 if (nix_weapon_ammo & IT_SHELLS)
127                         self.ammo_shells = self.ammo_shells + autocvar_g_balance_nix_ammoincr_shells;
128                 else if (nix_weapon_ammo & IT_NAILS)
129                         self.ammo_nails = self.ammo_nails + autocvar_g_balance_nix_ammoincr_nails;
130                 else if (nix_weapon_ammo & IT_ROCKETS)
131                         self.ammo_rockets = self.ammo_rockets + autocvar_g_balance_nix_ammoincr_rockets;
132                 else if (nix_weapon_ammo & IT_CELLS)
133                         self.ammo_cells = self.ammo_cells + autocvar_g_balance_nix_ammoincr_cells;
134                 if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
135                         self.ammo_fuel = self.ammo_fuel + autocvar_g_balance_nix_ammoincr_fuel;
136                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
137         }
138
139         WEPSET_CLEAR_E(self);
140         if(g_nix_with_laser)
141                 WEPSET_ANDNOT_EW(self, WEP_LASER);
142         WEPSET_OR_EW(self, nix_weapon);
143
144         if(self.switchweapon != nix_weapon)
145                 if(!client_hasweapon(self, self.switchweapon, TRUE, FALSE))
146                         if(client_hasweapon(self, nix_weapon, TRUE, FALSE))
147                                 W_SwitchWeapon(nix_weapon);
148 }
149
150 void NIX_precache()
151 {
152         float i;
153         for (i = WEP_FIRST; i <= WEP_LAST; ++i)
154                 if (NIX_CanChooseWeapon(i))
155                         weapon_action(i, WR_PRECACHE);
156 }
157
158 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
159 {
160         return 1; // no throwing in NIX
161 }
162
163 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsString)
164 {
165         ret_string = strcat(ret_string, ":NIX");
166         return 0;
167 }
168
169 MUTATOR_HOOKFUNCTION(nix_BuildMutatorsPrettyString)
170 {
171         ret_string = strcat(ret_string, ", NIX");
172         return 0;
173 }
174
175 MUTATOR_HOOKFUNCTION(nix_FilterItem)
176 {
177         switch (self.items)
178         {
179                 case IT_HEALTH:
180                 case IT_5HP:
181                 case IT_25HP:
182                 case IT_ARMOR:
183                 case IT_ARMOR_SHARD:
184                         if (autocvar_g_nix_with_healtharmor)
185                                 return 0;
186                         break;
187                 case IT_STRENGTH:
188                 case IT_INVINCIBLE:
189                         if (autocvar_g_nix_with_powerups)
190                                 return 0;
191                         break;
192         }
193
194         return 1; // delete all other items
195 }
196
197 MUTATOR_HOOKFUNCTION(nix_OnEntityPreSpawn)
198 {
199         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
200                 return 1;
201         return 0;
202 }
203
204 MUTATOR_HOOKFUNCTION(nix_PlayerPreThink)
205 {
206         if(!intermission_running)
207         if(self.deadflag == DEAD_NO)
208         if(IS_PLAYER(self))
209                 NIX_GiveCurrentWeapon();
210         return 0;
211 }
212
213 MUTATOR_HOOKFUNCTION(nix_PlayerSpawn)
214 {
215         self.nix_lastchange_id = -1;
216         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
217         self.items |= IT_UNLIMITED_SUPERWEAPONS;
218         return 0;
219 }
220
221 MUTATOR_HOOKFUNCTION(nix_SetModname)
222 {
223         modname = "NIX";
224         return 0;
225 }
226
227 MUTATOR_DEFINITION(mutator_nix)
228 {
229         entity e;
230
231         MUTATOR_HOOK(ForbidThrowCurrentWeapon, nix_ForbidThrowCurrentWeapon, CBC_ORDER_ANY);
232         MUTATOR_HOOK(BuildMutatorsString, nix_BuildMutatorsString, CBC_ORDER_ANY);
233         MUTATOR_HOOK(BuildMutatorsPrettyString, nix_BuildMutatorsPrettyString, CBC_ORDER_ANY);
234         MUTATOR_HOOK(FilterItem, nix_FilterItem, CBC_ORDER_ANY);
235         MUTATOR_HOOK(OnEntityPreSpawn, nix_OnEntityPreSpawn, CBC_ORDER_ANY);
236         MUTATOR_HOOK(PlayerPreThink, nix_PlayerPreThink, CBC_ORDER_ANY);
237         MUTATOR_HOOK(PlayerSpawn, nix_PlayerSpawn, CBC_ORDER_ANY);
238         MUTATOR_HOOK(SetModname, nix_SetModname, CBC_ORDER_LAST);
239
240         MUTATOR_ONADD
241         {
242                 g_nix_with_laser = autocvar_g_nix_with_laser;
243
244                 nix_nextchange = 0;
245                 nix_nextweapon = 0;
246
247                 NIX_precache();
248         }
249
250         MUTATOR_ONROLLBACK_OR_REMOVE
251         {
252                 // nothing to roll back
253         }
254
255         MUTATOR_ONREMOVE
256         {
257                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
258
259                 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
260                 {
261                         e.ammo_cells = start_ammo_cells;
262                         e.ammo_shells = start_ammo_shells;
263                         e.ammo_nails = start_ammo_nails;
264                         e.ammo_rockets = start_ammo_rockets;
265                         e.ammo_fuel = start_ammo_fuel;
266                         WEPSET_COPY_EA(e, start_weapons);
267                         if(!client_hasweapon(e, e.weapon, TRUE, FALSE))
268                                 e.switchweapon = w_getbestweapon(self);
269                 }
270         }
271
272         return 0;
273 }