From 0ca59fa70f5e81336415e1661d879aa91ff03db0 Mon Sep 17 00:00:00 2001 From: terencehill Date: Wed, 10 Apr 2019 16:54:55 +0200 Subject: [PATCH] Fix #2201 "ForbidWeaponUse mutator hook can leave the player holding a weapon they no longer possess". ForbidWeaponUse now forbids weapon use but allows switching to another weapon, while the new mutator hook LockWeapon applies both restrictions --- .../mutators/mutator/campcheck/sv_campcheck.qc | 2 +- qcsrc/common/mutators/mutator/nades/nades.qc | 2 +- .../mutators/mutator/overkill/sv_overkill.qc | 2 +- .../sv_spawn_near_teammate.qc | 2 +- qcsrc/common/vehicles/sv_vehicles.qc | 2 +- qcsrc/common/vehicles/vehicle/bumblebee.qc | 4 ++-- qcsrc/common/vehicles/vehicle/racer.qc | 4 ++-- qcsrc/common/vehicles/vehicle/raptor.qc | 4 ++-- qcsrc/common/vehicles/vehicle/spiderbot.qc | 2 +- .../vehicles/vehicle/spiderbot_weapons.qc | 2 +- qcsrc/common/weapons/weapon/hagar.qc | 2 +- qcsrc/common/weapons/weapon/vaporizer.qc | 2 +- qcsrc/server/g_hook.qc | 2 +- qcsrc/server/impulse.qc | 2 +- qcsrc/server/mutators/events.qh | 16 ++++++++++++---- qcsrc/server/weapons/selection.qc | 2 +- qcsrc/server/weapons/weaponsystem.qc | 17 ++++++++++++----- qcsrc/server/weapons/weaponsystem.qh | 3 ++- 18 files changed, 44 insertions(+), 28 deletions(-) diff --git a/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc b/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc index e56d04466..97e63161d 100644 --- a/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc +++ b/qcsrc/common/mutators/mutator/campcheck/sv_campcheck.qc @@ -45,7 +45,7 @@ MUTATOR_HOOKFUNCTION(campcheck, PlayerPreThink) if(!STAT(FROZEN, player)) if(!PHYS_INPUT_BUTTON_CHAT(player)) if(IS_REAL_CLIENT(player)) // bots may camp, but that's no reason to constantly kill them - if(!forbidWeaponUse(player)) + if(!weaponLocked(player)) { // calculate player movement (in 2 dimensions only, so jumping on one spot doesn't count as movement) vector dist = vec2(player.campcheck_prevorigin - player.origin); diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index 6924947f0..b6c4578d5 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -1161,7 +1161,7 @@ bool CanThrowNade(entity this) if (!autocvar_g_nades) return false; // allow turning them off mid match - if(forbidWeaponUse(this)) + if (weaponLocked(this)) return false; if (!IS_PLAYER(this)) diff --git a/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc b/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc index c8e4398b0..15a2fc2e0 100644 --- a/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc +++ b/qcsrc/common/mutators/mutator/overkill/sv_overkill.qc @@ -143,7 +143,7 @@ MUTATOR_HOOKFUNCTION(ok, PlayerPreThink) { return; } - if (!PHYS_INPUT_BUTTON_ATCK2(player) || forbidWeaponUse(player) || + if (!PHYS_INPUT_BUTTON_ATCK2(player) || weaponLocked(player) || !(round_handler_IsActive() && !round_handler_IsRoundStarted())) { return; diff --git a/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc b/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc index b747ce749..73435841d 100644 --- a/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc +++ b/qcsrc/common/mutators/mutator/spawn_near_teammate/sv_spawn_near_teammate.qc @@ -95,7 +95,7 @@ MUTATOR_HOOKFUNCTION(spawn_near_teammate, PlayerSpawn) if (IS_DEAD(it)) continue; if (time < it.msnt_timer) continue; if (time < it.spawnshieldtime) continue; - if (forbidWeaponUse(it)) continue; + if (weaponLocked(it)) continue; if (it == player) continue; tested++; // i consider a teammate to be available when he passes the checks above diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 9a85e1145..c8e47dabc 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -924,7 +924,7 @@ void vehicles_touch(entity this, entity toucher) // Vehicle currently in use if(this.owner) { - if(!forbidWeaponUse(this.owner)) + if(!weaponLocked(this.owner)) if(toucher != NULL) if((this.origin_z + this.maxs_z) > (toucher.origin_z)) if(vehicles_crushable(toucher)) diff --git a/qcsrc/common/vehicles/vehicle/bumblebee.qc b/qcsrc/common/vehicles/vehicle/bumblebee.qc index a83b0928f..2bd81f12d 100644 --- a/qcsrc/common/vehicles/vehicle/bumblebee.qc +++ b/qcsrc/common/vehicles/vehicle/bumblebee.qc @@ -157,7 +157,7 @@ bool bumblebee_gunner_frame(entity this, float dt) autocvar_g_vehicle_bumblebee_cannon_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_cannon_pitchlimit_up, _out * -1, _in, autocvar_g_vehicle_bumblebee_cannon_turnspeed, dt); - if(!forbidWeaponUse(this)) + if(!weaponLocked(this)) if(PHYS_INPUT_BUTTON_ATCK(this)) if(time > gun.attack_finished_single[0]) if(gun.vehicle_energy >= autocvar_g_vehicle_bumblebee_cannon_cost) @@ -531,7 +531,7 @@ bool bumblebee_pilot_frame(entity this, float dt) autocvar_g_vehicle_bumblebee_raygun_pitchlimit_down * -1, autocvar_g_vehicle_bumblebee_raygun_pitchlimit_up, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides * -1, autocvar_g_vehicle_bumblebee_raygun_turnlimit_sides, autocvar_g_vehicle_bumblebee_raygun_turnspeed, dt); - if(!forbidWeaponUse(this)) + if(!weaponLocked(this)) if((PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_ATCK2(this)) && (vehic.vehicle_energy > autocvar_g_vehicle_bumblebee_raygun_dps * PHYS_INPUT_FRAMETIME || autocvar_g_vehicle_bumblebee_raygun == 0)) { vehic.gun3.enemy.realowner = this; diff --git a/qcsrc/common/vehicles/vehicle/racer.qc b/qcsrc/common/vehicles/vehicle/racer.qc index 109eab0ca..eb9d6623a 100644 --- a/qcsrc/common/vehicles/vehicle/racer.qc +++ b/qcsrc/common/vehicles/vehicle/racer.qc @@ -287,7 +287,7 @@ bool racer_frame(entity this, float dt) Weapon wep1 = WEP_RACER; .entity weaponentity = weaponentities[0]; // TODO: unhardcode - if (!forbidWeaponUse(player)) + if (!weaponLocked(player)) if (PHYS_INPUT_BUTTON_ATCK(player)) if (wep1.wr_checkammo1(wep1, vehic, weaponentity)) { @@ -327,7 +327,7 @@ bool racer_frame(entity this, float dt) } } - if(!forbidWeaponUse(player)) + if(!weaponLocked(player)) if(time > vehic.delay) if(PHYS_INPUT_BUTTON_ATCK2(player)) { diff --git a/qcsrc/common/vehicles/vehicle/raptor.qc b/qcsrc/common/vehicles/vehicle/raptor.qc index b672d348b..6e9144168 100644 --- a/qcsrc/common/vehicles/vehicle/raptor.qc +++ b/qcsrc/common/vehicles/vehicle/raptor.qc @@ -358,7 +358,7 @@ bool raptor_frame(entity this, float dt) Weapon wep1 = WEP_RAPTOR; .entity weaponentity = weaponentities[0]; - if(!forbidWeaponUse(this)) + if(!weaponLocked(this)) if(PHYS_INPUT_BUTTON_ATCK(this)) if (wep1.wr_checkammo1(wep1, vehic, weaponentity)) { @@ -375,7 +375,7 @@ bool raptor_frame(entity this, float dt) vehicles_regen(vehic, vehic.cnt, vehicle_energy, autocvar_g_vehicle_raptor_energy, autocvar_g_vehicle_raptor_energy_regen_pause, autocvar_g_vehicle_raptor_energy_regen, dt, false); Weapon wep2a = WEP_RAPTOR_BOMB; - if(!forbidWeaponUse(this)) + if(!weaponLocked(this)) if(STAT(VEHICLESTAT_W2MODE, vehic) == RSM_BOMB) { if(time > vehic.lip + autocvar_g_vehicle_raptor_bombs_refire) diff --git a/qcsrc/common/vehicles/vehicle/spiderbot.qc b/qcsrc/common/vehicles/vehicle/spiderbot.qc index 3f023729f..36f6cb2f8 100644 --- a/qcsrc/common/vehicles/vehicle/spiderbot.qc +++ b/qcsrc/common/vehicles/vehicle/spiderbot.qc @@ -246,7 +246,7 @@ bool spiderbot_frame(entity this, float dt) vehic.angles_x = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, vehic.angles_x, autocvar_g_vehicle_spiderbot_tiltlimit); vehic.angles_z = bound(-autocvar_g_vehicle_spiderbot_tiltlimit, vehic.angles_z, autocvar_g_vehicle_spiderbot_tiltlimit); - if(!forbidWeaponUse(this)) + if(!weaponLocked(this)) if(PHYS_INPUT_BUTTON_ATCK(this)) { vehic.cnt = time; diff --git a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc index a18d03213..4b48eecce 100644 --- a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc @@ -175,7 +175,7 @@ void spiderbot_rocket_do(entity this) if(!PHYS_INPUT_BUTTON_ATCK2(this.owner)) return; - if(forbidWeaponUse(this.owner)) + if(weaponLocked(this.owner)) return; v = gettaginfo(this.tur_head,gettagindex(this.tur_head,"tag_fire")); diff --git a/qcsrc/common/weapons/weapon/hagar.qc b/qcsrc/common/weapons/weapon/hagar.qc index 20c588715..51699bf0c 100644 --- a/qcsrc/common/weapons/weapon/hagar.qc +++ b/qcsrc/common/weapons/weapon/hagar.qc @@ -257,7 +257,7 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity) // loadable hagar secondary attack, must always run each frame if(time < game_starttime || time < actor.race_penalty || timeout_status == TIMEOUT_ACTIVE) return; - if (round_handler_IsActive() && !round_handler_IsRoundStarted()) + if (weaponUseForbidden(actor)) return; bool loaded = actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max); diff --git a/qcsrc/common/weapons/weapon/vaporizer.qc b/qcsrc/common/weapons/weapon/vaporizer.qc index 2e76827d7..dbf24c796 100644 --- a/qcsrc/common/weapons/weapon/vaporizer.qc +++ b/qcsrc/common/weapons/weapon/vaporizer.qc @@ -295,7 +295,7 @@ METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponent } else if(WEP_CVAR(vaporizer, reload_ammo) && actor.(weaponentity).clip_load < vaporizer_ammo) { // forced reload thiswep.wr_reload(thiswep, actor, weaponentity); } - if((fire & 1) && (GetResource(actor, RES_CELLS) || !autocvar_g_rm) && !forbidWeaponUse(actor)) + if((fire & 1) && (GetResource(actor, RES_CELLS) || !autocvar_g_rm) && !weaponLocked(actor)) { if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(vaporizer, refire))) { diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index ffb19f17a..453cfc1e7 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -360,7 +360,7 @@ void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float void FireGrapplingHook(entity actor, .entity weaponentity) { - if(forbidWeaponUse(actor)) return; + if(weaponLocked(actor)) return; if(actor.vehicle) return; // TODO: offhand hook shoots from eye diff --git a/qcsrc/server/impulse.qc b/qcsrc/server/impulse.qc index 9b1e38e8e..2320eb830 100644 --- a/qcsrc/server/impulse.qc +++ b/qcsrc/server/impulse.qc @@ -334,7 +334,7 @@ IMPULSE(weapon_reload) { if (this.vehicle) return; if (IS_DEAD(this)) return; - if (forbidWeaponUse(this)) return; + if (weaponLocked(this)) return; entity actor = this; for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) { diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index ff8928c98..f0237b27e 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -1083,15 +1083,23 @@ MUTATOR_HOOKABLE(Player_ChangeTeamKill, EV_Player_ChangeTeamKill); /** id */ i(float, MUTATOR_ARGV_0_float) \ /** status */ i(float, MUTATOR_ARGV_1_float) \ /** data */ i(string, MUTATOR_ARGV_2_string) \ - /**/ + /**/ MUTATOR_HOOKABLE(URI_GetCallback, EV_URI_GetCallback); +/** + * return true to lock weapon (can't be used nor changed) for a player + */ +#define EV_LockWeapon(i, o) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /**/ +MUTATOR_HOOKABLE(LockWeapon, EV_LockWeapon); + /** * return true to prevent weapon use for a player */ - #define EV_ForbidWeaponUse(i, o) \ - /** player */ i(entity, MUTATOR_ARGV_0_entity) \ - /**/ +#define EV_ForbidWeaponUse(i, o) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /**/ MUTATOR_HOOKABLE(ForbidWeaponUse, EV_ForbidWeaponUse); /** called when creating a clone of the player (usually for corpses that stay after the player has re-spawned) */ diff --git a/qcsrc/server/weapons/selection.qc b/qcsrc/server/weapons/selection.qc index ea5bd2255..7f9c6ad0d 100644 --- a/qcsrc/server/weapons/selection.qc +++ b/qcsrc/server/weapons/selection.qc @@ -281,7 +281,7 @@ bool W_SwitchWeapon(entity this, Weapon w, .entity weaponentity) return false; } } - else if(!forbidWeaponUse(this) && CS(this).cvar_cl_weapon_switch_reload) + else if(!weaponLocked(this) && CS(this).cvar_cl_weapon_switch_reload) { entity actor = this; w.wr_reload(w, actor, weaponentity); diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index e7ab90c39..b75881127 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -435,13 +435,20 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( } } -bool forbidWeaponUse(entity player) +bool weaponUseForbidden(entity player) +{ + if (round_handler_IsActive() && !round_handler_IsRoundStarted()) return true; + if (MUTATOR_CALLHOOK(ForbidWeaponUse, player)) return true; + return false; +} + +bool weaponLocked(entity player) { if (time < game_starttime && !sv_ready_restart_after_countdown) return true; if (player.player_blocked) return true; if (game_stopped) return true; if (STAT(FROZEN, player)) return true; - if (MUTATOR_CALLHOOK(ForbidWeaponUse, player)) return true; + if (MUTATOR_CALLHOOK(LockWeapon, player)) return true; return false; } @@ -459,10 +466,10 @@ void W_WeaponFrame(Player actor, .entity weaponentity) int button_atck = PHYS_INPUT_BUTTON_ATCK(actor); int button_atck2 = PHYS_INPUT_BUTTON_ATCK2(actor); - if (round_handler_IsActive() && !round_handler_IsRoundStarted()) + if (weaponUseForbidden(actor)) button_atck = button_atck2 = 0; // forbid primary and secondary fire, switching is allowed - if (forbidWeaponUse(actor)) + if (weaponLocked(actor)) { if (this.state != WS_CLEAR) { @@ -591,7 +598,7 @@ void W_WeaponFrame(Player actor, .entity weaponentity) bool block_weapon = false; { bool key_pressed = PHYS_INPUT_BUTTON_HOOK(actor) && !actor.vehicle; - if (round_handler_IsActive() && !round_handler_IsRoundStarted()) + if (weaponUseForbidden(actor)) key_pressed = false; Weapon off = actor.offhand; diff --git a/qcsrc/server/weapons/weaponsystem.qh b/qcsrc/server/weapons/weaponsystem.qh index c53b15094..91879feb2 100644 --- a/qcsrc/server/weapons/weaponsystem.qh +++ b/qcsrc/server/weapons/weaponsystem.qh @@ -12,7 +12,8 @@ void CL_SpawnWeaponentity(entity e, .entity weaponentity); vector CL_Weapon_GetShotOrg(float wpn); -bool forbidWeaponUse(entity player); +bool weaponUseForbidden(entity player); +bool weaponLocked(entity player); void W_AttachToShotorg(entity actor, .entity weaponentity, entity flash, vector offset); -- 2.39.2