Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
impulse.qc
Go to the documentation of this file.
1#include "impulse.qh"
2
6#include <common/state.qh>
9#include <server/cheats.qh>
10#include <server/client.qh>
11#include <server/clientkill.qh>
13#include <server/damage.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
51
52// weapon switching impulses
53
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 }
75X(1)
76X(2)
77X(3)
78X(4)
79X(5)
80X(6)
81X(7)
82X(8)
83X(9)
84X(0)
85#undef X
86
87// custom order weapon cycling
88
89void 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 }
115X(1, prev)
117X(3, prev)
119X(5, prev)
121X(7, prev)
123X(9, prev)
124
126X(1, best)
128X(3, best)
130X(5, best)
132X(7, best)
134X(9, best)
135
137X(1, next)
139X(3, next)
141X(5, next)
143X(7, next)
145X(9, next)
146#undef X
147
148// direct weapons
149
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];
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 }
173X(1)
174X(2)
175X(3)
176X(4)
177X(5)
178X(6)
179X(7)
180X(8)
181X(9)
182X(10)
183X(11)
184X(12)
185X(13)
186X(14)
187X(15)
188X(16)
189X(17)
190X(18)
191X(19)
192X(20)
193X(21)
194X(22)
195X(23)
196#undef X
197
198IMPULSE(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
216IMPULSE(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
234IMPULSE(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
252IMPULSE(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
270IMPULSE(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
288IMPULSE(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
306IMPULSE(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
320IMPULSE(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
334IMPULSE(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 dv = v_right * -md.y;
344 if(!is_dualwielding)
345 dv = '0 0 0'; // don't override!
346 W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), dv, true);
347
349 break; // in this mode, the off-hand weapon is selected based on the primary weapon, don't drop it twice!
350 }
351}
352
353IMPULSE(weapon_reload)
354{
355 if (this.vehicle) return;
356 if (IS_DEAD(this)) return;
357 if (weaponLocked(this)) return;
358 entity actor = this;
359 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
360 {
361 .entity weaponentity = weaponentities[slot];
362 Weapon w = this.(weaponentity).m_weapon;
363 w.wr_reload(w, actor, weaponentity);
364
365 // allow reloading all active slots?
366 //if(autocvar_g_weaponswitch_debug != 1)
367 //break;
368 }
369}
370
372{
373 if (game_stopped) return;
374
375 int imp = CS(this).impulse;
376 if (!imp) return;
377 CS(this).impulse = 0;
378
379 if (MinigameImpulse(this, imp)) return;
380
381 if (timeout_status == TIMEOUT_ACTIVE) return; // don't allow any impulses while the game is paused
382
384 {
385 // impulses forbidden while waiting for the start of a round
386 #define X(id) case IMP_##id.impulse:
387 switch (imp)
388 {
389 X(weapon_drop)
390 X(weapon_reload)
391 X(use)
392 return;
393 }
394#undef X
395 }
396
397 if (vehicle_impulse(this, imp)) return;
398
399 if (CheatImpulse(this, imp)) return;
400
401 FOREACH(IMPULSES, it.impulse == imp, {
402 void(entity) f = it.impulse_handle;
403 if (!f) continue;
404 f(this);
405 return;
406 });
407}
408
410{
411 PlayerUseKey(this);
412}
413
414IMPULSE(waypoint_personal_here)
415{
416 entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, this.origin, RADARICON_WAYPOINT);
417 if (wp) WaypointSprite_Ping(wp);
418 sprint(this, "personal waypoint spawned at location\n");
419}
420
421IMPULSE(waypoint_personal_crosshair)
422{
424 entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, trace_endpos, RADARICON_WAYPOINT);
425 if (wp) WaypointSprite_Ping(wp);
426 sprint(this, "personal waypoint spawned at crosshair\n");
427}
428
429IMPULSE(waypoint_personal_death)
430{
431 if (!this.death_origin) return;
432 entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, this.death_origin, RADARICON_WAYPOINT);
433 if (wp) WaypointSprite_Ping(wp);
434 sprint(this, "personal waypoint spawned at death location\n");
435}
436
437IMPULSE(waypoint_here_follow)
438{
439 if (!teamplay) return;
440 if (IS_DEAD(this)) return;
441 if (!MUTATOR_CALLHOOK(HelpMePing, this))
442 {
443 entity wp = WaypointSprite_Attach(WP_Helpme, this, true, RADARICON_HELPME);
445 else WaypointSprite_Ping(wp);
446 }
447 sprint(this, "HELP ME attached\n");
448}
449
450IMPULSE(waypoint_here_here)
451{
452 entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, this.origin, RADARICON_HERE);
453 if (wp) WaypointSprite_Ping(wp);
454 sprint(this, "HERE spawned at location\n");
455}
456
457IMPULSE(waypoint_here_crosshair)
458{
460 entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, trace_endpos, RADARICON_HERE);
461 if (wp) WaypointSprite_Ping(wp);
462 sprint(this, "HERE spawned at crosshair\n");
463}
464
465IMPULSE(waypoint_here_death)
466{
467 if (!this.death_origin) return;
468 entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, this.death_origin, RADARICON_HERE);
469 if (wp) WaypointSprite_Ping(wp);
470 sprint(this, "HERE spawned at death location\n");
471}
472
473IMPULSE(waypoint_danger_here)
474{
475 entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, this.origin, RADARICON_DANGER);
476 if (wp) WaypointSprite_Ping(wp);
477 sprint(this, "DANGER spawned at location\n");
478}
479
480IMPULSE(waypoint_danger_crosshair)
481{
483 entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, trace_endpos, RADARICON_DANGER);
484 if (wp) WaypointSprite_Ping(wp);
485 sprint(this, "DANGER spawned at crosshair\n");
486}
487
488IMPULSE(waypoint_danger_death)
489{
490 if (!this.death_origin) return;
491 entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, this.death_origin, RADARICON_DANGER);
492 if (wp) WaypointSprite_Ping(wp);
493 sprint(this, "DANGER spawned at death location\n");
494}
495
496IMPULSE(waypoint_clear_personal)
497{
499 if (this.personal)
500 {
501 delete(this.personal);
502 this.personal = NULL;
503
505 ClientKill(this);
506 }
507 sprint(this, "personal waypoint cleared\n");
508}
509
510IMPULSE(waypoint_clear)
511{
513 if (this.personal)
514 {
515 delete(this.personal);
516 this.personal = NULL;
518 ClientKill(this);
519 }
520 sprint(this, "all waypoints cleared\n");
521}
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
float CheatImpulse(entity this, int imp)
Definition cheats.qc:138
entity personal
Definition cheats.qh:24
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:44
virtual void wr_reload()
(SERVER) handles reloading for weapon
Definition weapon.qh:104
#define g_race
Definition race.qh:48
#define IS_DEAD(s)
Definition player.qh:245
int timeout_status
Definition stats.qh:87
float game_stopped
Definition stats.qh:81
vector velocity
vector v_right
vector trace_endpos
vector v_forward
vector origin
#define use
#define g_cts
Definition cts.qh:36
vector death_origin
Definition damage.qh:67
#define X()
best
Definition all.qh:82
prev
Definition all.qh:71
next
Definition all.qh:93
#define FOREACH(list, cond, body)
Definition iter.qh:19
#define ClientKill
Definition _all.inc:250
vector movedir
Definition viewloc.qh:18
void sprint(float clientnum, string text,...)
#define NULL
Definition post.qh:14
float impulse
Definition progsdefs.qc:158
#define round_handler_IsActive()
#define round_handler_IsRoundStarted()
bool W_SwitchWeapon(entity this, Weapon w,.entity weaponentity)
Definition selection.qc:275
void W_PreviousWeapon(entity this, float list,.entity weaponentity)
Definition selection.qc:333
void W_NextWeapon(entity this, int list,.entity weaponentity)
Definition selection.qc:322
void W_CycleWeapon(entity this, string weaponorder, float dir,.entity weaponentity)
Definition selection.qc:305
void W_SwitchWeapon_TryOthers(entity this, Weapon w,.entity weaponentity)
Definition selection.qc:299
void W_NextWeaponOnImpulse(entity this, float imp,.entity weaponentity)
Definition selection.qc:313
void W_LastWeapon(entity this,.entity weaponentity)
Definition selection.qc:344
#define w_getbestweapon(ent, wepent)
Definition selection.qh:23
bool autocvar_g_weaponswitch_debug
Definition selection.qh:7
vector
Definition self.qh:92
void PlayerUseKey(entity this)
Definition client.qc:2584
const float TIMEOUT_ACTIVE
Definition common.qh:49
void weapon_group_handle(entity this, int number, int imp)
Impulse map:
Definition impulse.qc:54
#define X(i)
Definition impulse.qc:70
void ImpulseCommands(entity this)
Definition impulse.qc:371
int int int imp
Definition impulse.qc:90
int dir
Definition impulse.qc:89
#define IMPULSE(id)
Definition impulse.qc:23
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
int int number
Definition impulse.qc:89
bool autocvar_g_allow_checkpoints
Definition race.qh:3
bool W_DualWielding(entity player)
Definition common.qc:20
#define CS_CVAR(this)
Definition state.qh:51
ClientState CS(Client this)
Definition state.qh:47
bool MinigameImpulse(entity this, int imp)
bool vehicle_impulse(entity this, int imp)
entity vehicle
Entity to disply the shild effect on damage.
bool teamplay
Definition teams.qh:59
void W_ThrowWeapon(entity this,.entity weaponentity, vector velo, vector delta, float doreduce)
Definition throwing.qc:133
vector W_CalculateProjectileVelocity(entity actor, vector pvelocity, vector mvelocity, float forceAbsolute)
Definition tracing.qc:176
void WarpZone_crosshair_trace_plusvisibletriggers(entity pl)
Definition tracing.qc:559
void WarpZone_crosshair_trace(entity pl)
Definition tracing.qc:585
void WaypointSprite_HelpMePing(entity e)
void WaypointSprite_ClearOwned(entity this)
entity WaypointSprite_DeployPersonal(entity spr, entity player, vector ofs, entity icon)
entity WaypointSprite_DeployFixed(entity spr, bool limited_range, entity player, vector ofs, entity icon)
void WaypointSprite_Ping(entity e)
void WaypointSprite_ClearPersonal(entity this)
entity WaypointSprite_Attach(entity spr, entity player, bool limited_range, entity icon)
entity waypointsprite_attachedforcarrier
Weapon Weapon_from_impulse(int imp)
Definition all.qh:150
const int MAX_WEAPONSLOTS
Definition weapon.qh:16
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
bool weaponLocked(entity player)
Weapon m_weapon
Definition wepent.qh:26