3 int autocvar_g_balance_nix_ammo_cells;
4 int autocvar_g_balance_nix_ammo_plasma;
5 int autocvar_g_balance_nix_ammo_fuel;
6 int autocvar_g_balance_nix_ammo_nails;
7 int autocvar_g_balance_nix_ammo_rockets;
8 int autocvar_g_balance_nix_ammo_shells;
9 int autocvar_g_balance_nix_ammoincr_cells;
10 int autocvar_g_balance_nix_ammoincr_plasma;
11 int autocvar_g_balance_nix_ammoincr_fuel;
12 int autocvar_g_balance_nix_ammoincr_nails;
13 int autocvar_g_balance_nix_ammoincr_rockets;
14 int autocvar_g_balance_nix_ammoincr_shells;
15 float autocvar_g_balance_nix_incrtime;
16 float autocvar_g_balance_nix_roundtime;
17 bool autocvar_g_nix_with_healtharmor;
18 bool autocvar_g_nix_with_blaster;
19 bool autocvar_g_nix_with_powerups;
20 int autocvar_g_pickup_cells_max;
21 int autocvar_g_pickup_plasma_max;
22 int autocvar_g_pickup_fuel_max;
23 int autocvar_g_pickup_nails_max;
24 int autocvar_g_pickup_rockets_max;
25 int autocvar_g_pickup_shells_max;
27 float g_nix_with_blaster;
32 .float nix_lastchange_id;
33 .float nix_lastinfotime;
36 bool NIX_CanChooseWeapon(int wpn);
38 REGISTER_MUTATOR(nix, cvar("g_nix") && !cvar("g_instagib") && !cvar("g_overkill"))
42 g_nix_with_blaster = autocvar_g_nix_with_blaster;
47 FOREACH(Weapons, it != WEP_Null && NIX_CanChooseWeapon(it.m_id), { it.wr_init(it); });
50 MUTATOR_ONROLLBACK_OR_REMOVE
52 // nothing to roll back
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 SetResourceAmount(it, RESOURCE_SHELLS, start_ammo_shells);
60 SetResourceAmount(it, RESOURCE_BULLETS, start_ammo_nails);
61 SetResourceAmount(it, RESOURCE_ROCKETS, start_ammo_rockets);
62 SetResourceAmount(it, RESOURCE_CELLS, start_ammo_cells);
63 SetResourceAmount(it, RESOURCE_PLASMA, start_ammo_plasma);
64 SetResourceAmount(it, RESOURCE_FUEL, start_ammo_fuel);
65 it.weapons = start_weapons;
66 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
68 .entity weaponentity = weaponentities[slot];
69 if(it.(weaponentity).m_weapon == WEP_Null && slot != 0)
71 if(!client_hasweapon(it, it.(weaponentity).m_weapon, weaponentity, true, false))
72 it.(weaponentity).m_switchweapon = w_getbestweapon(it, weaponentity);
80 bool NIX_CanChooseWeapon(int wpn)
82 entity e = Weapons_from(wpn);
83 if (e == WEP_Null) return false; // skip dummies
86 if(!(g_weaponarena_weapons & e.m_wepset))
91 if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster)
93 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
95 if (!(e.spawnflags & WEP_FLAG_NORMAL))
100 void NIX_ChooseNextWeapon()
102 RandomSelection_Init();
103 FOREACH(Weapons, it != WEP_Null, {
104 if(NIX_CanChooseWeapon(it.m_id))
105 RandomSelection_AddFloat(it.m_id, 1, (it.m_id != nix_weapon));
107 nix_nextweapon = RandomSelection_chosen_float;
110 void NIX_GiveCurrentWeapon(entity this)
115 NIX_ChooseNextWeapon();
117 dt = ceil(nix_nextchange - time);
121 nix_weapon = nix_nextweapon;
123 if (!nix_nextchange) // no round played yet?
124 nix_nextchange = time; // start the first round now!
126 nix_nextchange = time + autocvar_g_balance_nix_roundtime;
127 // Weapon w = Weapons_from(nix_weapon);
128 // w.wr_init(w); // forget it, too slow
132 entity e = Weapons_from(nix_weapon);
134 if(nix_nextchange != this.nix_lastchange_id) // this shall only be called once per round!
136 SetResourceAmount(this, RESOURCE_SHELLS, 0);
137 SetResourceAmount(this, RESOURCE_BULLETS, 0);
138 SetResourceAmount(this, RESOURCE_ROCKETS, 0);
139 SetResourceAmount(this, RESOURCE_CELLS, 0);
140 SetResourceAmount(this, RESOURCE_PLASMA, 0);
141 SetResourceAmount(this, RESOURCE_FUEL, 0);
142 if(this.items & IT_UNLIMITED_WEAPON_AMMO)
146 case ammo_shells: SetResourceAmount(this, RESOURCE_SHELLS, autocvar_g_pickup_shells_max); break;
147 case ammo_nails: SetResourceAmount(this, RESOURCE_BULLETS, autocvar_g_pickup_nails_max); break;
148 case ammo_rockets: SetResourceAmount(this, RESOURCE_ROCKETS, autocvar_g_pickup_rockets_max); break;
149 case ammo_cells: SetResourceAmount(this, RESOURCE_CELLS, autocvar_g_pickup_cells_max); break;
150 case ammo_plasma: SetResourceAmount(this, RESOURCE_PLASMA, autocvar_g_pickup_plasma_max); break;
151 case ammo_fuel: SetResourceAmount(this, RESOURCE_FUEL, autocvar_g_pickup_fuel_max); break;
158 case ammo_shells: SetResourceAmount(this, RESOURCE_SHELLS, autocvar_g_balance_nix_ammo_shells); break;
159 case ammo_nails: SetResourceAmount(this, RESOURCE_BULLETS, autocvar_g_balance_nix_ammo_nails); break;
160 case ammo_rockets: SetResourceAmount(this, RESOURCE_ROCKETS, autocvar_g_balance_nix_ammo_rockets); break;
161 case ammo_cells: SetResourceAmount(this, RESOURCE_CELLS, autocvar_g_balance_nix_ammo_cells); break;
162 case ammo_plasma: SetResourceAmount(this, RESOURCE_PLASMA, autocvar_g_balance_nix_ammo_plasma); break;
163 case ammo_fuel: SetResourceAmount(this, RESOURCE_FUEL, autocvar_g_balance_nix_ammo_fuel); break;
167 this.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
168 if(dt >= 1 && dt <= 5)
169 this.nix_lastinfotime = -42;
171 Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
173 e.wr_resetplayer(e, this);
175 // all weapons must be fully loaded when we spawn
176 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
178 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
180 .entity weaponentity = weaponentities[slot];
181 this.(weaponentity).(weapon_load[nix_weapon]) = e.reloading_ammo;
186 if(WEP_CVAR(vortex, charge))
188 if(WEP_CVAR_SEC(vortex, chargepool))
189 this.vortex_chargepool_ammo = 1;
190 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
192 .entity weaponentity = weaponentities[slot];
193 this.(weaponentity).vortex_charge = WEP_CVAR(vortex, charge_start);
197 // set last change info
198 this.nix_lastchange_id = nix_nextchange;
200 if(this.nix_lastinfotime != dt)
202 this.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
203 if(dt >= 1 && dt <= 5)
204 Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
207 if(!(this.items & IT_UNLIMITED_WEAPON_AMMO) && time > this.nix_nextincr)
211 case ammo_shells: GiveResource(this, RESOURCE_SHELLS, autocvar_g_balance_nix_ammoincr_shells); break;
212 case ammo_nails: GiveResource(this, RESOURCE_BULLETS, autocvar_g_balance_nix_ammoincr_nails); break;
213 case ammo_rockets: GiveResource(this, RESOURCE_ROCKETS, autocvar_g_balance_nix_ammoincr_rockets); break;
214 case ammo_cells: GiveResource(this, RESOURCE_CELLS, autocvar_g_balance_nix_ammoincr_cells); break;
215 case ammo_plasma: GiveResource(this, RESOURCE_PLASMA, autocvar_g_balance_nix_ammoincr_plasma); break;
216 case ammo_fuel: GiveResource(this, RESOURCE_FUEL, autocvar_g_balance_nix_ammoincr_fuel); break;
219 this.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
222 this.weapons = '0 0 0';
223 if(g_nix_with_blaster)
224 this.weapons |= WEPSET(BLASTER);
225 this.weapons |= e.m_wepset;
227 Weapon w = Weapons_from(nix_weapon);
228 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
230 .entity weaponentity = weaponentities[slot];
231 if(this.(weaponentity).m_weapon == WEP_Null && slot != 0)
234 if(this.(weaponentity).m_switchweapon != w)
235 if(!client_hasweapon(this, this.(weaponentity).m_switchweapon, weaponentity, true, false))
237 if(client_hasweapon(this, w, weaponentity, true, false))
238 W_SwitchWeapon(this, w, weaponentity);
243 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
245 return true; // no throwing in NIX
248 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsString)
250 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":NIX");
253 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
255 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", NIX");
258 MUTATOR_HOOKFUNCTION(nix, FilterItem)
260 entity item = M_ARGV(0, entity);
262 if(item.itemdef.instanceOfHealth || item.itemdef.instanceOfArmor)
264 return !autocvar_g_nix_with_healtharmor;
266 else if(item.itemdef.instanceOfPowerup)
268 return !autocvar_g_nix_with_powerups;
271 return true; // delete all other items
274 MUTATOR_HOOKFUNCTION(nix, OnEntityPreSpawn)
276 entity ent = M_ARGV(0, entity);
278 if(ent.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
282 MUTATOR_HOOKFUNCTION(nix, PlayerPreThink)
284 entity player = M_ARGV(0, entity);
288 if(IS_PLAYER(player))
289 NIX_GiveCurrentWeapon(player);
292 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
294 entity player = M_ARGV(0, entity);
296 player.nix_lastchange_id = -1;
297 NIX_GiveCurrentWeapon(player); // overrides the weapons you got when spawning
298 player.items |= IT_UNLIMITED_SUPERWEAPONS;
301 MUTATOR_HOOKFUNCTION(nix, SetModname, CBC_ORDER_LAST)
303 M_ARGV(0, string) = "NIX";