Xonotic
sv_nix.qc
Go to the documentation of this file.
1 #include "sv_nix.qh"
2 
4 #include <server/world.qh>
5 
6 //string autocvar_g_nix;
30 
32 // WEAPONTODO
38 .float nix_nextincr;
39 
40 bool NIX_CanChooseWeapon(int wpn);
41 
43 {
45  {
47 
48  nix_nextchange = 0;
49  nix_nextweapon = 0;
50 
51  FOREACH(Weapons, it != WEP_Null && NIX_CanChooseWeapon(it.m_id), { it.wr_init(it); });
52  }
53 
55  {
56  // nothing to roll back
57  }
58 
60  {
61  // as the PlayerSpawn hook will no longer run, NIX is turned off by this!
62  FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), {
63  SetResource(it, RES_SHELLS, start_ammo_shells);
64  SetResource(it, RES_BULLETS, start_ammo_nails);
65  SetResource(it, RES_ROCKETS, start_ammo_rockets);
66  SetResource(it, RES_CELLS, start_ammo_cells);
67  SetResource(it, RES_PLASMA, start_ammo_plasma);
68  SetResource(it, RES_FUEL, start_ammo_fuel);
69  STAT(WEAPONS, it) = start_weapons;
70  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
71  {
72  .entity weaponentity = weaponentities[slot];
73  if(it.(weaponentity).m_weapon == WEP_Null && slot != 0)
74  continue;
75  if(!client_hasweapon(it, it.(weaponentity).m_weapon, weaponentity, true, false))
76  it.(weaponentity).m_switchweapon = w_getbestweapon(it, weaponentity);
77  }
78  });
79  }
80 
81  return false;
82 }
83 
84 bool NIX_CanChooseWeapon(int wpn)
85 {
86  entity e = REGISTRY_GET(Weapons, wpn);
87  if (e == WEP_Null) return false; // skip dummies
88  if(g_weaponarena)
89  {
90  if(!(g_weaponarena_weapons & e.m_wepset))
91  return false;
92  }
93  else
94  {
95  if(wpn == WEP_BLASTER.m_id && g_nix_with_blaster)
96  return false;
97  if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
98  return false;
99  if (!(e.spawnflags & WEP_FLAG_NORMAL))
100  return false;
101  }
102  return true;
103 }
105 {
107  FOREACH(Weapons, it != WEP_Null, {
108  if(NIX_CanChooseWeapon(it.m_id))
109  RandomSelection_AddFloat(it.m_id, 1, (it.m_id != nix_weapon));
110  });
112 }
113 
115 {
116  float dt;
117 
118  if(!nix_nextweapon)
120 
121  dt = ceil(nix_nextchange - time);
122 
123  if(dt <= 0)
124  {
126  nix_nextweapon = 0;
127  if (!nix_nextchange) // no round played yet?
128  nix_nextchange = time; // start the first round now!
129  else
131  // Weapon w = REGISTRY_GET(Weapons, nix_weapon);
132  // w.wr_init(w); // forget it, too slow
133  }
134 
135  // get weapon info
136  entity wpn = REGISTRY_GET(Weapons, nix_weapon);
137 
138  // TODO: registry handles
139  if(nix_nextchange != this.nix_lastchange_id) // this shall only be called once per round!
140  {
141  SetResource(this, RES_SHELLS, 0);
142  SetResource(this, RES_BULLETS, 0);
143  SetResource(this, RES_ROCKETS, 0);
144  SetResource(this, RES_CELLS, 0);
145  SetResource(this, RES_PLASMA, 0);
146  SetResource(this, RES_FUEL, 0);
147  if(this.items & IT_UNLIMITED_AMMO)
148  {
149  switch (wpn.ammo_type)
150  {
151  case RES_SHELLS: SetResource(this, RES_SHELLS, autocvar_g_pickup_shells_max); break;
152  case RES_BULLETS: SetResource(this, RES_BULLETS, autocvar_g_pickup_nails_max); break;
153  case RES_ROCKETS: SetResource(this, RES_ROCKETS, autocvar_g_pickup_rockets_max); break;
154  case RES_CELLS: SetResource(this, RES_CELLS, autocvar_g_pickup_cells_max); break;
155  case RES_PLASMA: SetResource(this, RES_PLASMA, autocvar_g_pickup_plasma_max); break;
156  case RES_FUEL: SetResource(this, RES_FUEL, autocvar_g_pickup_fuel_max); break;
157  }
158  }
159  else
160  {
161  switch (wpn.ammo_type)
162  {
163  case RES_SHELLS: SetResource(this, RES_SHELLS, autocvar_g_balance_nix_ammo_shells); break;
164  case RES_BULLETS: SetResource(this, RES_BULLETS, autocvar_g_balance_nix_ammo_nails); break;
165  case RES_ROCKETS: SetResource(this, RES_ROCKETS, autocvar_g_balance_nix_ammo_rockets); break;
166  case RES_CELLS: SetResource(this, RES_CELLS, autocvar_g_balance_nix_ammo_cells); break;
167  case RES_PLASMA: SetResource(this, RES_PLASMA, autocvar_g_balance_nix_ammo_plasma); break;
168  case RES_FUEL: SetResource(this, RES_FUEL, autocvar_g_balance_nix_ammo_fuel); break;
169  }
170  }
171 
173  if(dt >= 1 && dt <= 5)
174  this.nix_lastinfotime = -42;
175  else
176  Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
177 
178  wpn.wr_resetplayer(wpn, this);
179 
180  // all weapons must be fully loaded when we spawn
181  if (wpn.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
182  {
183  for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
184  {
185  .entity weaponentity = weaponentities[slot];
186  this.(weaponentity).(weapon_load[nix_weapon]) = wpn.reloading_ammo;
187  }
188  }
189 
190  // set last change info
192  }
193  if(this.nix_lastinfotime != dt)
194  {
195  this.nix_lastinfotime = dt; // initial value 0 should count as "not seen"
196  if(dt >= 1 && dt <= 5)
197  Send_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CENTER_NIX_COUNTDOWN, nix_nextweapon, dt);
198  }
199 
200  if(!(this.items & IT_UNLIMITED_AMMO) && time > this.nix_nextincr)
201  {
202  switch (wpn.ammo_type)
203  {
204  case RES_SHELLS: GiveResource(this, RES_SHELLS, autocvar_g_balance_nix_ammoincr_shells); break;
205  case RES_BULLETS: GiveResource(this, RES_BULLETS, autocvar_g_balance_nix_ammoincr_nails); break;
206  case RES_ROCKETS: GiveResource(this, RES_ROCKETS, autocvar_g_balance_nix_ammoincr_rockets); break;
207  case RES_CELLS: GiveResource(this, RES_CELLS, autocvar_g_balance_nix_ammoincr_cells); break;
208  case RES_PLASMA: GiveResource(this, RES_PLASMA, autocvar_g_balance_nix_ammoincr_plasma); break;
209  case RES_FUEL: GiveResource(this, RES_FUEL, autocvar_g_balance_nix_ammoincr_fuel); break;
210  }
211 
213  }
214 
215  STAT(WEAPONS, this) = '0 0 0';
217  STAT(WEAPONS, this) |= WEPSET(BLASTER);
218  STAT(WEAPONS, this) |= wpn.m_wepset;
219 
220  for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
221  {
222  .entity weaponentity = weaponentities[slot];
223  if (this.(weaponentity).m_weapon == WEP_Null && slot != 0)
224  continue;
225 
226  if (this.(weaponentity).m_switchweapon != wpn)
227  if (!client_hasweapon(this, this.(weaponentity).m_switchweapon, weaponentity, true, false))
228  {
229  if (client_hasweapon(this, wpn, weaponentity, true, false))
230  W_SwitchWeapon(this, wpn, weaponentity);
231  }
232  }
233 }
234 
235 MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
236 {
237  return true; // no throwing in NIX
238 }
239 
240 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsString)
241 {
242  M_ARGV(0, string) = strcat(M_ARGV(0, string), ":NIX");
243 }
244 
245 MUTATOR_HOOKFUNCTION(nix, BuildMutatorsPrettyString)
246 {
247  M_ARGV(0, string) = strcat(M_ARGV(0, string), ", NIX");
248 }
249 
250 MUTATOR_HOOKFUNCTION(nix, FilterItemDefinition)
251 {
252  entity definition = M_ARGV(0, entity);
253 
254  if (definition.instanceOfHealth || definition.instanceOfArmor)
255  {
257  }
258  else if (definition.instanceOfPowerup)
259  {
261  }
262 
263  return true; // delete all other items
264 }
265 
266 MUTATOR_HOOKFUNCTION(nix, OnEntityPreSpawn)
267 {
268  entity ent = M_ARGV(0, entity);
269 
270  if(ent.classname == "target_items") // items triggers cannot work in nix (as they change weapons/ammo)
271  return true;
272 }
273 
275 {
276  entity player = M_ARGV(0, entity);
277 
278  if(!game_stopped)
279  if(!IS_DEAD(player))
280  if(IS_PLAYER(player))
281  NIX_GiveCurrentWeapon(player);
282 }
283 
284 MUTATOR_HOOKFUNCTION(nix, ForbidRandomStartWeapons)
285 {
286  return true;
287 }
288 
289 MUTATOR_HOOKFUNCTION(nix, PlayerSpawn)
290 {
291  entity player = M_ARGV(0, entity);
292 
293  player.nix_lastchange_id = -1;
294  NIX_GiveCurrentWeapon(player); // overrides the weapons you got when spawning
295  player.items |= IT_UNLIMITED_SUPERWEAPONS;
296 }
297 
299 {
300  M_ARGV(0, string) = "NIX";
301 }
int autocvar_g_balance_nix_ammoincr_rockets
Definition: sv_nix.qc:17
#define WEPSET(id)
Definition: all.qh:37
float start_ammo_rockets
Definition: world.qh:87
float weapon_load[REGISTRY_MAX(Weapons)]
Definition: weaponsystem.qh:29
int autocvar_g_balance_nix_ammoincr_cells
Definition: sv_nix.qc:13
const int WEP_FLAG_RELOADABLE
Definition: weapon.qh:201
float start_ammo_fuel
Definition: world.qh:90
WepSet start_weapons
Definition: world.qh:81
#define w_getbestweapon(ent, wepent)
Definition: selection.qh:23
int autocvar_g_balance_nix_ammo_shells
Definition: sv_nix.qc:12
ERASEABLE void RandomSelection_Init()
Definition: random.qc:4
int autocvar_g_balance_nix_ammo_plasma
Definition: sv_nix.qc:8
entity() spawn
int autocvar_g_pickup_fuel_max
Definition: sv_nix.qc:26
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
float nix_lastchange_id
Definition: sv_nix.qc:36
#define FOREACH_CLIENT(cond, body)
Definition: utils.qh:49
int autocvar_g_balance_nix_ammoincr_plasma
Definition: sv_nix.qc:14
Gametype MapInfo_LoadedGametype
Definition: mapinfo.qh:193
int nix_weapon
Definition: sv_nix.qc:33
float autocvar_g_balance_nix_roundtime
Definition: sv_nix.qc:20
float autocvar_g_balance_nix_incrtime
Definition: sv_nix.qc:19
float RandomSelection_chosen_float
Definition: random.qh:6
float start_ammo_shells
Definition: world.qh:85
bool NIX_CanChooseWeapon(int wpn)
Definition: sv_nix.qc:84
bool autocvar_g_nix_with_healtharmor
Definition: sv_nix.qc:21
int autocvar_g_pickup_rockets_max
Definition: sv_nix.qc:28
int autocvar_g_pickup_shells_max
Definition: sv_nix.qc:29
float g_nix_with_blaster
Definition: sv_nix.qc:31
float nix_nextchange
Definition: sv_nix.qc:34
void PlayerPreThink(entity this)
Definition: client.qc:2402
int autocvar_g_balance_nix_ammoincr_shells
Definition: sv_nix.qc:18
REGISTER_MUTATOR(nix, expr_evaluate(cvar_string("g_nix")) &&!MUTATOR_IS_ENABLED(mutator_instagib) &&!MUTATOR_IS_ENABLED(ok) &&!MapInfo_LoadedGametype.m_weaponarena)
Definition: sv_nix.qc:42
void NIX_GiveCurrentWeapon(entity this)
Definition: sv_nix.qc:114
#define MUTATOR_ONROLLBACK_OR_REMOVE
Definition: base.qh:286
int autocvar_g_balance_nix_ammo_cells
Definition: sv_nix.qc:7
#define MUTATOR_IS_ENABLED(this)
Definition: base.qh:176
const int CBC_ORDER_LAST
Definition: base.qh:8
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
Definition: cl_resources.qc:26
float nix_nextweapon
Definition: sv_nix.qc:35
spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 spree_cen s1 f1 s1 strcat(_("Level %s: "), "^BG%s\3\, _("^BGPress ^F2%s^BG to enter the game"))
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
float start_ammo_cells
Definition: world.qh:88
float nix_nextincr
Definition: sv_nix.qc:38
int autocvar_g_balance_nix_ammoincr_nails
Definition: sv_nix.qc:16
int autocvar_g_balance_nix_ammo_rockets
Definition: sv_nix.qc:11
#define M_ARGV(x, type)
Definition: events.qh:17
#define IS_DEAD(s)
Definition: utils.qh:26
int autocvar_g_pickup_nails_max
Definition: sv_nix.qc:27
int autocvar_g_balance_nix_ammo_nails
Definition: sv_nix.qc:10
bool m_weaponarena
does this gametype enforce its own weapon arena?
Definition: mapinfo.qh:46
void GiveResource(entity receiver, Resource res_type, float amount)
Gives an entity some resource.
int autocvar_g_balance_nix_ammoincr_fuel
Definition: sv_nix.qc:15
#define MUTATOR_ONREMOVE
Definition: base.qh:285
bool autocvar_g_nix_with_blaster
Definition: sv_nix.qc:22
#define RandomSelection_AddFloat(f, weight, priority)
Definition: random.qh:15
float items
Definition: progsdefs.qc:145
int autocvar_g_pickup_cells_max
Definition: sv_nix.qc:24
void NIX_ChooseNextWeapon()
Definition: sv_nix.qc:104
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:272
float start_ammo_nails
Definition: world.qh:86
bool autocvar_g_nix_with_powerups
Definition: sv_nix.qc:23
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
MUTATOR_HOOKFUNCTION(nix, ForbidThrowCurrentWeapon)
Definition: sv_nix.qc:235
const int WEP_FLAG_NORMAL
Definition: weapon.qh:199
const int WEP_FLAG_MUTATORBLOCKED
Definition: weapon.qh:203
#define MUTATOR_ONADD
Definition: base.qh:284
int autocvar_g_pickup_plasma_max
Definition: sv_nix.qc:25
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
Definition: selection.qc:48
float time
Definition: csprogsdefs.qc:16
int autocvar_g_balance_nix_ammo_fuel
Definition: sv_nix.qc:9
float nix_lastinfotime
Definition: sv_nix.qc:37
float start_ammo_plasma
Definition: world.qh:89
#define FOREACH(list, cond, body)
Definition: iter.qh:19
WepSet g_weaponarena_weapons
Definition: world.qh:77
#define IS_PLAYER(v)
Definition: utils.qh:9
ERASEABLE bool expr_evaluate(string s)
Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
Definition: cvar.qh:48
float g_weaponarena
Definition: world.qh:76