2 #include "round_handler.qh"
4 #include "weapons/throwing.qh"
5 #include "command/common.qh"
7 #include "weapons/selection.qh"
8 #include "weapons/tracing.qh"
9 #include "weapons/weaponsystem.qh"
11 #include <common/state.qh>
13 #include "../common/minigames/sv_minigames.qh"
15 #include <common/weapons/_all.qh>
16 #include "../common/vehicles/sv_vehicles.qh"
18 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
22 #define IMPULSE(id) _IMPULSE(IMP_##id)
23 #define _IMPULSE(id) \
24 void id##_handle(entity this); \
25 STATIC_INIT_LATE(id) \
27 id.impulse_handle = id##_handle; \
29 void id##_handle(entity this)
34 * 0 reserved (no input)
41 * 143: emergency teleport
42 * 148: unfairly eliminate
45 * 200 to 209: prev weapon shortcuts
46 * 210 to 219: best weapon shortcuts
47 * 220 to 229: next weapon shortcuts
48 * 230 to 253: individual weapons (up to 24)
51 // weapon switching impulses
54 IMPULSE(weapon_group_##slot) \
58 this.impulse = IMP_weapon_group_##slot.impulse; \
61 for(int wepslot = 0; wepslot < MAX_WEAPONSLOTS; ++wepslot) \
63 .entity weaponentity = weaponentities[wepslot]; \
64 W_NextWeaponOnImpulse(this, slot, weaponentity); \
65 if(wepslot == 0 && autocvar_g_weaponswitch_debug != 1) \
81 // custom order weapon cycling
83 #define X(slot, dir) \
84 IMPULSE(weapon_priority_##slot##_##dir) \
86 if (this.vehicle) return; \
89 this.impulse = IMP_weapon_priority_##slot##_##dir.impulse; \
92 noref int prev = -1; \
94 noref int next = +1; \
95 for(int wepslot = 0; wepslot < MAX_WEAPONSLOTS; ++wepslot) \
97 .entity weaponentity = weaponentities[wepslot]; \
98 W_CycleWeapon(this, CS(this).cvar_cl_weaponpriorities[slot], dir, weaponentity); \
99 if(wepslot == 0 && autocvar_g_weaponswitch_debug != 1) \
140 IMPULSE(weapon_byid_##i) \
142 if (this.vehicle) return; \
145 this.impulse = IMP_weapon_byid_##i.impulse; \
148 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) \
150 .entity weaponentity = weaponentities[slot]; \
151 W_SwitchWeapon(this, Weapons_from(WEP_FIRST + i), weaponentity); \
152 if(slot == 0 && autocvar_g_weaponswitch_debug != 1) \
182 IMPULSE(weapon_next_byid)
184 if (this.vehicle) return;
187 this.impulse = IMP_weapon_next_byid.impulse;
190 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
192 .entity weaponentity = weaponentities[slot];
193 W_NextWeapon(this, 0, weaponentity);
195 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
200 IMPULSE(weapon_prev_byid)
202 if (this.vehicle) return;
205 this.impulse = IMP_weapon_prev_byid.impulse;
208 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
210 .entity weaponentity = weaponentities[slot];
211 W_PreviousWeapon(this, 0, weaponentity);
213 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
218 IMPULSE(weapon_next_bygroup)
220 if (this.vehicle) return;
223 this.impulse = IMP_weapon_next_bygroup.impulse;
226 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
228 .entity weaponentity = weaponentities[slot];
229 W_NextWeapon(this, 1, weaponentity);
231 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
236 IMPULSE(weapon_prev_bygroup)
238 if (this.vehicle) return;
241 this.impulse = IMP_weapon_prev_bygroup.impulse;
244 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
246 .entity weaponentity = weaponentities[slot];
247 W_PreviousWeapon(this, 1, weaponentity);
249 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
254 IMPULSE(weapon_next_bypriority)
256 if (this.vehicle) return;
259 this.impulse = IMP_weapon_next_bypriority.impulse;
262 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
264 .entity weaponentity = weaponentities[slot];
265 W_NextWeapon(this, 2, weaponentity);
267 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
272 IMPULSE(weapon_prev_bypriority)
274 if (this.vehicle) return;
277 this.impulse = IMP_weapon_prev_bypriority.impulse;
280 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
282 .entity weaponentity = weaponentities[slot];
283 W_PreviousWeapon(this, 2, weaponentity);
285 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
292 if (this.vehicle) return;
293 if (IS_DEAD(this)) return;
294 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
296 .entity weaponentity = weaponentities[slot];
297 W_LastWeapon(this, weaponentity);
299 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
306 if (this.vehicle) return;
307 if (IS_DEAD(this)) return;
308 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
310 .entity weaponentity = weaponentities[slot];
311 W_SwitchWeapon(this, w_getbestweapon(this, weaponentity), weaponentity);
313 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
320 if (this.vehicle) return;
321 if (IS_DEAD(this)) return;
322 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
324 .entity weaponentity = weaponentities[slot];
325 W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
327 if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
332 IMPULSE(weapon_reload)
334 if (this.vehicle) return;
335 if (IS_DEAD(this)) return;
336 if (forbidWeaponUse(this)) return;
338 for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
340 .entity weaponentity = weaponentities[slot];
341 Weapon w = this.(weaponentity).m_weapon;
342 w.wr_reload(w, actor, weaponentity);
344 // allow reloading all active slots?
345 //if(slot == 0 && autocvar_g_weaponswitch_debug != 1)
350 void ImpulseCommands(entity this)
352 if (game_stopped) return;
354 int imp = CS(this).impulse;
356 CS(this).impulse = 0;
358 if (MinigameImpulse(this, imp)) return;
360 if (timeout_status == TIMEOUT_ACTIVE) return; // don't allow any impulses while the game is paused
362 // allow only weapon change impulses when not in round time
363 if (round_handler_IsActive() && !round_handler_IsRoundStarted())
365 #define X(id) case IMP_##id.impulse:
380 X(weapon_next_bygroup)
381 X(weapon_prev_bygroup)
382 X(weapon_next_bypriority)
383 X(weapon_prev_bypriority)
387 X(weapon_priority_0_prev)
388 X(weapon_priority_1_prev)
389 X(weapon_priority_2_prev)
390 X(weapon_priority_3_prev)
391 X(weapon_priority_4_prev)
392 X(weapon_priority_5_prev)
393 X(weapon_priority_6_prev)
394 X(weapon_priority_7_prev)
395 X(weapon_priority_8_prev)
396 X(weapon_priority_9_prev)
397 X(weapon_priority_0_next)
398 X(weapon_priority_1_next)
399 X(weapon_priority_2_next)
400 X(weapon_priority_3_next)
401 X(weapon_priority_4_next)
402 X(weapon_priority_5_next)
403 X(weapon_priority_6_next)
404 X(weapon_priority_7_next)
405 X(weapon_priority_8_next)
406 X(weapon_priority_9_next)
407 X(weapon_priority_0_best)
408 X(weapon_priority_1_best)
409 X(weapon_priority_2_best)
410 X(weapon_priority_3_best)
411 X(weapon_priority_4_best)
412 X(weapon_priority_5_best)
413 X(weapon_priority_6_best)
414 X(weapon_priority_7_best)
415 X(weapon_priority_8_best)
416 X(weapon_priority_9_best)
447 if (vehicle_impulse(this, imp)) return;
449 if (CheatImpulse(this, imp)) return;
451 FOREACH(IMPULSES, it.impulse == imp, {
452 void(entity) f = it.impulse_handle;
464 IMPULSE(waypoint_personal_here)
466 entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, this.origin, RADARICON_WAYPOINT);
467 if (wp) WaypointSprite_Ping(wp);
468 sprint(this, "personal waypoint spawned at location\n");
471 IMPULSE(waypoint_personal_crosshair)
473 WarpZone_crosshair_trace(this);
474 entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, trace_endpos, RADARICON_WAYPOINT);
475 if (wp) WaypointSprite_Ping(wp);
476 sprint(this, "personal waypoint spawned at crosshair\n");
479 IMPULSE(waypoint_personal_death)
481 if (!this.death_origin) return;
482 entity wp = WaypointSprite_DeployPersonal(WP_Waypoint, this, this.death_origin, RADARICON_WAYPOINT);
483 if (wp) WaypointSprite_Ping(wp);
484 sprint(this, "personal waypoint spawned at death location\n");
487 IMPULSE(waypoint_here_follow)
489 if (!teamplay) return;
490 if (IS_DEAD(this)) return;
491 if (!MUTATOR_CALLHOOK(HelpMePing, this))
493 entity wp = WaypointSprite_Attach(WP_Helpme, this, true, RADARICON_HELPME);
494 if (!wp) WaypointSprite_HelpMePing(this.waypointsprite_attachedforcarrier);
495 else WaypointSprite_Ping(wp);
497 sprint(this, "HELP ME attached\n");
500 IMPULSE(waypoint_here_here)
502 entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, this.origin, RADARICON_HERE);
503 if (wp) WaypointSprite_Ping(wp);
504 sprint(this, "HERE spawned at location\n");
507 IMPULSE(waypoint_here_crosshair)
509 WarpZone_crosshair_trace(this);
510 entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, trace_endpos, RADARICON_HERE);
511 if (wp) WaypointSprite_Ping(wp);
512 sprint(this, "HERE spawned at crosshair\n");
515 IMPULSE(waypoint_here_death)
517 if (!this.death_origin) return;
518 entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, this.death_origin, RADARICON_HERE);
519 if (wp) WaypointSprite_Ping(wp);
520 sprint(this, "HERE spawned at death location\n");
523 IMPULSE(waypoint_danger_here)
525 entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, this.origin, RADARICON_DANGER);
526 if (wp) WaypointSprite_Ping(wp);
527 sprint(this, "DANGER spawned at location\n");
530 IMPULSE(waypoint_danger_crosshair)
532 WarpZone_crosshair_trace(this);
533 entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, trace_endpos, RADARICON_DANGER);
534 if (wp) WaypointSprite_Ping(wp);
535 sprint(this, "DANGER spawned at crosshair\n");
538 IMPULSE(waypoint_danger_death)
540 if (!this.death_origin) return;
541 entity wp = WaypointSprite_DeployFixed(WP_Danger, false, this, this.death_origin, RADARICON_DANGER);
542 if (wp) WaypointSprite_Ping(wp);
543 sprint(this, "DANGER spawned at death location\n");
546 IMPULSE(waypoint_clear_personal)
548 WaypointSprite_ClearPersonal(this);
551 delete(this.personal);
552 this.personal = NULL;
554 if((g_cts || g_race) && autocvar_g_allow_checkpoints)
557 sprint(this, "personal waypoint cleared\n");
560 IMPULSE(waypoint_clear)
562 WaypointSprite_ClearOwned(this);
565 delete(this.personal);
566 this.personal = NULL;
567 if((g_cts || g_race) && autocvar_g_allow_checkpoints)
570 sprint(this, "all waypoints cleared\n");