Xonotic
selection.qh File Reference
+ Include dependency graph for selection.qh:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define w_getbestweapon(ent, wepent)   REGISTRY_GET(Weapons, W_GetCycleWeapon(ent, CS_CVAR(ent).cvar_cl_weaponpriority, 0, -1, false, true, wepent))
 

Functions

bool client_hasweapon (entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
 
void Send_WeaponComplain (entity e, float wpn, float type)
 
void W_CycleWeapon (entity this, string weaponorder, float dir,.entity weaponentity)
 
float W_GetCycleWeapon (entity this, string weaponorder, float dir, float imp, float complain, float skipmissing,.entity weaponentity)
 
void W_LastWeapon (entity this,.entity weaponentity)
 
void W_NextWeapon (entity this, float list,.entity weaponentity)
 
void W_NextWeaponOnImpulse (entity this, float imp,.entity weaponentity)
 
void W_PreviousWeapon (entity this, float list,.entity weaponentity)
 
void W_SwitchToOtherWeapon (entity this,.entity weaponentity)
 
bool W_SwitchWeapon (entity this, Weapon imp,.entity weaponentity)
 
void W_SwitchWeapon_Force (Player this, Weapon w,.entity weaponentity)
 
void W_SwitchWeapon_TryOthers (entity this, Weapon imp,.entity weaponentity)
 

Variables

int autocvar_g_showweaponspawns
 
bool autocvar_g_weaponswitch_debug
 
bool autocvar_g_weaponswitch_debug_alternate
 
WepSet dual_weapons
 
float hasweapon_complain_spam
 
int selectweapon
 
int weaponcomplainindex
 

Macro Definition Documentation

◆ w_getbestweapon

#define w_getbestweapon (   ent,
  wepent 
)    REGISTRY_GET(Weapons, W_GetCycleWeapon(ent, CS_CVAR(ent).cvar_cl_weaponpriority, 0, -1, false, true, wepent))

Function Documentation

◆ client_hasweapon()

bool client_hasweapon ( entity  this,
Weapon  wpn,
.entity  weaponentity,
float  andammo,
bool  complain 
)

Definition at line 48 of file selection.qc.

References autocvar_g_showweaponspawns, autocvar_g_weaponswitch_debug, CS(), dual_weapons, FOREACH, hasweapon_complain_spam, IL_EACH, Weapon::impulse, IS_REAL_CLIENT, items, Weapon::m_id, OFFHAND_HOOK, PS, Send_WeaponComplain(), SND, Weapon::spawnflags, sprint(), time, Weapon_whereis(), weaponslot(), WEP_FLAG_DUALWIELD, and WepSet_FromWeapon.

Referenced by bot_cmd_select_weapon(), havocbot_chooseweapon(), havocbot_movetogoal(), NIX_GiveCurrentWeapon(), REGISTER_MUTATOR(), W_GetCycleWeapon(), W_LastWeapon(), and W_SwitchWeapon().

