]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/common/mutators/mutator/nix/nix.qc
Merge branch 'master' into terencehill/dynamic_hud
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / mutators / mutator / nix / nix.qc
1 #ifdef IMPLEMENTATION
2 int autocvar_g_balance_nix_ammo_cells;
3 int autocvar_g_balance_nix_ammo_plasma;
4 int autocvar_g_balance_nix_ammo_fuel;
5 int autocvar_g_balance_nix_ammo_nails;
6 int autocvar_g_balance_nix_ammo_rockets;
7 int autocvar_g_balance_nix_ammo_shells;
8 int autocvar_g_balance_nix_ammoincr_cells;
9 int autocvar_g_balance_nix_ammoincr_plasma;
10 int autocvar_g_balance_nix_ammoincr_fuel;
11 int autocvar_g_balance_nix_ammoincr_nails;
12 int autocvar_g_balance_nix_ammoincr_rockets;
13 int autocvar_g_balance_nix_ammoincr_shells;
14 float autocvar_g_balance_nix_incrtime;
15 float autocvar_g_balance_nix_roundtime;
16 bool autocvar_g_nix_with_healtharmor;
17 bool autocvar_g_nix_with_blaster;
18 bool autocvar_g_nix_with_powerups;
19 int autocvar_g_pickup_cells_max;
20 int autocvar_g_pickup_plasma_max;
21 int autocvar_g_pickup_fuel_max;
22 int autocvar_g_pickup_nails_max;
23 int autocvar_g_pickup_rockets_max;
24 int autocvar_g_pickup_shells_max;
25
26 float g_nix_with_blaster;
27 // WEAPONTODO
28 int nix_weapon;
29 float nix_nextchange;
30 float nix_nextweapon;
31 .float nix_lastchange_id;
32 .float nix_lastinfotime;
33 .float nix_nextincr;
34
35 bool NIX_CanChooseWeapon(int wpn);
36
37 REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"))
38 {
39     SELFPARAM();
40         MUTATOR_ONADD
41         {
42                 g_nix_with_blaster = autocvar_g_nix_with_blaster;
43
44                 nix_nextchange = 0;
45                 nix_nextweapon = 0;
46
47                 FOREACH(Weapons, it != WEP_Null && NIX_CanChooseWeapon(it.m_id), LAMBDA(it.wr_init(it)));
48         }
49
50         MUTATOR_ONROLLBACK_OR_REMOVE
51         {
52                 // nothing to roll back
53         }
54
55         MUTATOR_ONREMOVE
56         {
57                 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
58                 FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), {
59                         it.ammo_cells = start_ammo_cells;
60                         it.ammo_plasma = start_ammo_plasma;
61                         it.ammo_shells = start_ammo_shells;
62                         it.ammo_nails = start_ammo_nails;
63                         it.ammo_rockets = start_ammo_rockets;
64                         it.ammo_fuel = start_ammo_fuel;
65                         it.weapons = start_weapons;
66                         if(!client_hasweapon(it, PS(it).m_weapon, true, false))
67                                 PS(it).m_switchweapon = w_getbestweapon(self);
68                 });
69         }
70
71         return 0;
72 }
73
74 bool NIX_CanChooseWeapon(int wpn)
75 {
76         entity e = Weapons_from(wpn);
77         if (e == WEP_Null) return false; // skip dummies
78         if(g_weaponarena)
79         {
80                 if(!(g_weaponarena_weapons & e.m_wepset))
81                         return false;
82         }
83         else
84         {
85                 if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster)
86                         return false;
87                 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
88                         return false;
89                 if (!(e.spawnflags & WEP_FLAG_NORMAL))
90                         return false;
91         }
92         return true;
93 }
94 void NIX_ChooseNextWeapon()
95 {
96         RandomSelection_Init();
97         FOREACH(Weapons, it != WEP_Null, LAMBDA(
98                 if(NIX_CanChooseWeapon(it.m_id))
99                         RandomSelection_Add(world, it.m_id, string_null, 1, (it.m_id != nix_weapon));
100         ));
101         nix_nextweapon = RandomSelection_chosen_float;
102 }
103
104 void NIX_GiveCurrentWeapon()
105 {SELFPARAM();
106         float dt;
107
108         if(!nix_nextweapon)
109                 NIX_ChooseNextWeapon();
110
111         dt = ceil(nix_nextchange - time);
112
113         if(dt <= 0)
114         {
115                 nix_weapon = nix_nextweapon;
116                 nix_nextweapon = 0;
117                 if (!nix_nextchange) // no round played yet?
118                         nix_nextchange = time; // start the first round now!
119                 else
120                         nix_nextchange = time + autocvar_g_balance_nix_roundtime;
121                 // Weapon w = Weapons_from(nix_weapon);
122                 // w.wr_init(w); // forget it, too slow
123         }
124
125         // get weapon info
126         entity e = Weapons_from(nix_weapon);
127
128         if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
129         {
130                 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0;
131
132                 if(self.items & IT_UNLIMITED_WEAPON_AMMO)
133                 {
134                         switch(e.ammo_field)
135                         {
136                                 case ammo_shells:  self.ammo_shells  = autocvar_g_pickup_shells_max;  break;
137                                 case ammo_nails:   self.ammo_nails   = autocvar_g_pickup_nails_max;   break;
138                                 case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break;
139                                 case ammo_cells:   self.ammo_cells   = autocvar_g_pickup_cells_max;   break;
140                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_pickup_plasma_max;   break;
141                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_pickup_fuel_max;    break;
142                         }
143                 }
144                 else
145                 {
146                         switch(e.ammo_field)
147                         {
148                                 case ammo_shells:  self.ammo_shells  = autocvar_g_balance_nix_ammo_shells;  break;
149                                 case ammo_nails:   self.ammo_nails   = autocvar_g_balance_nix_ammo_nails;   break;
150                                 case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
151                                 case ammo_cells:   self.ammo_cells   = autocvar_g_balance_nix_ammo_cells;   break;
152                                 case ammo_plasma:  self.ammo_plasma  = autocvar_g_balance_nix_ammo_plasma;   break;
153                                 case ammo_fuel:    self.ammo_fuel    = autocvar_g_balance_nix_ammo_fuel;    break;
154                         }
155                 }
156
157                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
158                 if(dt >= 1 && dt <= 5)
159                         self.nix_lastinfotime = -42;
160                 else
161                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
162
163                 e.wr_resetplayer(e);
164
165                 // all weapons must be fully loaded when we spawn
166                 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
167                         self.(weapon_load[nix_weapon]) = e.reloading_ammo;
168
169                 // vortex too
170                 if(WEP_CVAR(vortex, charge))
171                 {
172                         if(WEP_CVAR_SEC(vortex, chargepool))
173                                 self.vortex_chargepool_ammo = 1;
174                         self.vortex_charge = WEP_CVAR(vortex, charge_start);
175                 }
176
177                 // set last change info
178                 self.nix_lastchange_id = nix_nextchange;
179         }
180         if(self.nix_lastinfotime != dt)
181         {
182                 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
183                 if(dt >= 1 && dt <= 5)
184                         Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
185         }
186
187         if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
188         {
189                 switch(e.ammo_field)
190                 {
191                         case ammo_shells:  self.ammo_shells  += autocvar_g_balance_nix_ammoincr_shells;  break;
192                         case ammo_nails:   self.ammo_nails   += autocvar_g_balance_nix_ammoincr_nails;   break;
193                         case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
194                         case ammo_cells:   self.ammo_cells   += autocvar_g_balance_nix_ammoincr_cells;   break;
195                         case ammo_plasma:  self.ammo_plasma  += autocvar_g_balance_nix_ammoincr_plasma;   break;
196                         case ammo_fuel:    self.ammo_fuel    += autocvar_g_balance_nix_ammoincr_fuel;    break;
197                 }
198
199                 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
200         }
201
202         self.weapons = '0 0 0';
203         if(g_nix_with_blaster)
204                 self.weapons |= WEPSET(BLASTER);
205         self.weapons |= e.m_wepset;
206
207     Weapon w = Weapons_from(nix_weapon);
208         if(PS(self).m_switchweapon != w)
209                 if(!client_hasweapon(self, PS(self).m_switchweapon, true, false))
210                 {
211                         if(client_hasweapon(self, w, true, false))
212                                 W_SwitchWeapon(w);
213                 }
214 }
215
216 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
217 {
218         return 1; // no throwing in NIX
219 }
220
221 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsString)
222 {
223         ret_string = strcat(ret_string, ":NIX");
224         return 0;
225 }
226
227 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
228 {
229         ret_string = strcat(ret_string, ", NIX");
230         return 0;
231 }
232
233 MUTATOR_HOOKFUNCTION(nix, FilterItem)
234 {SELFPARAM();
235         switch (self.items)
236         {
237                 case ITEM_HealthSmall.m_itemid:
238                 case ITEM_HealthMedium.m_itemid:
239                 case ITEM_HealthLarge.m_itemid:
240                 case ITEM_HealthMega.m_itemid:
241                 case ITEM_ArmorSmall.m_itemid:
242                 case ITEM_ArmorMedium.m_itemid:
243                 case ITEM_ArmorLarge.m_itemid:
244                 case ITEM_ArmorMega.m_itemid:
245                         if (autocvar_g_nix_with_healtharmor)
246                                 return 0;
247                         break;
248                 case ITEM_Strength.m_itemid:
249                 case ITEM_Shield.m_itemid:
250                         if (autocvar_g_nix_with_powerups)
251                                 return 0;
252                         break;
253         }
254
255         return 1; // delete all other items
256 }
257
258 MUTATOR_HOOKFUNCTION(nix, OnEntityPreSpawn)
259 {SELFPARAM();
260         if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
261                 return 1;
262         return 0;
263 }
264
265 MUTATOR_HOOKFUNCTION(nix, PlayerPreThink)
266 {SELFPARAM();
267         if(!intermission_running)
268         if(!IS_DEAD(self))
269         if(IS_PLAYER(self))
270                 NIX_GiveCurrentWeapon();
271         return 0;
272 }
273
274 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
275 {SELFPARAM();
276         self.nix_lastchange_id = -1;
277         NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
278         self.items |= IT_UNLIMITED_SUPERWEAPONS;
279         return 0;
280 }
281
282 MUTATOR_HOOKFUNCTION(nix, SetModname, CBC_ORDER_LAST)
283 {
284         modname = "NIX";
285         return 0;
286 }
287 #endif