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 FOREACH(Weapons, it != WEP_Null && NIX_CanChooseWeapon(it.m_id), LAMBDA(it.wr_init(it)));
49 MUTATOR_ONROLLBACK_OR_REMOVE
51 // nothing to roll back
56 // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
57 FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), {
58 it.ammo_cells = start_ammo_cells;
59 it.ammo_plasma = start_ammo_plasma;
60 it.ammo_shells = start_ammo_shells;
61 it.ammo_nails = start_ammo_nails;
62 it.ammo_rockets = start_ammo_rockets;
63 it.ammo_fuel = start_ammo_fuel;
64 it.weapons = start_weapons;
65 if(!client_hasweapon(it, PS(it).m_weapon, true, false))
66 PS(it).m_switchweapon = w_getbestweapon(it);
71 bool NIX_CanChooseWeapon(int wpn)
73 entity e = Weapons_from(wpn);
74 if (e == WEP_Null) return false; // skip dummies
77 if(!(g_weaponarena_weapons & e.m_wepset))
82 if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster)
84 if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
86 if (!(e.spawnflags & WEP_FLAG_NORMAL))
91 void NIX_ChooseNextWeapon()
93 RandomSelection_Init();
94 FOREACH(Weapons, it != WEP_Null, LAMBDA(
95 if(NIX_CanChooseWeapon(it.m_id))
96 RandomSelection_Add(world, it.m_id, string_null, 1, (it.m_id != nix_weapon));
98 nix_nextweapon = RandomSelection_chosen_float;
101 void NIX_GiveCurrentWeapon(entity this)
106 NIX_ChooseNextWeapon();
108 dt = ceil(nix_nextchange - time);
112 nix_weapon = nix_nextweapon;
114 if (!nix_nextchange) // no round played yet?
115 nix_nextchange = time; // start the first round now!
117 nix_nextchange = time + autocvar_g_balance_nix_roundtime;
118 // Weapon w = Weapons_from(nix_weapon);
119 // w.wr_init(w); // forget it, too slow
123 entity e = Weapons_from(nix_weapon);
125 if(nix_nextchange != this.nix_lastchange_id) // this shall only be called once per round!
127 this.ammo_shells = this.ammo_nails = this.ammo_rockets = this.ammo_cells = this.ammo_plasma = this.ammo_fuel = 0;
129 if(this.items & IT_UNLIMITED_WEAPON_AMMO)
133 case ammo_shells: this.ammo_shells = autocvar_g_pickup_shells_max; break;
134 case ammo_nails: this.ammo_nails = autocvar_g_pickup_nails_max; break;
135 case ammo_rockets: this.ammo_rockets = autocvar_g_pickup_rockets_max; break;
136 case ammo_cells: this.ammo_cells = autocvar_g_pickup_cells_max; break;
137 case ammo_plasma: this.ammo_plasma = autocvar_g_pickup_plasma_max; break;
138 case ammo_fuel: this.ammo_fuel = autocvar_g_pickup_fuel_max; break;
145 case ammo_shells: this.ammo_shells = autocvar_g_balance_nix_ammo_shells; break;
146 case ammo_nails: this.ammo_nails = autocvar_g_balance_nix_ammo_nails; break;
147 case ammo_rockets: this.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
148 case ammo_cells: this.ammo_cells = autocvar_g_balance_nix_ammo_cells; break;
149 case ammo_plasma: this.ammo_plasma = autocvar_g_balance_nix_ammo_plasma; break;
150 case ammo_fuel: this.ammo_fuel = autocvar_g_balance_nix_ammo_fuel; break;
154 this.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
155 if(dt >= 1 && dt <= 5)
156 this.nix_lastinfotime = -42;
158 Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
160 e.wr_resetplayer(e, this);
162 // all weapons must be fully loaded when we spawn
163 if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
164 this.(weapon_load[nix_weapon]) = e.reloading_ammo;
167 if(WEP_CVAR(vortex, charge))
169 if(WEP_CVAR_SEC(vortex, chargepool))
170 this.vortex_chargepool_ammo = 1;
171 this.vortex_charge = WEP_CVAR(vortex, charge_start);
174 // set last change info
175 this.nix_lastchange_id = nix_nextchange;
177 if(this.nix_lastinfotime != dt)
179 this.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
180 if(dt >= 1 && dt <= 5)
181 Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
184 if(!(this.items & IT_UNLIMITED_WEAPON_AMMO) && time > this.nix_nextincr)
188 case ammo_shells: this.ammo_shells += autocvar_g_balance_nix_ammoincr_shells; break;
189 case ammo_nails: this.ammo_nails += autocvar_g_balance_nix_ammoincr_nails; break;
190 case ammo_rockets: this.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
191 case ammo_cells: this.ammo_cells += autocvar_g_balance_nix_ammoincr_cells; break;
192 case ammo_plasma: this.ammo_plasma += autocvar_g_balance_nix_ammoincr_plasma; break;
193 case ammo_fuel: this.ammo_fuel += autocvar_g_balance_nix_ammoincr_fuel; break;
196 this.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
199 this.weapons = '0 0 0';
200 if(g_nix_with_blaster)
201 this.weapons |= WEPSET(BLASTER);
202 this.weapons |= e.m_wepset;
204 Weapon w = Weapons_from(nix_weapon);
205 if(PS(this).m_switchweapon != w)
206 if(!client_hasweapon(this, PS(this).m_switchweapon, true, false))
208 if(client_hasweapon(this, w, true, false))
209 W_SwitchWeapon(this, w);
213 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
215 return true; // no throwing in NIX
218 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsString)
220 M_ARGV(0, string) = strcat(M_ARGV(0, string), ":NIX");
223 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
225 M_ARGV(0, string) = strcat(M_ARGV(0, string), ", NIX");
228 MUTATOR_HOOKFUNCTION(nix, FilterItem)
230 entity item = M_ARGV(0, entity);
234 case ITEM_HealthSmall.m_itemid:
235 case ITEM_HealthMedium.m_itemid:
236 case ITEM_HealthLarge.m_itemid:
237 case ITEM_HealthMega.m_itemid:
238 case ITEM_ArmorSmall.m_itemid:
239 case ITEM_ArmorMedium.m_itemid:
240 case ITEM_ArmorLarge.m_itemid:
241 case ITEM_ArmorMega.m_itemid:
242 if (autocvar_g_nix_with_healtharmor)
245 case ITEM_Strength.m_itemid:
246 case ITEM_Shield.m_itemid:
247 if (autocvar_g_nix_with_powerups)
252 return true; // delete all other items
255 MUTATOR_HOOKFUNCTION(nix, OnEntityPreSpawn)
257 entity ent = M_ARGV(0, entity);
259 if(ent.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
263 MUTATOR_HOOKFUNCTION(nix, PlayerPreThink)
265 entity player = M_ARGV(0, entity);
267 if(!intermission_running)
269 if(IS_PLAYER(player))
270 NIX_GiveCurrentWeapon(player);
273 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
275 entity player = M_ARGV(0, entity);
277 player.nix_lastchange_id = -1;
278 NIX_GiveCurrentWeapon(player); // overrides the weapons you got when spawning
279 player.items |= IT_UNLIMITED_SUPERWEAPONS;
282 MUTATOR_HOOKFUNCTION(nix, SetModname, CBC_ORDER_LAST)
284 M_ARGV(0, string) = "NIX";