Xonotic
impulse.qc
Go to the documentation of this file.
1 #include "impulse.qh"
2 
6 #include <common/state.qh>
8 #include <common/weapons/_all.qh>
9 #include <server/cheats.qh>
10 #include <server/client.qh>
11 #include <server/clientkill.qh>
12 #include <server/command/common.qh>
13 #include <server/damage.qh>
14 #include <server/mutators/_mod.qh>
15 #include <server/round_handler.qh>
20 
21 .entity vehicle;
22 
23 #define IMPULSE(id) _IMPULSE(IMP_##id)
24 #define _IMPULSE(id) \
25  void id##_handle(entity this); \
26  STATIC_INIT_LATE(id) \
27  { \
28  id.impulse_handle = id##_handle; \
29  } \
30  void id##_handle(entity this)
31 
52 // weapon switching impulses
53 
54 void weapon_group_handle(entity this, int number, int imp)
55 {
56  if (IS_DEAD(this))
57  {
58  this.impulse = imp;
59  return;
60  }
61  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
62  {
63  .entity weaponentity = weaponentities[slot];
64  W_NextWeaponOnImpulse(this, number, weaponentity);
66  break;
67  }
68 }
69 
70 #define X(i) \
71  IMPULSE(weapon_group_##i) \
72  { \
73  weapon_group_handle(this, i, IMP_weapon_group_##i.impulse); \
74  }
75 X(1)
76 X(2)
77 X(3)
78 X(4)
79 X(5)
80 X(6)
81 X(7)
82 X(8)
83 X(9)
84 X(0)
85 #undef X
86 
87 // custom order weapon cycling
88 
89 void weapon_priority_handle(entity this, int dir, int number, int imp)
90 {
91  if (this.vehicle) return;
92  if (IS_DEAD(this))
93  {
94  this.impulse = imp;
95  return;
96  }
97  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
98  {
99  .entity weaponentity = weaponentities[slot];
100  W_CycleWeapon(this, CS_CVAR(this).cvar_cl_weaponpriorities[number], dir, weaponentity);
102  break;
103  }
104 }
105 
106 #define X(i, dir) \
107  IMPULSE(weapon_priority_##i##_##dir) \
108  { \
109  noref int prev = -1; \
110  noref int best = 0; \
111  noref int next = +1; \
112  weapon_priority_handle(this, dir, i, IMP_weapon_priority_##i##_##dir.impulse); \
113  }
114 X(0, prev)
115 X(1, prev)
116 X(2, prev)
117 X(3, prev)
118 X(4, prev)
119 X(5, prev)
120 X(6, prev)
121 X(7, prev)
122 X(8, prev)
123 X(9, prev)
124 
125 X(0, best)
126 X(1, best)
127 X(2, best)
128 X(3, best)
129 X(4, best)
130 X(5, best)
131 X(6, best)
132 X(7, best)
133 X(8, best)
134 X(9, best)
135 
136 X(0, next)
137 X(1, next)
138 X(2, next)
139 X(3, next)
140 X(4, next)
141 X(5, next)
142 X(6, next)
143 X(7, next)
144 X(8, next)
145 X(9, next)
146 #undef X
147 
148 // direct weapons
149 
150 void weapon_byid_handle(entity this, int number, int imp)
151 {
152  if (this.vehicle) return;
153  if (IS_DEAD(this))
154  {
155  this.impulse = imp;
156  return;
157  }
158  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
159  {
160  .entity weaponentity = weaponentities[slot];
161  W_SwitchWeapon_TryOthers(this, REGISTRY_GET(Weapons, WEP_FIRST + number), weaponentity);
163  break;
164  }
165 }
166 
167 #define X(i) \
168  IMPULSE(weapon_byid_##i) \
169  { \
170  weapon_byid_handle(this, i, IMP_weapon_byid_##i.impulse); \
171  }
172 X(0)
173 X(1)
174 X(2)
175 X(3)
176 X(4)
177 X(5)
178 X(6)
179 X(7)
180 X(8)
181 X(9)
182 X(10)
183 X(11)
184 X(12)
185 X(13)
186 X(14)
187 X(15)
188 X(16)
189 X(17)
190 X(18)
191 X(19)
192 X(20)
193 X(21)
194 X(22)
195 X(23)
196 #undef X
197 
198 IMPULSE(weapon_next_byid)
199 {
200  if (this.vehicle) return;
201  if (IS_DEAD(this))
202  {
203  this.impulse = IMP_weapon_next_byid.impulse;
204  return;
205  }
206  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
207  {
208  .entity weaponentity = weaponentities[slot];
209  W_NextWeapon(this, 0, weaponentity);
210 
212  break;
213  }
214 }
215 
216 IMPULSE(weapon_prev_byid)
217 {
218  if (this.vehicle) return;
219  if (IS_DEAD(this))
220  {
221  this.impulse = IMP_weapon_prev_byid.impulse;
222  return;
223  }
224  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
225  {
226  .entity weaponentity = weaponentities[slot];
227  W_PreviousWeapon(this, 0, weaponentity);
228 
230  break;
231  }
232 }
233 
234 IMPULSE(weapon_next_bygroup)
235 {
236  if (this.vehicle) return;
237  if (IS_DEAD(this))
238  {
239  this.impulse = IMP_weapon_next_bygroup.impulse;
240  return;
241  }
242  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
243  {
244  .entity weaponentity = weaponentities[slot];
245  W_NextWeapon(this, 1, weaponentity);
246 
248  break;
249  }
250 }
251 
252 IMPULSE(weapon_prev_bygroup)
253 {
254  if (this.vehicle) return;
255  if (IS_DEAD(this))
256  {
257  this.impulse = IMP_weapon_prev_bygroup.impulse;
258  return;
259  }
260  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
261  {
262  .entity weaponentity = weaponentities[slot];
263  W_PreviousWeapon(this, 1, weaponentity);
264 
266  break;
267  }
268 }
269 
270 IMPULSE(weapon_next_bypriority)
271 {
272  if (this.vehicle) return;
273  if (IS_DEAD(this))
274  {
275  this.impulse = IMP_weapon_next_bypriority.impulse;
276  return;
277  }
278  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
279  {
280  .entity weaponentity = weaponentities[slot];
281  W_NextWeapon(this, 2, weaponentity);
282 
284  break;
285  }
286 }
287 
288 IMPULSE(weapon_prev_bypriority)
289 {
290  if (this.vehicle) return;
291  if (IS_DEAD(this))
292  {
293  this.impulse = IMP_weapon_prev_bypriority.impulse;
294  return;
295  }
296  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
297  {
298  .entity weaponentity = weaponentities[slot];
299  W_PreviousWeapon(this, 2, weaponentity);
300 
302  break;
303  }
304 }
305 
306 IMPULSE(weapon_last)
307 {
308  if (this.vehicle) return;
309  if (IS_DEAD(this)) return;
310  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
311  {
312  .entity weaponentity = weaponentities[slot];
313  W_LastWeapon(this, weaponentity);
314 
316  break;
317  }
318 }
319 
320 IMPULSE(weapon_best)
321 {
322  if (this.vehicle) return;
323  if (IS_DEAD(this)) return;
324  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
325  {
326  .entity weaponentity = weaponentities[slot];
327  W_SwitchWeapon(this, w_getbestweapon(this, weaponentity), weaponentity);
328 
330  break;
331  }
332 }
333 
334 IMPULSE(weapon_drop)
335 {
336  if (this.vehicle) return;
337  if (IS_DEAD(this)) return;
338  bool is_dualwielding = W_DualWielding(this);
339  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
340  {
341  .entity weaponentity = weaponentities[slot];
342  vector md = this.(weaponentity).movedir;
343  vector vecs = ((md.x > 0) ? md : '0 0 0');
344  vector dv = v_right * -vecs.y;
345  if(!is_dualwielding)
346  dv = '0 0 0'; // don't override!
347  W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), dv, true);
348 
350  break; // in this mode, the off-hand weapon is selected based on the primary weapon, don't drop it twice!
351  }
352 }
353 
354 IMPULSE(weapon_reload)
355 {
356  if (this.vehicle) return;
357  if (IS_DEAD(this)) return;
358  if (weaponLocked(this)) return;
359  entity actor = this;
360  for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
361  {
362  .entity weaponentity = weaponentities[slot];
363  Weapon w = this.(weaponentity).m_weapon;
364  w.wr_reload(w, actor, weaponentity);
365 
366  // allow reloading all active slots?
367  //if(autocvar_g_weaponswitch_debug != 1)
368  //break;
369  }
370 }
371 
373 {
374  if (game_stopped) return;
375 
376  int imp = CS(this).impulse;
377  if (!imp) return;
378  CS(this).impulse = 0;
379 
380  if (MinigameImpulse(this, imp)) return;
381 
382  if (timeout_status == TIMEOUT_ACTIVE) return; // don't allow any impulses while the game is paused
383 
385  {
386  // impulses forbidden while waiting for the start of a round
387  #define X(id) case IMP_##id.impulse:
388  switch (imp)
389  {
390  X(weapon_drop)
391  X(weapon_reload)
392  X(use)
393  return;
394  }
395 #undef X
396  }
397 
398  if (vehicle_impulse(this, imp)) return;
399 
400  if (CheatImpulse(this, imp)) return;
401 
402  FOREACH(IMPULSES, it.impulse == imp, {
403  void(entity) f = it.impulse_handle;
404  if (!f) continue;
405  f(this);
406  return;
407  });
408 }
409 
411 {
412  PlayerUseKey(this);
413 }
414 
415 IMPULSE(waypoint_personal_here)
416 {
417  entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, this.origin, RADARICON_WAYPOINT);
418  if (wp) WaypointSprite_Ping(wp);
419  sprint(this, "personal waypoint spawned at location\n");
420 }
421 
422 IMPULSE(waypoint_personal_crosshair)
423 {
425  entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, trace_endpos, RADARICON_WAYPOINT);
426  if (wp) WaypointSprite_Ping(wp);
427  sprint(this, "personal waypoint spawned at crosshair\n");
428 }
429 
430 IMPULSE(waypoint_personal_death)
431 {
432  if (!this.death_origin) return;
433  entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, this.death_origin, RADARICON_WAYPOINT);
434  if (wp) WaypointSprite_Ping(wp);
435  sprint(this, "personal waypoint spawned at death location\n");
436 }
437 
438 IMPULSE(waypoint_here_follow)
439 {
440  if (!teamplay) return;
441  if (IS_DEAD(this)) return;
442  if (!MUTATOR_CALLHOOK(HelpMePing, this))
443  {
444  entity wp = WaypointSprite_Attach(WP_Helpme, this, true, RADARICON_HELPME);
445  if (!wp) WaypointSprite_HelpMePing(this.waypointsprite_attachedforcarrier);
446  else WaypointSprite_Ping(wp);
447  }
448  sprint(this, "HELP ME attached\n");
449 }
450 
451 IMPULSE(waypoint_here_here)
452 {
453  entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, this.origin, RADARICON_HERE);
454  if (wp) WaypointSprite_Ping(wp);
455  sprint(this, "HERE spawned at location\n");
456 }
457 
458 IMPULSE(waypoint_here_crosshair)
459 {
461  entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, trace_endpos, RADARICON_HERE);
462  if (wp) WaypointSprite_Ping(wp);
463  sprint(this, "HERE spawned at crosshair\n");
464 }
465 
466 IMPULSE(waypoint_here_death)
467 {
468  if (!this.death_origin) return;
469  entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, this.death_origin, RADARICON_HERE);
470  if (wp) WaypointSprite_Ping(wp);
471  sprint(this, "HERE spawned at death location\n");
472 }
473 
474 IMPULSE(waypoint_danger_here)
475 {
476  entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, this.origin, RADARICON_DANGER);
477  if (wp) WaypointSprite_Ping(wp);
478  sprint(this, "DANGER spawned at location\n");
479 }
480 
481 IMPULSE(waypoint_danger_crosshair)
482 {
484  entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, trace_endpos, RADARICON_DANGER);
485  if (wp) WaypointSprite_Ping(wp);
486  sprint(this, "DANGER spawned at crosshair\n");
487 }
488 
489 IMPULSE(waypoint_danger_death)
490 {
491  if (!this.death_origin) return;
492  entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, this.death_origin, RADARICON_DANGER);
493  if (wp) WaypointSprite_Ping(wp);
494  sprint(this, "DANGER spawned at death location\n");
495 }
496 
497 IMPULSE(waypoint_clear_personal)
498 {
499  WaypointSprite_ClearPersonal(this);
500  if (this.personal)
501  {
502  delete(this.personal);
503  this.personal = NULL;
504 
506  ClientKill(this);
507  }
508  sprint(this, "personal waypoint cleared\n");
509 }
510 
511 IMPULSE(waypoint_clear)
512 {
513  WaypointSprite_ClearOwned(this);
514  if (this.personal)
515  {
516  delete(this.personal);
517  this.personal = NULL;
519  ClientKill(this);
520  }
521  sprint(this, "all waypoints cleared\n");
522 }
int int int imp
Definition: impulse.qc:90
#define round_handler_IsActive()
void weapon_group_handle(entity this, int number, int imp)
Impulse map:
Definition: impulse.qc:54
#define X(i)
Definition: impulse.qc:167
const int WEP_FIRST
Definition: all.qh:304
int int number
Definition: impulse.qc:89
void W_SwitchWeapon_TryOthers(entity this, Weapon w,.entity weaponentity)
Definition: selection.qc:296
#define w_getbestweapon(ent, wepent)
Definition: selection.qh:23
void W_NextWeapon(entity this, int list,.entity weaponentity)
Definition: selection.qc:319
void ClientKill(entity this)
Definition: clientkill.qc:208
entity() spawn
float CheatImpulse(entity this, int imp)
Definition: cheats.qc:130
prev
Definition: all.qh:66
#define REGISTRY_GET(id, i)
Definition: registry.qh:43
ClientState CS(Client this)
Definition: state.qh:47
#define CS_CVAR(this)
Definition: state.qh:51
bool vehicle_impulse(entity this, int imp)
Definition: sv_vehicles.qc:921
origin
Definition: ent_cs.qc:114
const float TIMEOUT_ACTIVE
Definition: common.qh:49
#define round_handler_IsRoundStarted()
void W_ThrowWeapon(entity this,.entity weaponentity, vector velo, vector delta, float doreduce)
Definition: throwing.qc:153
float impulse
Definition: progsdefs.qc:158
bool weaponLocked(entity player)
vector movedir
Definition: progsdefs.qc:203
entity personal
Definition: cheats.qh:23
bool MinigameImpulse(entity this, int imp)
bool autocvar_g_weaponswitch_debug
Definition: selection.qh:7
#define g_cts
Definition: cts.qh:36
#define g_race
Definition: race.qh:46
bool W_DualWielding(entity player)
Definition: common.qc:20
const int MAX_WEAPONSLOTS
Definition: weapon.qh:13
bool autocvar_g_allow_checkpoints
Definition: race.qh:3
void PlayerUseKey(entity this)
Definition: client.qc:2349
#define NULL
Definition: post.qh:17
vector trace_endpos
Definition: csprogsdefs.qc:37
#define IMPULSE(id)
Definition: impulse.qc:23
float teamplay
Definition: progsdefs.qc:31
#define IS_DEAD(s)
Definition: utils.qh:26
vector(float skel, float bonenum) _skel_get_boneabs_hidden
next
Definition: all.qh:88
vector death_origin
Definition: damage.qh:70
void WarpZone_crosshair_trace(entity pl)
Definition: tracing.qc:544
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
vector v_right
Definition: csprogsdefs.qc:31
#define MUTATOR_CALLHOOK(id,...)
Definition: base.qh:140
entity weaponentities[MAX_WEAPONSLOTS]
Definition: weapon.qh:14
#define use
Definition: csprogsdefs.qh:50
best
Definition: all.qh:77
vector W_CalculateProjectileVelocity(entity actor, vector pvelocity, vector mvelocity, float forceAbsolute)
Definition: tracing.qc:169
entity vehicle
Definition: impulse.qc:21
void WarpZone_crosshair_trace_plusvisibletriggers(entity pl)
Definition: tracing.qc:518
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition: weapon.qh:41
vector velocity
Definition: csprogsdefs.qc:103
int dir
Definition: impulse.qc:89
prev prev prev prev prev best best best best best next next next next next void weapon_byid_handle(entity this, int number, int imp)
Definition: impulse.qc:150
#define FOREACH(list, cond, body)
Definition: iter.qh:19
void W_CycleWeapon(entity this, string weaponorder, float dir,.entity weaponentity)
Definition: selection.qc:302
void W_LastWeapon(entity this,.entity weaponentity)
Definition: selection.qc:341
void W_PreviousWeapon(entity this, float list,.entity weaponentity)
Definition: selection.qc:330
vector v_forward
Definition: csprogsdefs.qc:31
void ImpulseCommands(entity this)
Definition: impulse.qc:372