49 {
50  float f = 0;
51 
52  if (time < CS(this).hasweapon_complain_spam)
53  complain = 0;
54 
55  // ignore hook button when using other offhand equipment
56  if (this.offhand != OFFHAND_HOOK)
57  if (wpn == WEP_HOOK && !((STAT(WEAPONS, this) | weaponsInMap) & WepSet_FromWeapon(wpn)))
58  complain = 0;
59 
60  if (complain)
61  CS(this).hasweapon_complain_spam = time + 0.2;
62 
63  if (wpn == WEP_Null)
64  {
65  if (complain)
66  sprint(this, "Invalid weapon\n");
67  return false;
68  }
69  if (autocvar_g_weaponswitch_debug == 2 && weaponslot(weaponentity) > 0 && !(wpn.spawnflags & WEP_FLAG_DUALWIELD) && !(PS(this).dual_weapons & wpn.m_wepset))
70  return false; // no complaints needed
71  if (STAT(WEAPONS, this) & WepSet_FromWeapon(wpn))
72  {
73  if (andammo)
74  {
75  if(this.items & IT_UNLIMITED_AMMO)
76  {
77  f = 1;
78  }
79  else
80  {
81  f = wpn.wr_checkammo1(wpn, this, weaponentity) + wpn.wr_checkammo2(wpn, this, weaponentity);
82 
83  // always allow selecting the Mine Layer if we placed mines, so that we can detonate them
84  if(wpn == WEP_MINE_LAYER)
85  IL_EACH(g_mines, it.owner == this && it.weaponentity_fld == weaponentity,
86  {
87  f = 1;
88  break; // no need to continue
89  });
90  }
91  if (!f)
92  {
93  if (complain)
94  if(IS_REAL_CLIENT(this))
95  {
96  play2(this, SND(UNAVAILABLE));
97  Send_WeaponComplain (this, wpn.m_id, 0);
98  }
99  return false;
100  }
101  }
102  return true;
103  }
104  if (complain)
105  {
106  // DRESK - 3/16/07
107  // Report Proper Weapon Status / Modified Weapon Ownership Message
108  if (weaponsInMap & WepSet_FromWeapon(wpn))
109  {
110  Send_WeaponComplain(this, wpn.m_id, 1);
112  Weapon_whereis(wpn, this);
113  else
114  {
115  FOREACH(Weapons, it.impulse == wpn.impulse,
116  {
117  Weapon_whereis(it, this);
118  });
119  }
120  }
121  else
122  {
123  Send_WeaponComplain (this, wpn.m_id, 2);
124  }
125 
126  play2(this, SND(UNAVAILABLE));
127  }
128  return false;
129 }
WepSet dual_weapons
Definition: selection.qh:12
OffhandHook OFFHAND_HOOK
Definition: hook.qh:67
#define IL_EACH(this, cond, body)
#define SND(id)
Definition: all.qh:35
float hasweapon_complain_spam
Definition: selection.qh:17
ClientState CS(Client this)
Definition: state.qh:47
void Send_WeaponComplain(entity e, float wpn, float type)
Definition: selection.qc:18
#define PS(this)
Definition: state.qh:18
#define IS_REAL_CLIENT(v)
Definition: utils.qh:17
int weaponslot(.entity weaponentity)
Definition: weapon.qh:16
int spawnflags
M: flags : WEPSPAWNFLAG_...
Definition: weapon.qh:52
int autocvar_g_showweaponspawns
Definition: selection.qh:6
bool autocvar_g_weaponswitch_debug
Definition: selection.qh:7
int impulse
M: impulse : weapon impulse.
Definition: weapon.qh:50
float items
Definition: progsdefs.qc:145
#define WepSet_FromWeapon(it)
Definition: all.qh:38
void Weapon_whereis(Weapon this, entity cl)
Definition: selection.qc:26
const int WEP_FLAG_DUALWIELD
Definition: weapon.qh:206
float time
Definition: csprogsdefs.qc:16
int m_id
Definition: weapon.qh:42
#define FOREACH(list, cond, body)
Definition: iter.qh:19
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ Send_WeaponComplain()

void Send_WeaponComplain ( entity  e,
float  wpn,
float  type 
)

Definition at line 18 of file selection.qc.

References msg_entity, MSG_ONE, and WriteByte().

Referenced by client_hasweapon().

19 {
20  msg_entity = e;
21  WriteHeader(MSG_ONE, TE_CSQC_WEAPONCOMPLAIN);
22  WriteByte(MSG_ONE, wpn);
23  WriteByte(MSG_ONE, type);
24 }
entity msg_entity
Definition: progsdefs.qc:63
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_CycleWeapon()

void W_CycleWeapon ( entity  this,
string  weaponorder,
float  dir,
.entity  weaponentity 
)

Definition at line 302 of file selection.qc.

References REGISTRY_GET, W_GetCycleWeapon(), and W_SwitchWeapon().

Referenced by for(), W_NextWeapon(), and W_PreviousWeapon().

303 {
304  float w;
305  w = W_GetCycleWeapon(this, weaponorder, dir, -1, 1, true, weaponentity);
306  if(w > 0)
307  W_SwitchWeapon(this, REGISTRY_GET(Weapons, w), weaponentity);
308 }
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing,.entity weaponentity)
Definition: selection.qc:131
entity weaponorder[REGISTRY_MAX(Weapons)]
Definition: weapons.qc:86
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:272
int dir
Definition: impulse.qc:89
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_GetCycleWeapon()

float W_GetCycleWeapon ( entity  this,
string  weaponorder,
float  dir,
float  imp,
float  complain,
float  skipmissing,
.entity  weaponentity 
)

Definition at line 131 of file selection.qc.

References car(), cdr(), client_hasweapon(), entity(), FOREACH, REGISTRY_GET, selectweapon, stof(), weaponcomplainindex, weaponorder, and WEP_FLAG_MUTATORBLOCKED.

