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;
26 float g_nix_with_blaster;
31 .float nix_lastchange_id;
32 .float nix_lastinfotime;
35 bool NIX_CanChooseWeapon(int wpn);
37 REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"))
41 g_nix_with_blaster = autocvar_g_nix_with_blaster;
46 for (int i = WEP_FIRST; i <= WEP_LAST; ++i)
47 if (NIX_CanChooseWeapon(i)) {
48 Weapon w = Weapons_from(i);
53 MUTATOR_ONROLLBACK_OR_REMOVE
55 // nothing to roll back
60 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
62 FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
64 e.ammo_cells = start_ammo_cells;
65 e.ammo_plasma = start_ammo_plasma;
66 e.ammo_shells = start_ammo_shells;
67 e.ammo_nails = start_ammo_nails;
68 e.ammo_rockets = start_ammo_rockets;
69 e.ammo_fuel = start_ammo_fuel;
70 e.weapons = start_weapons;
71 if(!client_hasweapon(e, Weapons_from(e.weapon), true, false))
72 PS(e).m_switchweapon = w_getbestweapon(self);
79 bool NIX_CanChooseWeapon(int wpn)
81 entity e = Weapons_from(wpn);
82 if (e == WEP_Null) return false; // skip dummies
85 if(!(g_weaponarena_weapons & e.m_wepset))
90 if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster)
92 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
94 if (!(e.spawnflags & WEP_FLAG_NORMAL))
99 void NIX_ChooseNextWeapon()
102 RandomSelection_Init();
103 for(j = WEP_FIRST; j <= WEP_LAST; ++j)
104 if(NIX_CanChooseWeapon(j))
105 RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
106 nix_nextweapon = RandomSelection_chosen_float;
109 void NIX_GiveCurrentWeapon()
114 NIX_ChooseNextWeapon();
116 dt = ceil(nix_nextchange - time);
120 nix_weapon = nix_nextweapon;
122 if (!nix_nextchange) // no round played yet?
123 nix_nextchange = time; // start the first round now!
125 nix_nextchange = time + autocvar_g_balance_nix_roundtime;
126 // Weapon w = Weapons_from(nix_weapon);
127 // w.wr_init(w); // forget it, too slow
131 entity e = Weapons_from(nix_weapon);
133 if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
135 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0;
137 if(self.items & IT_UNLIMITED_WEAPON_AMMO)
141 case ammo_shells: self.ammo_shells = autocvar_g_pickup_shells_max; break;
142 case ammo_nails: self.ammo_nails = autocvar_g_pickup_nails_max; break;
143 case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break;
144 case ammo_cells: self.ammo_cells = autocvar_g_pickup_cells_max; break;
145 case ammo_plasma: self.ammo_plasma = autocvar_g_pickup_plasma_max; break;
146 case ammo_fuel: self.ammo_fuel = autocvar_g_pickup_fuel_max; break;
153 case ammo_shells: self.ammo_shells = autocvar_g_balance_nix_ammo_shells; break;
154 case ammo_nails: self.ammo_nails = autocvar_g_balance_nix_ammo_nails; break;
155 case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
156 case ammo_cells: self.ammo_cells = autocvar_g_balance_nix_ammo_cells; break;
157 case ammo_plasma: self.ammo_plasma = autocvar_g_balance_nix_ammo_plasma; break;
158 case ammo_fuel: self.ammo_fuel = autocvar_g_balance_nix_ammo_fuel; break;
162 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
163 if(dt >= 1 && dt <= 5)
164 self.nix_lastinfotime = -42;
166 Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
170 // all weapons must be fully loaded when we spawn
171 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
172 self.(weapon_load[nix_weapon]) = e.reloading_ammo;
175 if(WEP_CVAR(vortex, charge))
177 if(WEP_CVAR_SEC(vortex, chargepool))
178 self.vortex_chargepool_ammo = 1;
179 self.vortex_charge = WEP_CVAR(vortex, charge_start);
182 // set last change info
183 self.nix_lastchange_id = nix_nextchange;
185 if(self.nix_lastinfotime != dt)
187 self.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
188 if(dt >= 1 && dt <= 5)
189 Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
192 if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
196 case ammo_shells: self.ammo_shells += autocvar_g_balance_nix_ammoincr_shells; break;
197 case ammo_nails: self.ammo_nails += autocvar_g_balance_nix_ammoincr_nails; break;
198 case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
199 case ammo_cells: self.ammo_cells += autocvar_g_balance_nix_ammoincr_cells; break;
200 case ammo_plasma: self.ammo_plasma += autocvar_g_balance_nix_ammoincr_plasma; break;
201 case ammo_fuel: self.ammo_fuel += autocvar_g_balance_nix_ammoincr_fuel; break;
204 self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
207 self.weapons = '0 0 0';
208 if(g_nix_with_blaster)
209 self.weapons |= WEPSET(BLASTER);
210 self.weapons |= e.m_wepset;
212 Weapon w = Weapons_from(nix_weapon);
213 if(PS(self).m_switchweapon != w)
214 if(!client_hasweapon(self, PS(self).m_switchweapon, true, false))
216 if(client_hasweapon(self, w, true, false))
221 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
223 return 1; // no throwing in NIX
226 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsString)
228 ret_string = strcat(ret_string, ":NIX");
232 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
234 ret_string = strcat(ret_string, ", NIX");
238 MUTATOR_HOOKFUNCTION(nix, FilterItem)
242 case ITEM_HealthSmall.m_itemid:
243 case ITEM_HealthMedium.m_itemid:
244 case ITEM_HealthLarge.m_itemid:
245 case ITEM_HealthMega.m_itemid:
246 case ITEM_ArmorSmall.m_itemid:
247 case ITEM_ArmorMedium.m_itemid:
248 case ITEM_ArmorLarge.m_itemid:
249 case ITEM_ArmorMega.m_itemid:
250 if (autocvar_g_nix_with_healtharmor)
253 case ITEM_Strength.m_itemid:
254 case ITEM_Shield.m_itemid:
255 if (autocvar_g_nix_with_powerups)
260 return 1; // delete all other items
263 MUTATOR_HOOKFUNCTION(nix, OnEntityPreSpawn)
265 if(self.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
270 MUTATOR_HOOKFUNCTION(nix, PlayerPreThink)
272 if(!intermission_running)
273 if(self.deadflag == DEAD_NO)
275 NIX_GiveCurrentWeapon();
279 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
281 self.nix_lastchange_id = -1;
282 NIX_GiveCurrentWeapon(); // overrides the weapons you got when spawning
283 self.items |= IT_UNLIMITED_SUPERWEAPONS;
287 MUTATOR_HOOKFUNCTION(nix, SetModname, CBC_ORDER_LAST)