Referenced by W_CycleWeapon(), and W_NextWeaponOnImpulse().

132 {
133  // We cannot tokenize in this function, as GiveItems calls this
134  // function. Thus we must use car/cdr.
135  float weaponwant, first_valid, prev_valid, switchtonext, switchtolast;
136  WepSet wepset = '0 0 0';
137  switchtonext = switchtolast = 0;
138  first_valid = prev_valid = 0;
139  float weaponcur;
140  entity wep;
141 
142  if(skipmissing || this.(weaponentity).selectweapon == 0)
143  weaponcur = this.(weaponentity).m_switchweapon.m_id;
144  else
145  weaponcur = this.(weaponentity).selectweapon;
146 
147  if(dir == 0)
148  switchtonext = 1;
149 
150  int c = 0;
151 
152  string rest = weaponorder;
153  while(rest != "")
154  {
155  weaponwant = stof(car(rest)); rest = cdr(rest);
156  wep = REGISTRY_GET(Weapons, weaponwant);
157  wepset = wep.m_wepset;
158  if(imp >= 0)
159  if(wep.impulse != imp)
160  continue;
161 
162  bool have_other = false;
163  FOREACH(Weapons, it != WEP_Null, {
164  if(i != weaponwant)
165  if(it.impulse == imp || imp < 0)
166  if((STAT(WEAPONS, this) & (it.m_wepset)) || (weaponsInMap & (it.m_wepset)))
167  have_other = true;
168  });
169 
170  // skip weapons we don't own that aren't normal and aren't in the map
171  if(!(STAT(WEAPONS, this) & wepset))
172  if(!(weaponsInMap & wepset))
173  if((wep.spawnflags & WEP_FLAG_MUTATORBLOCKED) || have_other)
174  continue;
175 
176  ++c;
177 
178  if(!skipmissing || client_hasweapon(this, wep, weaponentity, true, false))
179  {
180  if(switchtonext)
181  return weaponwant;
182  if(!first_valid)
183  first_valid = weaponwant;
184  if(weaponwant == weaponcur)
185  {
186  if(dir >= 0)
187  switchtonext = 1;
188  else if(prev_valid)
189  return prev_valid;
190  else
191  switchtolast = 1;
192  }
193  prev_valid = weaponwant;
194  }
195  }
196  if(first_valid)
197  {
198  if(switchtolast)
199  return prev_valid;
200  else
201  return first_valid;
202  }
203  // complain (but only for one weapon on the button that has been pressed)
204  if(complain)
205  {
206  this.weaponcomplainindex += 1;
207  c = (this.weaponcomplainindex % c) + 1;
208  rest = weaponorder;
209  while(rest != "")
210  {
211  weaponwant = stof(car(rest)); rest = cdr(rest);
212  wep = REGISTRY_GET(Weapons, weaponwant);
213  wepset = wep.m_wepset;
214  if(imp >= 0)
215  if(wep.impulse != imp)
216  continue;
217 
218  bool have_other = false;
219  FOREACH(Weapons, it != WEP_Null, {
220  if(i != weaponwant)
221  if(it.impulse == imp || imp < 0)
222  if((STAT(WEAPONS, this) & (it.m_wepset)) || (weaponsInMap & (it.m_wepset)))
223  have_other = true;
224  });
225 
226  // skip weapons we don't own that aren't normal and aren't in the map
227  if(!(STAT(WEAPONS, this) & wepset))
228  if(!(weaponsInMap & wepset))
229  if((wep.spawnflags & WEP_FLAG_MUTATORBLOCKED) || have_other)
230  continue;
231 
232  --c;
233  if(c == 0)
234  {
235  client_hasweapon(this, wep, weaponentity, true, true);
236  break;
237  }
238  }
239  }
240  return 0;
241 }
vector WepSet
Definition: weapon.qh:11
int int int imp
Definition: impulse.qc:90
entity() spawn
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
ERASEABLE string cdr(string s)
returns all but first word
Definition: string.qh:249
ERASEABLE string car(string s)
returns first word
Definition: string.qh:240
int weaponcomplainindex
Definition: selection.qh:20
entity weaponorder[REGISTRY_MAX(Weapons)]
Definition: weapons.qc:86
const int WEP_FLAG_MUTATORBLOCKED
Definition: weapon.qh:203
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
Definition: selection.qc:48
int dir
Definition: impulse.qc:89
int selectweapon
Definition: selection.qh:10
#define FOREACH(list, cond, body)
Definition: iter.qh:19
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_LastWeapon()

void W_LastWeapon ( entity  this,
.entity  weaponentity 
)

Definition at line 341 of file selection.qc.

References client_hasweapon(), cnt, MAX_WEAPONSLOTS, REGISTRY_GET, REPLICATE_APPLYCHANGE(), w_getbestweapon, W_SwitchToOtherWeapon(), W_SwitchWeapon(), and weaponentities.

Referenced by IMPULSE().

342 {
343  Weapon wep = REGISTRY_GET(Weapons, this.(weaponentity).cnt);
344  if (client_hasweapon(this, wep, weaponentity, true, false))
345  W_SwitchWeapon(this, wep, weaponentity);
346  else
347  W_SwitchToOtherWeapon(this, weaponentity);
348 }
void W_SwitchToOtherWeapon(entity this,.entity weaponentity)
Definition: selection.qc:253
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
float cnt
Definition: powerups.qc:24
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:272
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
Definition: selection.qc:48
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_NextWeapon()

void W_NextWeapon ( entity  this,
float  list,
.entity  weaponentity 
)

◆ W_NextWeaponOnImpulse()

void W_NextWeaponOnImpulse ( entity  this,
float  imp,
.entity  weaponentity 
)

Definition at line 310 of file selection.qc.

References CS_CVAR, REGISTRY_GET, W_GetCycleWeapon(), and W_SwitchWeapon().

Referenced by W_SwitchWeapon_TryOthers(), and weapon_group_handle().

311 {
312  float w;
313  w = W_GetCycleWeapon(this, CS_CVAR(this).cvar_cl_weaponpriority, +1, imp, 1, (CS_CVAR(this).cvar_cl_weaponimpulsemode == 0), weaponentity);
314  if(w > 0)
315  W_SwitchWeapon(this, REGISTRY_GET(Weapons, w), weaponentity);
316 }
int int int imp
Definition: impulse.qc:90
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
#define CS_CVAR(this)
Definition: state.qh:51
float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, float complain, float skipmissing,.entity weaponentity)
Definition: selection.qc:131
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:272
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_PreviousWeapon()

void W_PreviousWeapon ( entity  this,
float  list,
.entity  weaponentity 
)

Definition at line 330 of file selection.qc.

References CS_CVAR, W_CycleWeapon(), weaponorder_byid, and weaponorder_byimpulse.

Referenced by IMPULSE().

331 {
332  if(list == 0)
333  W_CycleWeapon(this, weaponorder_byid, +1, weaponentity);
334  else if(list == 1)
335  W_CycleWeapon(this, CS_CVAR(this).weaponorder_byimpulse, +1, weaponentity);
336  else if(list == 2)
337  W_CycleWeapon(this, CS_CVAR(this).cvar_cl_weaponpriority, +1, weaponentity);
338 }
#define CS_CVAR(this)
Definition: state.qh:51
string weaponorder_byid
Definition: weapon.qh:214
string weaponorder_byimpulse
Definition: client.qh:60
void W_CycleWeapon(entity this, string weaponorder, float dir,.entity weaponentity)
Definition: selection.qc:302
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_SwitchToOtherWeapon()

void W_SwitchToOtherWeapon ( entity  this,
.entity  weaponentity 
)

Definition at line 253 of file selection.qc.

References w_getbestweapon, W_SwitchWeapon_Force(), and WepSet_FromWeapon.

Referenced by W_LastWeapon(), W_Reload(), and weapon_prepareattack_checkammo().

254 {
255  // hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
256  Weapon ww;
257  WepSet set = WepSet_FromWeapon(this.(weaponentity).m_weapon);
258  if (STAT(WEAPONS, this) & set)
259  {
260  STAT(WEAPONS, this) &= ~set;
261  ww = w_getbestweapon(this, weaponentity);
262  STAT(WEAPONS, this) |= set;
263  }
264  else
265  {
266  ww = w_getbestweapon(this, weaponentity);
267  }
268  if (ww == WEP_Null) return;
269  W_SwitchWeapon_Force(this, ww, weaponentity);
270 }
vector WepSet
Definition: weapon.qh:11
#define w_getbestweapon(ent, wepent)
Definition: selection.qh:23
void W_SwitchWeapon_Force(Player this, Weapon wep,.entity weaponentity)
Definition: selection.qc:243
#define WepSet_FromWeapon(it)
Definition: all.qh:38
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_SwitchWeapon()

bool W_SwitchWeapon ( entity  this,
Weapon  imp,
.entity  weaponentity 
)

Definition at line 272 of file selection.qc.

References client_hasweapon(), CS_CVAR, entity(), Weapon::m_id, selectweapon, W_SwitchWeapon_Force(), and weaponLocked().

Referenced by GiveBall(), IMPULSE(), MUTATOR_HOOKFUNCTION(), NIX_GiveCurrentWeapon(), W_CycleWeapon(), W_LastWeapon(), W_NextWeaponOnImpulse(), W_SwitchWeapon_TryOthers(), and W_WeaponFrame().

273 {
274  if(this.(weaponentity).m_switchweapon != w)
275  {
276  if(client_hasweapon(this, w, weaponentity, true, true))
277  {
278  W_SwitchWeapon_Force(this, w, weaponentity);
279  return true;
280  }
281  else
282  {
283  this.(weaponentity).selectweapon = w.m_id; // update selectweapon anyway
284  return false;
285  }
286  }
287  else if(!weaponLocked(this) && CS_CVAR(this).cvar_cl_weapon_switch_reload)
288  {
289  entity actor = this;
290  w.wr_reload(w, actor, weaponentity);
291  }
292 
293  return true; // player already has the weapon out or needs to reload
294 }
entity() spawn
#define CS_CVAR(this)
Definition: state.qh:51
bool weaponLocked(entity player)
void W_SwitchWeapon_Force(Player this, Weapon wep,.entity weaponentity)
Definition: selection.qc:243
bool client_hasweapon(entity this, Weapon wpn,.entity weaponentity, float andammo, bool complain)
Definition: selection.qc:48
int selectweapon
Definition: selection.qh:10
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_SwitchWeapon_Force()

void W_SwitchWeapon_Force ( Player  this,
Weapon  w,
.entity  weaponentity 
)

Definition at line 243 of file selection.qc.

References entity(), Weapon::m_id, and TC.

Referenced by W_SwitchToOtherWeapon(), and W_SwitchWeapon().

244 {
245  TC(Weapon, wep);
246  entity w_ent = this.(weaponentity);
247  w_ent.cnt = w_ent.m_switchweapon.m_id;
248  w_ent.m_switchweapon = wep;
249  w_ent.selectweapon = wep.m_id;
250 }
entity() spawn
#define TC(T, sym)
Definition: _all.inc:82
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ W_SwitchWeapon_TryOthers()

void W_SwitchWeapon_TryOthers ( entity  this,
Weapon  imp,
.entity  weaponentity 
)

Definition at line 296 of file selection.qc.

References CS_CVAR, Weapon::impulse, W_NextWeaponOnImpulse(), and W_SwitchWeapon().

Referenced by weapon_byid_handle().

297 {
298  if(!W_SwitchWeapon(this, w, weaponentity) && CS_CVAR(this).cvar_cl_weapon_switch_fallback_to_impulse)
299  W_NextWeaponOnImpulse(this, w.impulse, weaponentity);
300 }
#define CS_CVAR(this)
Definition: state.qh:51
void W_NextWeaponOnImpulse(entity this, float imp,.entity weaponentity)
Definition: selection.qc:310
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:272
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

Variable Documentation

◆ autocvar_g_showweaponspawns

int autocvar_g_showweaponspawns

Definition at line 6 of file selection.qh.

Referenced by client_hasweapon(), and Weapon_whereis().

◆ autocvar_g_weaponswitch_debug

bool autocvar_g_weaponswitch_debug

◆ autocvar_g_weaponswitch_debug_alternate

bool autocvar_g_weaponswitch_debug_alternate

Definition at line 8 of file selection.qh.

Referenced by weapon_prepareattack_do().

◆ dual_weapons

WepSet dual_weapons

Definition at line 12 of file selection.qh.

Referenced by client_hasweapon().

◆ hasweapon_complain_spam

float hasweapon_complain_spam

Definition at line 17 of file selection.qh.

Referenced by client_hasweapon().

◆ selectweapon

int selectweapon

Definition at line 10 of file selection.qh.

Referenced by W_GetCycleWeapon(), and W_SwitchWeapon().

◆ weaponcomplainindex

int weaponcomplainindex

Definition at line 20 of file selection.qh.

Referenced by W_GetCycleWeapon().