From c048ca752681436804403dff79ac06016fbe279b Mon Sep 17 00:00:00 2001 From: A1m` <33463136+A1mDev@users.noreply.github.com> Date: Sat, 6 Nov 2021 18:42:53 +0700 Subject: [PATCH] Updated plugins. (#411) 1) Fix the build of plugins for the latest version of the sourcemod (fixed errors and warnings). 2) Updated syntax in some plugins. 3) Added latest version of 'left4dhooks'. 4) 'l4d2_tank_damage_cvars' fixed broken functionality related to cvar 'vs_tank_pound_damage' (apparently this code never worked). 5) 'l4d2_sniper_bodyshot' code optimization. 6) Added smac include for plugin build l4d2_user_commands'. 7) Removed conversions to another datatype in many plugins due to enum. 8) Removed unnecessary checks in some plugins. 9) Changed l4d2util includes. Since we only use enum as constants, the enumeration names have been removed. the name made it clear to the compiler that we were using our own datatype, so we had to convert it to another datatype to avoid the warnings. 10) --- .../sourcemod/gamedata/left4dhooks.l4d2.txt | 972 +++- .../plugins/anticheat/l4d2_user_commands.smx | Bin 6467 -> 6491 bytes addons/sourcemod/plugins/left4dhooks.smx | Bin 77865 -> 83678 bytes .../plugins/optional/l4d2_playstats.smx | Bin 76000 -> 75999 bytes .../plugins/optional/l4d2_sniper_bodyshot.smx | Bin 4395 -> 6643 bytes .../plugins/optional/l4d2_sniper_precache.smx | Bin 5371 -> 5515 bytes .../optional/l4d2_tank_damage_cvars.smx | Bin 4319 -> 6768 bytes .../plugins/optional/survivor_mvp.smx | Bin 18816 -> 19048 bytes addons/sourcemod/scripting/1v1.sp | 6 +- addons/sourcemod/scripting/TickrateFixes.sp | 12 +- addons/sourcemod/scripting/aitankgank.sp | 2 + .../archive/include/l4d2util_stocks.inc | 2 +- addons/sourcemod/scripting/botpopstop.sp | 10 +- addons/sourcemod/scripting/caster_assister.sp | 50 +- addons/sourcemod/scripting/caster_system.sp | 10 + addons/sourcemod/scripting/code_patcher.sp | 30 +- addons/sourcemod/scripting/dhooks-test.sp | 2 + addons/sourcemod/scripting/double_getup.sp | 52 +- addons/sourcemod/scripting/eq_finale_tanks.sp | 2 + addons/sourcemod/scripting/ghost_hurt.sp | 4 + addons/sourcemod/scripting/holdout_bonus.sp | 50 +- addons/sourcemod/scripting/include/colors.inc | 12 +- .../scripting/include/l4d2util_constants.inc | 57 +- .../scripting/include/l4d2util_infected.inc | 36 +- .../scripting/include/l4d2util_stocks.inc | 52 +- .../scripting/include/l4d2util_survivors.inc | 32 +- .../scripting/include/l4d2util_tanks.inc | 11 +- .../scripting/include/l4d2util_weapons.inc | 64 +- .../scripting/include/left4dhooks.inc | 313 +- addons/sourcemod/scripting/include/smac.inc | 129 + .../scripting/include/smac_stocks.inc | 334 ++ .../sourcemod/scripting/infected_flow_warp.sp | 25 +- addons/sourcemod/scripting/l4d2_antibaiter.sp | 12 +- .../scripting/l4d2_blind_infected.sp | 14 +- .../scripting/l4d2_car_alarm_hittable_fix.sp | 6 +- .../scripting/l4d2_charger_getup_fix.sp | 23 +- .../scripting/l4d2_collision_adjustments.sp | 2 +- .../scripting/l4d2_drop_secondary.sp | 12 +- .../scripting/l4d2_fix_spawn_order.sp | 14 +- .../scripting/l4d2_getup_slide_fix.sp | 65 +- addons/sourcemod/scripting/l4d2_getupfix.sp | 28 +- .../scripting/l4d2_godframes_control_merge.sp | 25 +- .../scripting/l4d2_hittable_control.sp | 15 +- .../scripting/l4d2_hybrid_scoremod.sp | 20 +- .../scripting/l4d2_hybrid_scoremod_zone.sp | 20 +- .../scripting/l4d2_jockey_jumpcap_patch.sp | 8 +- .../sourcemod/scripting/l4d2_jockey_skeet.sp | 5 +- .../sourcemod/scripting/l4d2_ladderblock.sp | 2 +- .../sourcemod/scripting/l4d2_m2_control_eq.sp | 12 +- .../scripting/l4d2_map_transitions.sp | 2 + .../scripting/l4d2_melee_damage_control.sp | 10 +- .../sourcemod/scripting/l4d2_nobackjumps.sp | 6 +- .../scripting/l4d2_nosecondchances.sp | 3 + .../sourcemod/scripting/l4d2_nosey_parker.sp | 9 +- .../sourcemod/scripting/l4d2_penalty_bonus.sp | 10 + addons/sourcemod/scripting/l4d2_pickup.sp | 22 +- addons/sourcemod/scripting/l4d2_playstats.sp | 97 +- addons/sourcemod/scripting/l4d2_riotcops.sp | 4 +- .../scripting/l4d2_saferoom_item_remove.sp | 11 +- addons/sourcemod/scripting/l4d2_scoremod.sp | 5 +- addons/sourcemod/scripting/l4d2_setscores.sp | 2 +- .../scripting/l4d2_shadow_removal.sp | 29 +- addons/sourcemod/scripting/l4d2_si_ffblock.sp | 6 +- .../sourcemod/scripting/l4d2_si_staggers.sp | 16 +- .../scripting/l4d2_slowdown_control.sp | 15 +- .../scripting/l4d2_smg_reload_tweak.sp | 6 +- .../l4d2_smoker_drag_damage_interval.sp | 32 - .../l4d2_smoker_drag_damage_interval_zone.sp | 32 - .../scripting/l4d2_sniper_bodyshot.sp | 163 +- .../scripting/l4d2_sniper_precache.sp | 53 +- .../scripting/l4d2_spec_stays_spec.sp | 6 +- addons/sourcemod/scripting/l4d2_spitblock.sp | 10 +- addons/sourcemod/scripting/l4d2_stats.sp | 15 +- .../sourcemod/scripting/l4d2_tank_announce.sp | 2 +- .../scripting/l4d2_tank_attack_control.sp | 25 +- .../l4d2_tank_attack_control_nextmod.sp | 3 +- .../scripting/l4d2_tank_damage_cvars.sp | 115 +- .../scripting/l4d2_tank_props_glow.sp | 6 +- .../sourcemod/scripting/l4d2_tongue_timer.sp | 55 +- .../sourcemod/scripting/l4d2_ultra_witch.sp | 2 +- .../scripting/l4d2_uncommon_blocker.sp | 9 +- .../scripting/l4d2_unsilent_jockey.sp | 16 +- .../sourcemod/scripting/l4d2_user_commands.sp | 2 +- .../sourcemod/scripting/l4d2_weaponrules.sp | 30 +- addons/sourcemod/scripting/l4d2lib/mapinfo.sp | 4 + addons/sourcemod/scripting/l4d2lib/tanks.sp | 2 + .../sourcemod/scripting/l4d_boss_percent.sp | 12 + addons/sourcemod/scripting/l4d_boss_vote.sp | 64 +- addons/sourcemod/scripting/l4d_ci_ffblock.sp | 5 +- .../scripting/l4d_jockey_ledgehang.sp | 2 +- addons/sourcemod/scripting/l4d_skip_intro.sp | 2 + .../scripting/l4d_stuckzombiemeleefix.sp | 39 +- .../scripting/l4d_tank_control_eq.sp | 24 +- .../scripting/l4d_tank_damage_announce.sp | 4 +- addons/sourcemod/scripting/l4d_tank_rush.sp | 6 +- .../scripting/l4d_tankpunchstuckfix.sp | 2 +- .../sourcemod/scripting/l4d_weapon_limits.sp | 28 +- addons/sourcemod/scripting/left4dhooks.sp | 5147 ++++++++++------- .../sourcemod/scripting/left4dhooks_test.sp | 968 +++- addons/sourcemod/scripting/lerpmonitor.sp | 6 +- addons/sourcemod/scripting/noteam_nudging.sp | 3 +- addons/sourcemod/scripting/pause.sp | 54 +- addons/sourcemod/scripting/pill_passer.sp | 12 +- .../sourcemod/scripting/playermanagement.sp | 6 +- .../scripting/predictable_unloader.sp | 11 +- addons/sourcemod/scripting/ratemonitor.sp | 14 +- addons/sourcemod/scripting/readyup.sp | 58 +- .../sourcemod/scripting/rock_stumble_block.sp | 13 +- .../sourcemod/scripting/si_class_announce.sp | 26 +- .../sourcemod/scripting/si_fire_immunity.sp | 2 + addons/sourcemod/scripting/spechud.sp | 49 +- addons/sourcemod/scripting/starting_items.sp | 16 +- addons/sourcemod/scripting/survivor_mvp.sp | 58 +- .../sourcemod/scripting/sv_consistency_fix.sp | 1 + addons/sourcemod/scripting/tankdoorfix.sp | 4 +- addons/sourcemod/scripting/temphealthfix.sp | 8 +- .../sourcemod/scripting/visualise_impacts.sp | 2 + .../scripting/weapon_loadout_vote.sp | 23 +- .../scripting/witch_and_tankifier.sp | 36 +- 119 files changed, 6642 insertions(+), 3450 deletions(-) create mode 100644 addons/sourcemod/scripting/include/smac.inc create mode 100644 addons/sourcemod/scripting/include/smac_stocks.inc diff --git a/addons/sourcemod/gamedata/left4dhooks.l4d2.txt b/addons/sourcemod/gamedata/left4dhooks.l4d2.txt index 626182b45..504bf2a98 100644 --- a/addons/sourcemod/gamedata/left4dhooks.l4d2.txt +++ b/addons/sourcemod/gamedata/left4dhooks.l4d2.txt @@ -12,7 +12,77 @@ // ==================================================================================================== "Functions" { - "CDeathFallCamera::Enable" + "L4DD::CTankClaw::DoSwing" + { + "signature" "CTankClaw::DoSwing" + "callconv" "thiscall" + "return" "void" + "this" "entity" + } + + "L4DD::CTankClaw::GroundPound" + { + "signature" "CTankClaw::GroundPound" + "callconv" "thiscall" + "return" "void" + "this" "entity" + } + + "L4DD::CTankClaw::OnPlayerHit" + { + "signature" "CTankClaw::OnPlayerHit" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "player" + { + "type" "cbaseentity" + } + "incap" + { + "type" "bool" + } + } + } + + "L4DD::CTankRock::Detonate" + { + "signature" "CTankRock::Detonate" + "callconv" "thiscall" + "return" "void" + "this" "entity" + } + + "L4DD::CTankRock::OnRelease" + { + "signature" "CTankRock::OnRelease" + "callconv" "thiscall" + "return" "void" + "this" "entity" + "arguments" + { + "vec" + { + "type" "vectorptr" + } + "ang" + { + "type" "vectorptr" + } + "vec2" + { + "type" "vectorptr" + } + "vec3" + { + "type" "vectorptr" + } + } + } + + "L4DD::CDeathFallCamera::Enable" { "signature" "CDeathFallCamera::Enable" "callconv" "thiscall" @@ -27,7 +97,7 @@ } } - "CTerrorPlayer::Fling" + "L4DD::CTerrorPlayer::Fling" { "signature" "CTerrorPlayer::Fling" "callconv" "thiscall" @@ -54,7 +124,7 @@ } } - "CTerrorPlayer::OnFalling" + "L4DD::CTerrorPlayer::OnFalling" { "signature" "CTerrorPlayer::OnFalling" "callconv" "thiscall" @@ -62,7 +132,7 @@ "this" "entity" } - "Tank::EnterStasis" + "L4DD::Tank::EnterStasis" { "signature" "Tank::EnterStasis" "callconv" "thiscall" @@ -70,7 +140,7 @@ "this" "entity" } - "Tank::LeaveStasis" + "L4DD::Tank::LeaveStasis" { "signature" "Tank::LeaveStasis" "callconv" "thiscall" @@ -78,9 +148,9 @@ "this" "entity" } - "GetRandomPZSpawnPosition" + "L4DD::ZombieManager::GetRandomPZSpawnPosition" { - "signature" "GetRandomPZSpawnPosition" + "signature" "ZombieManager::GetRandomPZSpawnPosition" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -105,9 +175,9 @@ } } - "SpawnSpecial" + "L4DD::ZombieManager::SpawnSpecial" { - "signature" "SpawnSpecial" + "signature" "ZombieManager::SpawnSpecial" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -128,9 +198,9 @@ } } - "SpawnTank" + "L4DD::ZombieManager::SpawnTank" { - "signature" "SpawnTank" + "signature" "ZombieManager::SpawnTank" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -147,9 +217,9 @@ } } - "SpawnWitch" + "L4DD::ZombieManager::SpawnWitch" { - "signature" "SpawnWitch" + "signature" "ZombieManager::SpawnWitch" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -166,9 +236,9 @@ } } - "SpawnWitchBride" + "L4DD::ZombieManager::SpawnWitchBride" { - "signature" "SpawnWitchBride" + "signature" "ZombieManager::SpawnWitchBride" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -185,17 +255,17 @@ } } - "OnMobRushStart" + "L4DD::CDirector::OnMobRushStart" { - "signature" "OnMobRushStart" + "signature" "CDirector::OnMobRushStart" "callconv" "thiscall" "return" "int" "this" "ignore" } - "SpawnITMob" + "L4DD::ZombieManager::SpawnITMob" { - "signature" "SpawnITMob" + "signature" "ZombieManager::SpawnITMob" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -208,9 +278,9 @@ } } - "SpawnMob" + "L4DD::ZombieManager::SpawnMob" { - "signature" "SpawnMob" + "signature" "ZombieManager::SpawnMob" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -223,17 +293,17 @@ } } - "OnEnterGhostState" + "L4DD::CTerrorPlayer::OnEnterGhostState" { - "signature" "OnEnterGhostState" + "signature" "CTerrorPlayer::OnEnterGhostState" "callconv" "thiscall" "return" "int" "this" "entity" } - "IsTeamFull" + "L4DD::CDirector::IsTeamFull" { - "signature" "IsTeamFull" + "signature" "CDirector::IsTeamFull" "callconv" "thiscall" "return" "bool" "arguments" @@ -249,9 +319,9 @@ } } - "ClearTeamScores" + "L4DD::CTerrorGameRules::ClearTeamScores" { - "signature" "ClearTeamScores" + "signature" "CTerrorGameRules::ClearTeamScores" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -264,9 +334,9 @@ } } - "SetCampaignScores" + "L4DD::CTerrorGameRules::SetCampaignScores" { - "signature" "SetCampaignScores" + "signature" "CTerrorGameRules::SetCampaignScores" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -283,9 +353,9 @@ } } - "OnFirstSurvivorLeftSafeArea" + "L4DD::CDirector::OnFirstSurvivorLeftSafeArea" { - "signature" "OnFirstSurvivorLeftSafeArea" + "signature" "CDirector::OnFirstSurvivorLeftSafeArea" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -298,33 +368,33 @@ } } - "GetCrouchTopSpeed" + "L4DD::CTerrorPlayer::GetCrouchTopSpeed" { - "signature" "GetCrouchTopSpeed" + "signature" "CTerrorPlayer::GetCrouchTopSpeed" "callconv" "thiscall" "return" "float" "this" "entity" } - "GetRunTopSpeed" + "L4DD::CTerrorPlayer::GetRunTopSpeed" { - "signature" "GetRunTopSpeed" + "signature" "CTerrorPlayer::GetRunTopSpeed" "callconv" "thiscall" "return" "float" "this" "entity" } - "GetWalkTopSpeed" + "L4DD::CTerrorPlayer::GetWalkTopSpeed" { - "signature" "GetWalkTopSpeed" + "signature" "CTerrorPlayer::GetWalkTopSpeed" "callconv" "thiscall" "return" "float" "this" "entity" } - "GetScriptValueInt" + "L4DD::CDirector::GetScriptValueInt" { - "signature" "GetScriptValueInt" + "signature" "CDirector::GetScriptValueInt" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -341,9 +411,9 @@ } } - "GetScriptValueFloat" + "L4DD::CDirector::GetScriptValueFloat" { - "signature" "GetScriptValueFloat" + "signature" "CDirector::GetScriptValueFloat" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -360,9 +430,9 @@ } } - "GetScriptValueString" + "L4DD::CDirector::GetScriptValueString" { - "signature" "GetScriptValueString" + "signature" "CDirector::GetScriptValueString" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -387,33 +457,33 @@ } } - "HasConfigurableDifficulty" + "L4DD::CTerrorGameRules::HasConfigurableDifficultySetting" { - "signature" "HasConfigurableDifficulty" + "signature" "CTerrorGameRules::HasConfigurableDifficultySetting" "callconv" "thiscall" "return" "int" "this" "ignore" } - "GetSurvivorSet" + "L4DD::CTerrorGameRules::GetSurvivorSet" { - "signature" "GetSurvivorSet" + "signature" "CTerrorGameRules::GetSurvivorSet" "callconv" "thiscall" "return" "int" "this" "ignore" } - "FastGetSurvivorSet" + "L4DD::CTerrorGameRules::FastGetSurvivorSet" { - "signature" "FastGetSurvivorSet" + "signature" "CTerrorGameRules::FastGetSurvivorSet" "callconv" "thiscall" "return" "int" "this" "ignore" } - "GetMissionVersusBossSpawning" + "L4DD::CDirectorVersusMode::GetMissionVersusBossSpawning" { - "signature" "GetMissionVersusBossSpawning" + "signature" "CDirectorVersusMode::GetMissionVersusBossSpawning" "callconv" "thiscall" "return" "bool" "this" "ignore" @@ -442,9 +512,9 @@ } } - "ReplaceTank" + "L4DD::ZombieManager::ReplaceTank" { - "signature" "ReplaceTank" + "signature" "ZombieManager::ReplaceTank" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -461,9 +531,9 @@ } } - "TryOfferingTankBot" + "L4DD::CDirector::TryOfferingTankBot" { - "signature" "TryOfferingTankBot" + "signature" "CDirector::TryOfferingTankBot" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -480,17 +550,17 @@ } } - "CThrowActivate" + "L4DD::CThrow::ActivateAbililty" { - "signature" "CThrowActivate" + "signature" "CThrow::ActivateAbililty" "callconv" "thiscall" "return" "int" "this" "entity" } - "SelectTankAttack" + "L4DD::CBaseAnimating::SelectWeightedSequence" { - "signature" "SelectWeightedSequence" + "signature" "CBaseAnimating::SelectWeightedSequence" "callconv" "thiscall" "return" "int" "this" "entity" @@ -503,9 +573,24 @@ } } - "StartMeleeSwing" + "L4DD::CTerrorMeleeWeapon::GetDamageForVictim" + { + "signature" "CTerrorMeleeWeapon::GetDamageForVictim" + "callconv" "thiscall" + "return" "float" + "this" "entity" + "arguments" + { + "victim" + { + "type" "cbaseentity" + } + } + } + + "L4DD::CTerrorMeleeWeapon::StartMeleeSwing" { - "signature" "StartMeleeSwing" + "signature" "CTerrorMeleeWeapon::StartMeleeSwing" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -523,9 +608,9 @@ } /* Works for Linux L4D2 but not L4D1, currently leaving out - "SendInRescueVehicle" + "L4DD::CDirectorScriptedEventManager::SendInRescueVehicle" { - "signature" "SendInRescueVehicle" + "signature" "CDirectorScriptedEventManager::SendInRescueVehicle" "callconv" "cdecl" "return" "void" "arguments" @@ -546,17 +631,17 @@ } } */ - "SendInRescueVehicle" + "L4DD::CDirectorScriptedEventManager::SendInRescueVehicle" { - "signature" "SendInRescueVehicle" + "signature" "CDirectorScriptedEventManager::SendInRescueVehicle" "callconv" "thiscall" "return" "int" "this" "ignore" } - "ChangeFinaleStage" + "L4DD::CDirectorScriptedEventManager::ChangeFinaleStage" { - "signature" "ChangeFinaleStage" + "signature" "CDirectorScriptedEventManager::ChangeFinaleStage" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -573,9 +658,9 @@ } } - "EndVersusModeRound" + "L4DD::CDirectorVersusMode::EndVersusModeRound" { - "signature" "EndVersusModeRound" + "signature" "CDirectorVersusMode::EndVersusModeRound" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -588,9 +673,9 @@ } } - "OnLedgeGrabbed" + "L4DD::CTerrorPlayer::OnLedgeGrabbed" { - "signature" "OnLedgeGrabbed" + "signature" "CTerrorPlayer::OnLedgeGrabbed" "callconv" "thiscall" "return" "void" "this" "entity" @@ -603,17 +688,17 @@ } } - "OnRevived" + "L4DD::CTerrorPlayer::OnRevived" { - "signature" "OnRevived" + "signature" "CTerrorPlayer::OnRevived" "callconv" "thiscall" "return" "int" "this" "entity" } - "OnStaggered" + "L4DD::CTerrorPlayer::OnStaggered" { - "signature" "OnStaggered" + "signature" "CTerrorPlayer::OnStaggered" "callconv" "thiscall" "return" "void" "this" "entity" @@ -630,9 +715,9 @@ } } - "OnShovedBySurvivor" + "L4DD::CTerrorPlayer::OnShovedBySurvivor" { - "signature" "OnShovedBySurvivor" + "signature" "CTerrorPlayer::OnShovedBySurvivor" "callconv" "thiscall" "return" "int" "this" "entity" @@ -649,9 +734,9 @@ } } - "OnHit" + "L4DD::CTerrorWeapon::OnHit" { - "signature" "OnHit" + "signature" "CTerrorWeapon::OnHit" "callconv" "thiscall" "return" "int" "this" "entity" @@ -672,9 +757,9 @@ } } - "OnShovedByPounceLanding" + "L4DD::CTerrorPlayer::OnShovedByPounceLanding" { - "signature" "OnShovedByPounceLanding" + "signature" "CTerrorPlayer::OnShovedByPounceLanding" "callconv" "thiscall" "return" "float" "this" "entity" @@ -691,9 +776,9 @@ } } - "Spread" + "L4DD::CInferno::Spread" { - "signature" "Spread" + "signature" "CInferno::Spread" "callconv" "thiscall" "return" "int" "this" "entity" @@ -706,9 +791,111 @@ } } - "OnVomitedUpon" + "L4DD::CPipeBombProjectile::Create" { - "signature" "CTerrorPlayer_OnVomitedUpon" + "signature" "CPipeBombProjectile::Create" + "callconv" "cdecl" + "return" "cbaseentity" + "arguments" + { + "origin" + { + "type" "vectorptr" + } + "angles" + { + "type" "vectorptr" + } + "velocity" + { + "type" "vectorptr" + } + "rotation" + { + "type" "vectorptr" + } + "owner" + { + "type" "cbaseentity" + } + "duration" + { + "type" "float" + } + } + } + + "L4DD::CTerrorPlayer::Extinguish" + { + "signature" "CTerrorPlayer::Extinguish" + "callconv" "thiscall" + "return" "void" + "this" "entity" + } + + "L4DD::CTerrorPlayer::OnPouncedOnSurvivor" + { + "signature" "CTerrorPlayer::OnPouncedOnSurvivor" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + } + } + + "L4DD::CTerrorPlayer::GrabVictimWithTongue" + { + "signature" "CTerrorPlayer::GrabVictimWithTongue" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + } + } + + "L4DD::CTerrorPlayer::OnLeptOnSurvivor" + { + "signature" "CTerrorPlayer::OnLeptOnSurvivor" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + } + } + + "L4DD::CTerrorPlayer::OnStartCarryingVictim" + { + "signature" "CTerrorPlayer::OnStartCarryingVictim" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + } + } + + "L4DD::CTerrorPlayer::OnVomitedUpon" + { + "signature" "CTerrorPlayer::OnVomitedUpon" "callconv" "thiscall" "return" "int" "this" "entity" @@ -725,9 +912,9 @@ } } - "OnHitByVomitJar" + "L4DD::CTerrorPlayer::OnHitByVomitJar" { - "signature" "CTerrorPlayer_OnHitByVomitJar" + "signature" "CTerrorPlayer::OnHitByVomitJar" "callconv" "thiscall" "return" "int" "this" "entity" @@ -740,17 +927,17 @@ } } - "OnMaterializeFromGhost" + "L4DD::CTerrorPlayer::MaterializeFromGhost" { - "signature" "MaterializeFromGhost" + "signature" "CTerrorPlayer::MaterializeFromGhost" "callconv" "thiscall" "return" "void" "this" "entity" } - "UseHealingItems" + "L4DD::SurvivorBot::UseHealingItems" { - "signature" "UseHealingItems" + "signature" "SurvivorBot::UseHealingItems" "callconv" "thiscall" "return" "int" "this" "entity" @@ -767,9 +954,9 @@ } } - "FindScavengeItem" + "L4DD::SurvivorBot::FindScavengeItem" { - "signature" "FindScavengeItem" + "signature" "SurvivorBot::FindScavengeItem" "callconv" "thiscall" "return" "cbaseentity" "this" "entity" @@ -782,10 +969,9 @@ } } - /* cdecl BossZombiePlayerBot::ChooseVictim(BossZombiePlayerBot *this, CTerrorPlayer *, char, CBaseCombatCharacter *) */ - "ChooseVictim" + "L4DD::BossZombiePlayerBot::ChooseVictim" { - "signature" "ChooseVictim" + "signature" "BossZombiePlayerBot::ChooseVictim" "callconv" "thiscall" "return" "cbaseentity" "this" "entity" @@ -806,7 +992,75 @@ } } - "OnVocalize" + "L4DD::CInsectSwarm::CanHarm" + { + "signature" "CInsectSwarm::CanHarm" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "CBaseEntity" + { + "type" "cbaseentity" + } + } + } + + "L4DD::CBreakableProp::Break" + { + "signature" "CBreakableProp::Break" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "entity" + { + "type" "cbaseentity" + } + "a3" + { + "type" "int" + } + } + } + + "L4DD::CGasCan::Event_Killed" + { + "signature" "CGasCan::Event_Killed" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "entity" + { + "type" "objectptr" + } + } + } + + "L4DD::CGasCan::OnActionComplete" + { + "signature" "CGasCan::OnActionComplete" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "client" + { + "type" "cbaseentity" + } + "entity" + { + "type" "cbaseentity" + } + } + } + + "L4DD::OnVocalize" { "signature" "Vocalize" "callconv" "thiscall" @@ -830,9 +1084,9 @@ } // Addons Disabler - "FillServerInfo" + "L4DD::CBaseServer::FillServerInfo" { - "signature" "FillServerInfo" + "signature" "CBaseServer::FillServerInfo" "callconv" "thiscall" "return" "int" "this" "address" @@ -848,9 +1102,9 @@ // UNUSED - "InfectedShoved" + "L4DD::InfectedShoved::OnShoved" { - "signature" "InfectedShoved" + "signature" "InfectedShoved::OnShoved" "callconv" "thiscall" "return" "int" "this" "ignore" @@ -867,9 +1121,9 @@ } } - "WaterMove" + "L4DD::CBasePlayer::WaterMove" { - "signature" "WaterMove" + "signature" "CBasePlayer::WaterMove" "callconv" "thiscall" "return" "int" "this" "entity" @@ -887,7 +1141,7 @@ { "windows" { - "signature" "DirectorMusicBanks_OnRoundStart" + "signature" "CDirectorMusicBanks::OnRoundStart" "read" "12" } "linux" @@ -915,12 +1169,12 @@ { "windows" { - "signature" "CVEngineServer_CreateFakeClient" + "signature" "CVEngineServer::CreateFakeClient" "read" "8" } "linux" { - "signature" "CVEngineServer_CreateFakeClient" + "signature" "CVEngineServer::CreateFakeClient" "read" "12" } } @@ -992,7 +1246,7 @@ } } - "ForceNextStage" + "CDirector::ForceNextStage" { "windows" { @@ -1004,17 +1258,17 @@ } } - "ForceNextStageAddress" + "CDirector::ForceNextStage::Address" { "windows" { - "signature" "ForceNextStageAddress" + "signature" "CDirector::ForceNextStage" "read" "163" // Midway through nearer target call // "read" "1436" // From function start } "linux" { - "signature" "ForceNextStageAddress" + "signature" "CDirector::ForceNextStage" } } @@ -1076,13 +1330,13 @@ // VIRTUAL CALLS - "CBaseServer_GetClient" + "CBaseServer::GetClient" { "windows" "6" "linux" "7" } - "DoAnimationEvent" + "CTerrorPlayer::DoAnimationEvent" { "windows" "510" "linux" "511" @@ -1407,7 +1661,7 @@ "linux" "540" } - // l4d2weapons.inc offsets + // l4d2weapons.inc offsets - Offsets can be found in: "CTerrorWeaponInfo::Parse" and "CCSWeaponInfo::Parse" and "FileWeaponInfo_t::Parse" // L4D2IntWeapon "L4D2IntWeapon_Damage" { @@ -1570,7 +1824,7 @@ } /* CMeleeWeaponInfoStore::GetMeleeWeaponInfo(CMeleeWeaponInfoStore *this, int) */ - "GetMeleeWeaponInfo" + "CMeleeWeaponInfoStore::GetMeleeWeaponInfo" { "library" "server" "linux" "@_ZN21CMeleeWeaponInfoStore18GetMeleeWeaponInfoEi" @@ -1618,7 +1872,7 @@ /* * CEntityDissolve::Create(CBaseEntity *pTarget, const char *pMaterialName, float flStartTime, int nDissolveType, bool *pRagdollCreated) */ - "CEntityDissolve_Create" + "CEntityDissolve::Create" { "library" "server" "linux" "@_ZN15CEntityDissolve6CreateEP11CBaseEntityPKcfiPb" @@ -1655,7 +1909,7 @@ /* * CTerrorGameRules::HasPlayerControlledZombies() */ - "HasPlayerControlledZombies" + "CTerrorGameRules::HasPlayerControlledZombies" { "library" "server" "linux" "@_ZN16CTerrorGameRules26HasPlayerControlledZombiesEv" @@ -1668,18 +1922,18 @@ * CPipeBombProjectile::Create(Vector const&, QAngle const&, Vector const&, Vector const&, CBaseCombatCharacter *, float) * Search: "BEEP_CONTEXT" */ - "CPipeBombProjectile_Create" + "CPipeBombProjectile::Create" { "library" "server" "linux" "@_ZN19CPipeBombProjectile6CreateERK6VectorRK6QAngleS2_S2_P20CBaseCombatCharacterf" - "windows" "\x55\x8B\x2A\x8B\x2A\x2A\x8B\x2A\x2A\x53\x8B\x2A\x2A\x56\x57\x50\x51\x53\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B" - /* 55 8B ? 8B ? ? 8B ? ? 53 8B ? ? 56 57 50 51 53 68 ? ? ? ? E8 ? ? ? ? 8B ? ? ? ? ? 83 ? ? ? ? ? ? 8B ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 68 ? ? ? ? E8 ? ? ? ? 8B */ + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x53\x8B\x2A\x2A\x56\x57\x50\x51\x53\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x68\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B" + /* ? ? ? ? ? ? 8B ? ? 53 8B ? ? 56 57 50 51 53 68 ? ? ? ? E8 ? ? ? ? 8B ? ? ? ? ? 83 ? ? ? ? ? ? 8B ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 68 ? ? ? ? E8 ? ? ? ? 8B */ } /* * CSpitterProjectile::Create(Vector const&,QAngle const&,Vector const&,Vector const&,CBaseCombatCharacter *) */ - "CSpitterProjectile_Create" + "CSpitterProjectile::Create" { "library" "server" "linux" "@_ZN18CSpitterProjectile6CreateERK6VectorRK6QAngleS2_S2_P20CBaseCombatCharacter" @@ -1691,7 +1945,7 @@ * CMolotovProjectile::Create(int, int, int, int, CBaseEntity *) * Search: "Molotov projectile spawned at %f %f %f" */ - "MolotovProjectile_Create" + "CMolotovProjectile::Create" { "library" "server" "linux" "@_ZN18CMolotovProjectile6CreateERK6VectorRK6QAngleS2_S2_P20CBaseCombatCharacter" @@ -1708,7 +1962,7 @@ * VomitJarProjectile::Create(int, int, int, int, CBaseEntity *) * Search: "VomitJar projectile spawned at %f %f %f" */ - "VomitJarProjectile_Create" + "VomitJarProjectile::Create" { "library" "server" "linux" "@_ZN19CVomitJarProjectile6CreateERK6VectorRK6QAngleS2_S2_P20CBaseCombatCharacter" @@ -1725,7 +1979,7 @@ * CGrenadeLauncher_Projectile::Create(int, int, int, int, CBaseEntity *, int) * Search: "VomitJar projectile spawned at %f %f %f" */ - "GrenadeLauncher_Create" + "CGrenadeLauncher_Projectile::Create" { "library" "server" "linux" "@_ZN27CGrenadeLauncher_Projectile6CreateERK6VectorRK6QAngleS2_S2_P20CBaseCombatCharacteri" @@ -1738,10 +1992,58 @@ /* Search for the literal string to then reverse bytes and search for that address. */ } + /* + * CTerrorPlayer::OnPouncedOnSurvivor(CTerrorPlayer *this, CTerrorPlayer *) + */ + "CTerrorPlayer::OnPouncedOnSurvivor" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer19OnPouncedOnSurvivorEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x55\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x81\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x00\x56\x57\x8B\x2A\x2A\x8B" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 81 ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? A1 ? ? ? ? 83 ? ? 00 56 57 8B ? ? 8B */ + /* Search: "%s pounced on %s, %d damage interrupts" */ // Found by "SilverShot". + } + + /* + * CTerrorPlayer::GrabVictimWithTongue(CTerrorPlayer *this, CTerrorPlayer *) + */ + "CTerrorPlayer::GrabVictimWithTongue" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer20GrabVictimWithTongueEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x55\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x83\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x56\x8B\x2A\x57\x89\x2A\x2A\x0F\x85\x2A\x2A\x2A\x2A\xE8" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 83 ? ? A1 ? ? ? ? 83 ? ? ? 56 8B ? 57 89 ? ? 0F 85 ? ? ? ? E8 */ + /* Search "Tongue grab starting." */ + } + + /* + * CTerrorPlayer::OnLeptOnSurvivor(CTerrorPlayer*) - Jockey hit Survivor function call + */ + "CTerrorPlayer::OnLeptOnSurvivor" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer16OnLeptOnSurvivorEPS_" + "windows" "\x55\x8B\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x2A\x57\x8B\x2A\x0F\x85\x2A\x2A\x2A\x2A\x56" + /* 55 8B ? A1 ? ? ? ? 83 ? ? 83 ? ? ? 57 8B ? 0F 85 ? ? ? ? 56 */ + /* Search: "JockeyZombie.Ride" */ // Found by "SilverShot". + } + + /* + * CTerrorPlayer::OnStartCarryingVictim(CTerrorPlayer *this, CTerrorPlayer *) + */ + "CTerrorPlayer::OnStartCarryingVictim" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer21OnStartCarryingVictimEPS_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x2A\x2A\x6A\x00\x6A\x00\x68\x2A\x2A\x2A\x2A\xFF\x2A\x8B\x2A\x85\x2A\x74\x2A\x8B\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x50\x8B\x2A\x2A\xFF\x2A\x8B\x2A\x50\x8B\x2A\x2A\x68\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x8B\x2A\x2A\x8B" + /* ? ? ? ? ? ? 8B ? 8B ? ? ? ? ? 8B ? 8B ? ? 6A 00 6A 00 68 ? ? ? ? FF ? 8B ? 85 ? 74 ? 8B ? ? 8B ? ? ? ? ? 8B ? 50 8B ? ? FF ? 8B ? 50 8B ? ? 68 ? ? ? ? 8B ? FF ? 8B ? ? 8B */ + /* Search: "charger_carry_start" */ // Found by "SilverShot". + } + /* * CTerrorPlayer::OnAdrenalineUsed(CTerrorPlayer *this, float) */ - "OnAdrenalineUsed" + "CTerrorPlayer::OnAdrenalineUsed" { "library" "server" "linux" "@_ZN13CTerrorPlayer16OnAdrenalineUsedEf" @@ -1750,10 +2052,29 @@ /* Search: "%s used adrenaline\n" call is 3rd above, match to Linux. */ } + /** + * Thanks to "Psyk0tik" from: https://github.com/Psykotikism/L4D1-2_Signatures/blob/main/gamedata/l4d_signatures.txt + * CTerrorPlayer::Extinguish() + * + * How to find on Windows: + * 1. Find the function's offsets with asherkin's VTable dump. + * 2. In IDA Pro, go to the ".rdata" section of the Windows binary. + * 3. Search for "CTerrorPlayer::`vftable'" to jump to the "CTerrorPlayer" vtable. + * 4. Compare your dump's offsets with asherkin's dump's offsets to find the target function. + * 5. Look for the target function in the Windows binary. + **/ + "CTerrorPlayer::Extinguish" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer10ExtinguishEv" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x53\x56\x57\x8B\x2A\x8B\xB7\x2A\x2A\x2A\x2A\x68" + /* ? ? ? ? ? ? 53 56 57 8B ? 8B B7 ? ? ? ? 68 */ + } + /* * ScriptClassDesc_t * GetScriptDesc(CDirector *) */ - "ForceNextStageAddress" + "CDirector::ForceNextStage" { "library" "server" "linux" "@_ZN9CDirector14ForceNextStageEv" @@ -1783,7 +2104,7 @@ /* * CDirector::IsTankInPlay(CDirector *this) */ - "IsTankInPlay" + "CDirector::IsTankInPlay" { "library" "server" "linux" "@_ZNK9CDirector12IsTankInPlayEv" @@ -1795,7 +2116,7 @@ /* * CDirector::GetFurthestSurvivorFlow(CDirector *this) */ - "GetFurthestSurvivorFlow" + "CDirector::GetFurthestSurvivorFlow" { "library" "server" "linux" "@_ZNK9CDirector23GetFurthestSurvivorFlowEv" @@ -1807,7 +2128,7 @@ /* * ZombieManager::GetRandomPZSpawnPosition(ZombieManager *_ZombieManager, int zombieClass, int attempts, int a4, int a5) */ - "GetRandomPZSpawnPosition" + "ZombieManager::GetRandomPZSpawnPosition" { "library" "server" "linux" "@_ZNK13ZombieManager24GetRandomPZSpawnPositionE15ZombieClassTypeiP13CTerrorPlayerP6Vector" @@ -1819,7 +2140,7 @@ /* * CNavMesh::GetNearestNavArea(CNavMesh *this, const Vector *, bool, float, bool, bool, bool) */ - "GetNearestNavArea" + "CNavMesh::GetNearestNavArea" { "library" "server" "linux" "@_ZNK8CNavMesh17GetNearestNavAreaERK6Vectorbfbbb" @@ -1831,19 +2152,7 @@ /* * TerrorNavArea::FindRandomSpot(TerrorNavArea *this) */ - "FindRandomSpot" - { - "library" "server" - "linux" "@_ZNK13TerrorNavArea14FindRandomSpotEv" - "windows" "\x55\x8B\x2A\xF3\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x56\x8B\x2A\xF3\x2A\x2A\x2A\x2A\xF3\x2A\x2A\x2A\x2A\x0F" - /* 55 8B ? F3 ? ? ? ? ? ? ? 83 ? ? 56 8B ? F3 ? ? ? ? F3 ? ? ? ? 0F */ - /* Search "Couldn't find a %s Spawn position in %d tries\n", some calls below */ - } - - /* - * TerrorNavArea::FindRandomSpot(TerrorNavArea *this) - */ - "FindRandomSpot" + "TerrorNavArea::FindRandomSpot" { "library" "server" "linux" "@_ZNK13TerrorNavArea14FindRandomSpotEv" @@ -1855,7 +2164,7 @@ /* * CDirector::HasAnySurvivorLeftSafeArea(CDirector *this) */ - "HasAnySurvivorLeftSafeArea" + "CDirector::HasAnySurvivorLeftSafeArea" { "library" "server" "linux" "@_ZN9CDirector26HasAnySurvivorLeftSafeAreaEv" @@ -1867,7 +2176,7 @@ /* * CDirector::IsAnySurvivorInStartArea(CDirector *__hidden this) */ - "IsAnySurvivorInStartArea" + "CDirector::IsAnySurvivorInStartArea" { "library" "server" "linux" "@_ZNK9CDirector24IsAnySurvivorInStartAreaEv" @@ -1879,7 +2188,7 @@ /* * CDirector::IsAnySurvivorInExitCheckpoint(CDirector *__hidden this) */ - "IsAnySurvivorInExitCheckpoint" + "CDirector::IsAnySurvivorInExitCheckpoint" { "library" "server" "linux" "@_ZNK9CDirector29IsAnySurvivorInExitCheckpointEv" @@ -1936,7 +2245,7 @@ } /* CTerrorGameRules::GetNumChaptersForMissionAndMode(CTerrorGameRules *__hidden this) */ - "GetNumChaptersForMissionAndMode" + "CTerrorGameRules::GetNumChaptersForMissionAndMode" { "library" "server" "linux" "@_ZN16CTerrorGameRules31GetNumChaptersForMissionAndModeEv" @@ -1946,7 +2255,7 @@ } /* CDirector::GetGameModeBase(CDirector *__hidden this) */ - "CDirector_GetGameModeBase" + "CDirector::GetGameModeBase" { "library" "server" "linux" "@_ZN9CDirector15GetGameModeBaseEv" @@ -1967,7 +2276,7 @@ * Make sure the one you have has like 11 xrefs, 6 from CCommentaryZombieSpawner::InputSpawnZombie * To find, look for non-unique string "common_", has three refs, one ref will have strings for all classes, that's CCommentaryZombieSpawner::InputSpawnZombie */ - "SpawnSpecial" + "ZombieManager::SpawnSpecial" { "library" "server" "linux" "@_ZN13ZombieManager12SpawnSpecialE15ZombieClassTypeRK6VectorRK6QAngle" @@ -1983,7 +2292,7 @@ * To find, look for non-unique string "common_", has three refs, one ref will have strings for all classes, that's CCommentaryZombieSpawner::InputSpawnZombie * SpawnTank will be called after string "tank" */ - "SpawnTank" + "ZombieManager::SpawnTank" { "library" "server" "linux" "@_ZN13ZombieManager9SpawnTankERK6VectorRK6QAngle" @@ -1999,7 +2308,7 @@ * To find, look for non-unique string "common_", has three refs, one ref will have strings for all classes, that's CCommentaryZombieSpawner::InputSpawnZombie * SpawnWitch will be called after string "witch" */ - "SpawnWitch" + "ZombieManager::SpawnWitch" { "library" "server" "linux" "@_ZN13ZombieManager10SpawnWitchERK6VectorRK6QAngle" @@ -2012,7 +2321,7 @@ * Has three xref, one is CInfoZombieSpawn::SpawnZombie (shared with SpawnWitch above) * where SpawnWitch is the third call after string "bride", and SpawnWitchBride is the second call after "bride" */ - "SpawnWitchBride" + "ZombieManager::SpawnWitchBride" { "library" "server" "linux" "@_ZN13ZombieManager15SpawnWitchBrideERK6VectorRK6QAngle" @@ -2025,7 +2334,7 @@ * * find by String: "MobMinSize", its inlined in Windows */ - "OnMobRushStart" + "CDirector::OnMobRushStart" { "library" "server" "linux" "@_ZN9CDirector14OnMobRushStartEv" @@ -2038,7 +2347,7 @@ * * search for unique strings with "SpawnITMob" */ - "SpawnITMob" + "ZombieManager::SpawnITMob" { "library" "server" "linux" "@_ZN13ZombieManager10SpawnITMobEi" @@ -2052,7 +2361,7 @@ * * search for unique strings with "SpawnMob" */ - "SpawnMob" + "ZombieManager::SpawnMob" { "library" "server" "linux" "@_ZN13ZombieManager8SpawnMobEi" @@ -2064,7 +2373,7 @@ * CTerrorPlayer::OnEnterGhostState() * almost unique string spawnmode_bar has three refs, one ref has strings "zombieClass" and "data" */ - "OnEnterGhostState" + "CTerrorPlayer::OnEnterGhostState" { "library" "server" "linux" "@_ZN13CTerrorPlayer17OnEnterGhostStateEv" @@ -2076,7 +2385,7 @@ * int CDirector::IsTeamFull(CTerrorGameRules *, int, int) * Search: "is auto-joining infected". Called from here. */ - "IsTeamFull" + "CDirector::IsTeamFull" { "library" "server" "linux" "@_ZNK9CDirector10IsTeamFullEiNS_15PlayerCountTypeE" @@ -2087,7 +2396,7 @@ /* * CTerrorGameRules::ClearTeamScores(bool) */ - "ClearTeamScores" + "CTerrorGameRules::ClearTeamScores" { "library" "server" "linux" "@_ZN16CTerrorGameRules15ClearTeamScoresEb" @@ -2104,7 +2413,7 @@ * -> first call is CTerrorGameRules::SetCampaignScores() * make sure to double check uniqueness when done */ - "SetCampaignScores" + "CTerrorGameRules::SetCampaignScores" { "library" "server" "linux" "@_ZN16CTerrorGameRules17SetCampaignScoresEii" @@ -2117,7 +2426,7 @@ * * string "Allowing spawning - %s left safe area\n" */ - "OnFirstSurvivorLeftSafeArea" + "CDirector::OnFirstSurvivorLeftSafeArea" { "library" "server" "linux" "@_ZN9CDirector27OnFirstSurvivorLeftSafeAreaEP13CTerrorPlayer" @@ -2130,7 +2439,7 @@ * CTerrorPlayer::GetCrouchTopSpeed(void)const * an xref from GetRunTopSpeed */ - "GetCrouchTopSpeed" + "CTerrorPlayer::GetCrouchTopSpeed" { "library" "server" "linux" "@_ZNK13CTerrorPlayer17GetCrouchTopSpeedEv" @@ -2143,7 +2452,7 @@ * * - Only references to float value 115.0 (00 00 E6 42) are in this func. */ - "GetRunTopSpeed" + "CTerrorPlayer::GetRunTopSpeed" { "library" "server" "linux" "@_ZNK13CTerrorPlayer14GetRunTopSpeedEv" @@ -2155,7 +2464,7 @@ * CTerrorPlayer::GetWalkTopSpeed(void)const * an xref from GetRunTopSpeed */ - "GetWalkTopSpeed" + "CTerrorPlayer::GetWalkTopSpeed" { "library" "server" "linux" "@_ZNK13CTerrorPlayer15GetWalkTopSpeedEv" @@ -2168,7 +2477,7 @@ * Find CTerrorPlayer::OnRevived(), then look for string SurvivorMaxIncapacitatedCount * If you look for string "No conversion from %s to int now\n" you will be one call too deep */ - "GetScriptValueInt" + "CDirector::GetScriptValueInt" { "library" "server" "linux" "@_ZN9CDirector14GetScriptValueEPKci" @@ -2180,7 +2489,7 @@ * CDirector::GetScriptValue(const char*, float) * Called in CDirector::OnMobRushStart */ - "GetScriptValueFloat" + "CDirector::GetScriptValueFloat" { "library" "server" "linux" "@_ZN9CDirector14GetScriptValueEPKcf" @@ -2192,7 +2501,7 @@ * CDirector::GetScriptValue(const char*, const char*, char*, int) * unique string "OnChangeFinaleMusic", call right after it */ - "GetScriptValueString" + "CDirector::GetScriptValueString" { "library" "server" "linux" "@_ZN9CDirector14GetScriptValueEPKcS1_Pci" @@ -2205,7 +2514,7 @@ * * - Look for string "hasdifficulty" */ - "HasConfigurableDifficulty" + "CTerrorGameRules::HasConfigurableDifficultySetting" { "library" "server" "linux" "@_ZN16CTerrorGameRules32HasConfigurableDifficultySettingEv" @@ -2317,12 +2626,110 @@ /* ? ? ? ? ? ? ? ? ? ? ? 8D B7 ? ? ? ? 74 ? 8B 86 ? ? ? ? 8B 90 ? ? ? ? 8D 8E ? ? ? ? 56 FF ? C6 ? ? 8B ? 8B 90 ? ? ? ? 8B */ } + /** + * Thanks to "Psyk0tik" from: https://github.com/Psykotikism/L4D1-2_Signatures/blob/main/gamedata/l4d_signatures.txt + * CTankClaw::SweepFist(Vector const&, Vector const&) + * + * How to find on Windows: + * 1a. Search for any of the following strings (they can each only be found in this function): + * - "rhand" + * - "lhand" + * - "ValveBiped.Bip01_L_Hand" + * 1b. Search for the "ValveBiped.Bip01_R_Hand" string. + * 2b. One of the functions that references that string should be this function. + **/ + "CTankClaw::DoSwing" + { + "library" "server" + "linux" "@_ZN9CTankClaw7DoSwingEv" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x56\x89\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x2A\x85" + /* ? ? ? ? ? ? 56 89 ? ? E8 ? ? ? ? 8B ? 85 */ + } + + /** + * Thanks to "Psyk0tik" from: https://github.com/Psykotikism/L4D1-2_Signatures/blob/main/gamedata/l4d_signatures.txt + * CTankClaw::GroundPound() + * + * How to find on Windows: + * 1. Locate the "CTankClaw::SweepFist" function. + * 2. Click on the second to last function call to go to "CTerrorWeapon::MarkAsHit". + * 3. This function calls "CTerrorWeapon::MarkAsHit" twice. + * 4. To pinpoint the right function, look for the one that sets multiple variables to "0". + **/ + "CTankClaw::GroundPound" + { + "library" "server" + "linux" "@_ZN9CTankClaw11GroundPoundEv" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x55\x8B\x2A\x2A\x89\x2A\x2A\x2A\x8B\x2A\x81\xEC\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\x56\x57\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x8B\x2A\x89" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 81 EC ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 56 57 8B ? E8 ? ? ? ? 8B ? 89 */ + } + + /** + * Thanks to "Psyk0tik" from: https://github.com/Psykotikism/L4D1-2_Signatures/blob/main/gamedata/l4d_signatures.txt + * CTankClaw::OnPlayerHit(CTerrorPlayer*, bool) + * + * How to find on Windows: + * 1a. Search for the "PlayerGroundPoundedByTank" string. + * 2a. The string can only be found in this function. + * + * 1b. Find the function's offsets with asherkin's VTable dump. + * 2b. In IDA Pro, go to the ".rdata" section of the Windows binary. + * 3b. Search for "CTankClaw::`vftable'" to jump to the "CTankClaw" vtable. + * 4b. Compare your dump's offsets with asherkin's dump's offsets to find the target function. + * 5b. Look for the target function in the Windows binary. + **/ + "CTankClaw::OnPlayerHit" + { + "library" "server" + "linux" "@_ZN9CTankClaw11OnPlayerHitEP13CTerrorPlayerb" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\x53\x56\x8B\x2A\x2A\x57\x8B\x2A\x89\x2A\x2A\xE8" + /* ? ? ? ? ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 53 56 8B ? ? 57 8B ? 89 ? ? E8 */ + } + + /** + * Thanks to "Psyk0tik" from: https://github.com/Psykotikism/L4D1-2_Signatures/blob/main/gamedata/l4d_signatures.txt + * CTankRock::Detonate() + * + * How to find on Windows: + * 1a. Search for the "tank_rock_throw_impact_stump" string. + * 2a. The string can only be found in this function. + * + * 1b. Find the function's offsets with asherkin's VTable dump. + * 2b. In IDA Pro, go to the ".rdata" section of the Windows binary. + * 3b. Search for "CTankRock::`vftable'" to jump to the "CTankRock" vtable. + * 4b. Compare your dump's offsets with asherkin's dump's offsets to find the target function. + * 5b. Look for the target function in the Windows binary. + **/ + "CTankRock::Detonate" + { + "library" "server" + "linux" "@_ZN9CTankRock8DetonateEv" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x53\x56\x8B\x2A\x80\xBE\x2A\x2A\x2A\x2A\x2A\x57\x0F\x84\x2A\x2A\x2A\x2A\xA1" + /* ? ? ? ? ? ? 53 56 8B ? 80 BE ? ? ? ? ? 57 0F 84 ? ? ? ? A1 */ + } + + /** + * Thanks to "Psyk0tik" from: https://github.com/Psykotikism/L4D1-2_Signatures/blob/main/gamedata/l4d_signatures.txt + * CTankRock::OnRelease(Vector const&, QAngle const&, Vector const&, Vector const&) + * + * How to find on Windows: + * 1. Search for the "HulkZombie.Throw.FlyLoop" string. + * 2. One of the functions that references that string should be this function. + **/ + "CTankRock::OnRelease" + { + "library" "server" + "linux" "@_ZN9CTankRock9OnReleaseERK6VectorRK6QAngleS2_S2_" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x57\xC6\x86\x2A\x2A\x2A\x2A\x2A\xC7" + /* ? ? ? ? ? ? 57 C6 86 ? ? ? ? ? C7 */ + } + /* * CTerrorGameRules::GetSurvivorSet(void) * * - string "survivor_set" */ - "GetSurvivorSet" + "CTerrorGameRules::GetSurvivorSet" { "library" "server" "linux" "@_ZN16CTerrorGameRules14GetSurvivorSetEv" @@ -2336,7 +2743,7 @@ * * - Should be 2 calls after "DistToMechanic" in CTerrorPlayer::ModifyOrAppendCriteria */ - "FastGetSurvivorSet" + "CTerrorGameRules::FastGetSurvivorSet" { "library" "server" "linux" "@_ZN16CTerrorGameRules18FastGetSurvivorSetEv" @@ -2349,7 +2756,7 @@ * * - string "versus_boss_spawning" hits in 2 functions: This short func and the much longer InitVersusBossSpawning */ - "GetMissionVersusBossSpawning" + "CDirectorVersusMode::GetMissionVersusBossSpawning" { "library" "server" "linux" "@_ZN19CDirectorVersusMode28GetMissionVersusBossSpawningERfS0_S0_S0_Rb" @@ -2362,7 +2769,7 @@ * * for finding: in CDirector::UpdateTankSpawns, easily findable in graph view from ReplaceWithBot */ - "ReplaceTank" + "ZombieManager::ReplaceTank" { "library" "server" "linux" "@_ZN13ZombieManager11ReplaceTankEP13CTerrorPlayerS1_" @@ -2374,7 +2781,7 @@ * CDirector::TryOfferingTankBot(void) * unique string "Tank offer: Starting the lottery\n" */ - "TryOfferingTankBot" + "CDirector::TryOfferingTankBot" { "library" "server" "linux" "@_ZN9CDirector18TryOfferingTankBotEP11CBaseEntityb" @@ -2388,7 +2795,7 @@ * * - "HulkZombie.Throw.Fail" has 2 refs in this function. Should be easy to find. */ - "CThrowActivate" + "CThrow::ActivateAbililty" { "library" "server" "linux" "@_ZN6CThrow15ActivateAbilityEv" @@ -2402,7 +2809,7 @@ * - Called at the end of CTerrorPlayer::SelectWeightedSequence() (found via string "Hulk_RunAttack1_Gesture") * NOTE - WARNING - This function should probably be hooked using vtable methods!!!!!!!! DEPRECATE */ - "SelectWeightedSequence" + "CBaseAnimating::SelectWeightedSequence" { "library" "server" "linux" "@_ZN14CBaseAnimating22SelectWeightedSequenceE8Activity" @@ -2410,12 +2817,22 @@ /* 55 8B EC 56 8B F1 83 BE ? ? ? ? 00 57 8B BE */ } + /* Thanks to "Lux" for the signature */ + "CTerrorMeleeWeapon::GetDamageForVictim" + { + "library" "server" + "linux" "@_ZN18CTerrorMeleeWeapon18GetDamageForVictimEP11CBaseEntity" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x17\x00\x00\x56\x57" + /* ? ? ? ? ? ? 17 00 00 56 57 */ + /* Search "MeleeSlashSplatter" - the function with "MeleeClubSplatter" below, and "bloodslash" even lower down. */ + } + /* * CTerrorMeleeWeapon::StartMeleeSwing(CTerrorPlayer *, bool) * * find "melee attack failed - !IsWeaponVisible" in CTerrorWeapon::PrimaryAttack and look for a call (being passed ptr and float) followed by some sse xmm0 calls. */ - "StartMeleeSwing" + "CTerrorMeleeWeapon::StartMeleeSwing" { "library" "server" "linux" "@_ZN18CTerrorMeleeWeapon15StartMeleeSwingEP13CTerrorPlayerb" @@ -2429,7 +2846,7 @@ * * find by String "FinaleEscapeStarted" */ - "SendInRescueVehicle" + "CDirectorScriptedEventManager::SendInRescueVehicle" { "library" "server" "linux" "@_ZN29CDirectorScriptedEventManager19SendInRescueVehicleEv" @@ -2438,12 +2855,11 @@ } /* - * CDirectorScriptedEventManager__ChangeFinaleStage(int, char arg, int) - * or CDirectorScriptedEventManager::ChangeFinaleStage(CDirectorScriptedEventManager::FinaleStageType,char const*) + * CDirectorScriptedEventManager::ChangeFinaleStage(CDirectorScriptedEventManager::FinaleStageType,char const*) * * find by String "CHANGEFINALESTAGEOVERRIDE: %s\n" */ - "ChangeFinaleStage" + "CDirectorScriptedEventManager::ChangeFinaleStage" { "library" "server" "linux" "@_ZN29CDirectorScriptedEventManager17ChangeFinaleStageENS_18ScriptedEventStageEPKc" @@ -2458,7 +2874,7 @@ * * find by String "fullscreen_vs_scoreboard", and look for a func which also creates a "scores" kv and sets values for "t1", "t2", "c1", "c2", and "tiebreak" */ - "EndVersusModeRound" + "CDirectorVersusMode::EndVersusModeRound" { "library" "server" "linux" "@_ZN19CDirectorVersusMode18EndVersusModeRoundEb" @@ -2470,7 +2886,7 @@ * void CTerrorPlayer::OnLedgeGrabbed(CTerrorPlayer *this, const Vector *) * Search: "%s grabs a ledge - last standing at %s." */ - "OnLedgeGrabbed" + "CTerrorPlayer::OnLedgeGrabbed" { "library" "server" "linux" "@_ZN13CTerrorPlayer14OnLedgeGrabbedERK6Vector" @@ -2485,7 +2901,7 @@ * Left4Downtown2 patches this function, which will prevent Sourcemod from finding it * That is why the first six bytes are wild cards (five bytes for detour + nop fill the remaining bytes of the instructions) */ - "OnRevived" + "CTerrorPlayer::OnRevived" { "library" "server" "linux" "@_ZN13CTerrorPlayer9OnRevivedEv" @@ -2498,7 +2914,7 @@ * * - string "PlayerShoved" has 3 refs, the one furthest into a function should be this one. */ - "OnStaggered" + "CTerrorPlayer::OnStaggered" { "library" "server" "linux" "@_ZN13CTerrorPlayer11OnStaggeredEP11CBaseEntityPK6Vector" @@ -2512,7 +2928,7 @@ * CTerrorPlayer::OnShovedBySurvivor(CTerrorPlayer*, Vector const&) - used by L4D2 on Special Infected (got melee'd) * unique string "jockey_ride" in CTerrorPlayer::OnLeptOnSurvivor(), look up for "JockeyZombie.Ride", look up for var_14, CTerrorPlayer::OnShovedBySurvivor is call after that */ - "OnShovedBySurvivor" + "CTerrorPlayer::OnShovedBySurvivor" { "library" "server" "linux" "@_ZN13CTerrorPlayer18OnShovedBySurvivorEPS_RK6Vector" @@ -2523,7 +2939,7 @@ /* * CTerrorWeapon::OnHit(CGameTrace &, Vector const&, bool) */ - "OnHit" + "CTerrorWeapon::OnHit" { "library" "server" "linux" "@_ZN13CTerrorWeapon5OnHitER10CGameTraceRK6Vectorb" @@ -2534,7 +2950,7 @@ /* * CTerrorPlayer::OnShovedByPounceLanding(CTerrorPlayer*) */ - "OnShovedByPounceLanding" + "CTerrorPlayer::OnShovedByPounceLanding" { "library" "server" "linux" "@_ZN13CTerrorPlayer23OnShovedByPounceLandingEPS_b" @@ -2548,7 +2964,7 @@ /* * CInferno::Spread(Vector const&) */ - "Spread" + "CInferno::Spread" { "library" "server" "linux" "@_ZN8CInferno6SpreadERK6Vector" @@ -2562,7 +2978,7 @@ * Called by the game when deciding whether the bots should use any healing items * unique string "Trying to heal a friend" */ - "UseHealingItems" + "SurvivorBot::UseHealingItems" { "library" "server" "linux" "@_ZN11SurvivorBot15UseHealingItemsEP6ActionIS_E" @@ -2578,7 +2994,7 @@ * SurvivorBot::ScavengeNearbyItems(Action*) has almost unique string "Scavenging something" * FindScavengeItem(float) is called with 420.0 (0x43D20000) as its argument */ - "FindScavengeItem" + "SurvivorBot::FindScavengeItem" { "library" "server" "linux" "@_ZNK11SurvivorBot16FindScavengeItemEf" @@ -2586,12 +3002,54 @@ /* 55 8B EC 81 EC ? ? ? ? A1 ? ? ? ? 33 C5 89 45 FC 53 56 57 8B F9 8B 97 ? ? ? ? 8D 85 */ } + /* + * CInsectSwarm::CanHarm(CInsectSwarm *this, CBaseEntity *) + */ + "CInsectSwarm::CanHarm" + { + "library" "server" + "linux" "@_ZNK12CInsectSwarm7CanHarmEP11CBaseEntity" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x2A\xFF\x2A\x84\x2A\x74\x2A\x8B\x2A\xE8\x2A\x2A\x2A\x2A\x50\xE8\x2A\x2A\x2A\x2A\x83\x2A\x2A\x5E\x5D" + /* ? ? ? ? ? ? ? 8B ? 8B ? ? ? ? ? 8B ? FF ? 84 ? 74 ? 8B ? E8 ? ? ? ? 50 E8 ? ? ? ? 83 ? ? 5E 5D */ + /* Search: "spitter_areaofdenial". Few entries down in vtable. */ + } + + /* CBreakableProp::Break(CBreakableProp *this, CBaseEntity *a2, const CTakeDamageInfo *a3) */ + "CBreakableProp::Break" + { + "library" "server" + "linux" "@_ZN14CBreakableProp5BreakEP11CBaseEntityRK15CTakeDamageInfo" + "windows" "\x55\x8B\x2A\x81\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\x8B\x2A\x2A\x53\x8B\x2A\x2A\x56\x8B\x2A\x8B\x2A\x8B\x2A\x2A\x89" + /* 55 8B ? 81 ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 8B ? ? 53 8B ? ? 56 8B ? 8B ? 8B ? ? 89 */ + /* Search: "Fire prop detonated %.0f,%.0f,%.0f. Breaker:%s. Attacker:%s.\n" */ + } + + /* CGasCan::Event_Killed(CGasCan *this, const CTakeDamageInfo *) */ + "CGasCan::Event_Killed" + { + "library" "server" + "linux" "@_ZN7CGasCan12Event_KilledERK15CTakeDamageInfo" + "windows" "\x55\x8B\x2A\x81\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\x53\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x56\x8B\x2A\x2A\xC1" + /* 55 8B ? 81 ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 53 8B ? 8B ? ? ? ? ? 56 8B ? ? C1 */ + /* Search: "scavenge_gas_can_destroyed" */ + } + + /* CGasCan::OnActionComplete(CGasCan *this, CTerrorPlayer *, CBaseEntity *) */ + "CGasCan::OnActionComplete" + { + "library" "server" + "linux" "@_ZN7CGasCan16OnActionCompleteEP13CTerrorPlayerP11CBaseEntity" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xA1\x2A\x2A\x2A\x2A\x33\x2A\x89\x2A\x2A\x8B\x2A\x2A\x53\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x83" + /* ? ? ? ? ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 8B ? ? 53 8B ? 8B ? ? ? ? ? 83 */ + /* Search: "gascan_pour_completed" */ + } + /* cdecl BossZombiePlayerBot::ChooseVictim(BossZombiePlayerBot *this, CTerrorPlayer *, char, CBaseCombatCharacter *) */ - "ChooseVictim" + "BossZombiePlayerBot::ChooseVictim" { "library" "server" - "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x53\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x56" "linux" "@_ZN19BossZombiePlayerBot12ChooseVictimEP13CTerrorPlayeriP20CBaseCombatCharacter" + "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x83\x2A\x2A\x2A\x53\x8B\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x8B\x2A\x2A\x2A\x2A\x2A\x56" /* ? ? ? ? ? ? ? ? ? ? ? 83 ? ? ? 53 8B ? 8B ? ? ? ? ? 8B ? ? ? ? ? 56 */ // Wildcarded for 3rd party plugins /* 55 8B ? 83 ? ? ? ? ? ? ? 83 ? ? ? 53 8B ? 8B ? ? ? ? ? 8B */ /* Search: "switching to mobile victim" */ @@ -2610,7 +3068,7 @@ - Find it through only xref, which is setting up ScriptDesc structures: string "Trigger a mob as soon as possible when" - If you go past the first call, you should hit unique bytes in sig making */ - "ResetMobTimer" + "CDirector::ResetMobTimer" { "library" "server" "linux" "@_ZN9CDirector13ResetMobTimerEv" @@ -2625,7 +3083,7 @@ * -> has two xref, one is CRestartGameIssue::ExecuteCommand() (exclude the other, CServerGameDLL::ServerHibernationUpdate(), which has string "FCVAR_NEVER_AS_STRING") * -> Last call in CRestartGameIssue::ExecuteCommand */ - "RestartScenarioFromVote" + "CDirector::RestartScenarioFromVote" { "library" "server" "linux" "@_ZN9CDirector23RestartScenarioFromVoteEPKc" @@ -2640,7 +3098,7 @@ * -> showed up near "info_window" * -> called twice along with another function called twice (CterrorGameRules::UpdateChapterScores) */ - "GetTeamScore" + "CTerrorGameRules::GetTeamScore" { "library" "server" "linux" "@_ZN16CTerrorGameRules12GetTeamScoreEib" @@ -2653,7 +3111,7 @@ is a First map. Called from CDirector::OnEndScenario, look near string "vs_shutting_down", up to case 7 */ - "IsFirstMapInScenario" + "CDirector::IsFirstMapInScenario" { "library" "server" "linux" "@_ZNK9CDirector20IsFirstMapInScenarioEv" @@ -2666,7 +3124,7 @@ is a Final(e) map. Called from CDirectorVersusMode::EndVersusModeRound(), look near string "versus_match_finished" */ - "IsMissionFinalMap" + "CTerrorGameRules::IsMissionFinalMap" { "library" "server" "linux" "@_ZN16CTerrorGameRules17IsMissionFinalMapEv" @@ -2682,7 +3140,7 @@ - Find "Going to intermission...\n" in CGameRules::GoToIntermission - Last call in the func */ - "NotifyNetworkStateChanged" + "CGameRulesProxy::NotifyNetworkStateChanged" { "library" "server" "linux" "@_ZN15CGameRulesProxy25NotifyNetworkStateChangedEv" @@ -2692,7 +3150,7 @@ // find string " Highest survivor flow distance = %f Tank at = %f witch at %f\n" in CDirectorVersusMode::UpdateVersusBossSpawning // look for __RTDynamicCast which is called on the result of this function. - "GetNavArea" + "CNavMesh::GetNavArea" { "library" "server" "linux" "@_ZNK8CNavMesh10GetNavAreaERK6Vectorf" @@ -2703,7 +3161,7 @@ /* * CTerrorPlayer::GetFlowDistance(TerrorNavArea::FlowType) */ - "GetFlowDistance" + "CTerrorPlayer::GetFlowDistance" { "library" "server" "linux" "@_ZNK13CTerrorPlayer15GetFlowDistanceEN13TerrorNavArea8FlowTypeE" @@ -2718,7 +3176,7 @@ * *(director + offset) == ptr to CDirectorScavengeMode * has unique string "AlwaysAllowWanderers" */ - "AreWanderersAllowed" + "CDirector::AreWanderersAllowed" { "library" "server" "linux" "@_ZNK9CDirector19AreWanderersAllowedEv" @@ -2731,7 +3189,7 @@ * unique string "#L4D_idle_spectator" in CTerrorPlayer::PreThink() * CDirector::IsFinaleEscapeInProgress is a couple calls before the string, and a couple calls after CountdownTimer::Now */ - "IsFinaleEscapeInProgress" + "CDirector::IsFinaleEscapeInProgress" { "library" "server" "linux" "@_ZNK9CDirector24IsFinaleEscapeInProgressEv" @@ -2743,7 +3201,7 @@ * CTerrorPlayer::CanBecomeGhost(bool areSpawnsDisabled) * unique string "ghost_spawn_time" */ - "CanBecomeGhost" + "CTerrorPlayer::CanBecomeGhost" { "library" "server" "linux" "@_ZN13CTerrorPlayer14CanBecomeGhostEb" @@ -2755,7 +3213,7 @@ * CTerrorPlayer::TakeOverBot * unique string "[TAKEOVER]: %s (%d) possessed %s" */ - "TakeOverBot" + "CTerrorPlayer::TakeOverBot" { "library" "server" "linux" "@_ZN13CTerrorPlayer11TakeOverBotEb" @@ -2768,7 +3226,7 @@ * Very similar to BossZombiePlayerBot::SetHumanSpectator() * SurvivorBot version has 5 xref (one of them is CTerrorPlayer::TakeOverBot), BossZombie has just 1 (CTerrorPlayer::TakeOverBot) */ - "SetHumanSpec" + "SurvivorBot::SetHumanSpectator" { "library" "server" "linux" "@_ZN11SurvivorBot17SetHumanSpectatorEP13CTerrorPlayer" @@ -2784,7 +3242,7 @@ /* * CTerrorPlayer::OnVomitedUpon(CTerrorPlayer*, bool) */ - "CTerrorPlayer_OnVomitedUpon" + "CTerrorPlayer::OnVomitedUpon" { "library" "server" "linux" "@_ZN13CTerrorPlayer13OnVomitedUponEPS_b" @@ -2795,7 +3253,7 @@ /* * CTerrorPlayer::OnHitByVomitJar(CBaseCombatCharacter *) */ - "CTerrorPlayer_OnHitByVomitJar" + "CTerrorPlayer::OnHitByVomitJar" { "library" "server" "linux" "@_ZN13CTerrorPlayer15OnHitByVomitJarEP20CBaseCombatCharacter" @@ -2806,7 +3264,7 @@ /* * Infected::OnHitByVomitJar(CBaseCombatCharacter *) */ - "Infected_OnHitByVomitJar" + "Infected::OnHitByVomitJar" { "library" "server" "linux" "@_ZN8Infected15OnHitByVomitJarEP20CBaseCombatCharacter" @@ -2833,7 +3291,7 @@ /* * CTerrorPlayer::CancelStagger(void) - used by the game to stop Survivor Staggering as something else happens */ - "CancelStagger" + "CTerrorPlayer::CancelStagger" { "library" "server" "linux" "@_ZN13CTerrorPlayer13CancelStaggerEv" @@ -2846,7 +3304,7 @@ /* * CDirector::CreateRescuableSurvivors(void) */ - "CreateRescuableSurvivors" + "CDirector::CreateRescuableSurvivors" { "library" "server" "linux" "@_ZN9CDirector24CreateRescuableSurvivorsEv" @@ -2858,7 +3316,7 @@ /* * CTerrorGameRules::GetVersusCompletion(CTerrorPlayer *) */ - "GetVersusCompletionPlayer" + "CTerrorGameRules::GetVersusCompletion" { "library" "server" "linux" "@_ZN16CTerrorGameRules19GetVersusCompletionEP13CTerrorPlayer" @@ -2870,7 +3328,7 @@ /* * CDirectorTacticalServices::GetHighestFlowSurvivor(TerrorNavArea::FlowType)const */ - "GetHighestFlowSurvivor" + "CDirectorTacticalServices::GetHighestFlowSurvivor" { "library" "server" "linux" "@_ZNK25CDirectorTacticalServices22GetHighestFlowSurvivorEN13TerrorNavArea8FlowTypeE" @@ -2882,7 +3340,7 @@ /* * Infected::GetFlowDistance(void)const */ - "GetInfectedFlowDistance" + "Infected::GetFlowDistance" { "library" "server" "linux" "@_ZNK8Infected15GetFlowDistanceEv" @@ -2896,7 +3354,7 @@ * for finding: * "bot_player_replace" */ - "TakeOverZombieBot" + "CTerrorPlayer::TakeOverZombieBot" { "library" "server" "linux" "@_ZN13CTerrorPlayer17TakeOverZombieBotEPS_" @@ -2910,7 +3368,7 @@ * for finding: in CDirector::UpdateTankSpawns, easily findable in graph view * "TANK OFFER: No tickets, choosing random" */ - "ReplaceWithBot" + "CTerrorPlayer::ReplaceWithBot" { "library" "server" "linux" "@_ZN13CTerrorPlayer14ReplaceWithBotEb" @@ -2922,7 +3380,7 @@ * CTerrorPlayer::CullZombie(void) * Called in ReplaceTank, followed by a call to CCSPlayer::State_Transition */ - "CullZombie" + "CTerrorPlayer::CullZombie" { "library" "server" "linux" "@_ZN13CTerrorPlayer10CullZombieEv" @@ -2930,7 +3388,10 @@ /* 55 8B EC 83 EC ? 56 8B F1 8B 0D ? ? ? ? 57 56 E8 */ } - "SetClass" + /* + * CTerrorPlayer::SetClass(CBaseEntity *, int) + */ + "CTerrorPlayer::SetClass" { "library" "server" "linux" "@_ZN13CTerrorPlayer8SetClassE15ZombieClassType" @@ -2939,7 +3400,10 @@ /* Search "weapon_smoker_claw" */ } - "CreateAbility" + /* + * CBaseAbility::CreateForPlayer(CBaseAbility *this, CTerrorPlayer *) + */ + "CBaseAbility::CreateForPlayer" { "library" "server" "linux" "@_ZN12CBaseAbility15CreateForPlayerEP13CTerrorPlayer" @@ -2951,7 +3415,7 @@ /* * CTerrorPlayer::MaterializeFromGhost(void) */ - "MaterializeFromGhost" + "CTerrorPlayer::MaterializeFromGhost" { "library" "server" "linux" "@_ZN13CTerrorPlayer20MaterializeFromGhostEv" @@ -2961,7 +3425,7 @@ } /* CTerrorPlayer::BecomeGhost(bool) */ - "BecomeGhost" + "CTerrorPlayer::BecomeGhost" { "library" "server" "linux" "@_ZN13CTerrorPlayer11BecomeGhostEb" @@ -2970,7 +3434,7 @@ } /* CCSPlayer::State_Transition(CSPlayerState) */ - "State_Transition" + "CCSPlayer::State_Transition" { "library" "server" "linux" "@_ZN9CCSPlayer16State_TransitionE13CSPlayerState" @@ -2981,7 +3445,7 @@ /* * CDirector::SwapTeams(void) */ - "SwapTeams" + "CDirector::SwapTeams" { "library" "server" "linux" "@_ZN9CDirector9SwapTeamsEv" @@ -2995,7 +3459,7 @@ * got via CTerrorPlayer::UpdateTeamDesired and its String "CTerrorPlayer::UpdateTeamDesired error " * */ - "AreTeamsFlipped" + "CDirector::AreTeamsFlipped" { "library" "server" "linux" "@_ZNK9CDirector15AreTeamsFlippedEv" @@ -3006,7 +3470,7 @@ /* * CDirector::StartRematchVote(void) */ - "StartRematchVote" + "CDirector::StartRematchVote" { "library" "server" "linux" "@_ZN9CDirector16StartRematchVoteEv" @@ -3018,7 +3482,7 @@ /* * CDirector::FullRestart(void) */ - "FullRestart" + "CDirector::FullRestart" { "library" "server" "linux" "@_ZN9CDirector11FullRestartEv" @@ -3030,7 +3494,7 @@ /* * CDirectorVersusMode::HideScoreboardNonVirtual(void) */ - "HideVersusScoreboard" + "CDirectorVersusMode::HideScoreboardNonVirtual" { "library" "server" "linux" "@_ZN19CDirectorVersusMode24HideScoreboardNonVirtualEv" @@ -3042,7 +3506,7 @@ /* * CDirectorScavengeMode::HideScoreboardNonVirtual(void) */ - "HideScavengeScoreboard" + "CDirectorScavengeMode::HideScoreboardNonVirtual" { "library" "server" "linux" "@_ZN21CDirectorScavengeMode24HideScoreboardNonVirtualEv" @@ -3054,7 +3518,7 @@ /* * CDirector::HideScoreboard(void) */ - "HideScoreboard" + "CDirector::HideScoreboard" { "library" "server" "linux" "@_ZN9CDirector14HideScoreboardEv" @@ -3066,7 +3530,7 @@ /* * CDirector::RegisterForbiddenTarget(CBaseEntity *) - used to create Car Alarms */ - "RegisterForbiddenTarget" + "CDirector::RegisterForbiddenTarget" { "library" "server" "linux" "@_ZN9CDirector23RegisterForbiddenTargetEP11CBaseEntity" @@ -3079,7 +3543,7 @@ /* * CDirector::UnregisterForbiddenTarget(CBaseEntity *) - used to remove Car Alarms */ - "UnRegisterForbiddenTarget" + "CDirector::UnregisterForbiddenTarget" { "library" "server" "linux" "@_ZN9CDirector25UnregisterForbiddenTargetEP11CBaseEntity" @@ -3095,7 +3559,7 @@ /* * CTerrorPlayer::OnSlammedSurvivor(CTerrorPlayer*, bool, bool) - Charger hit Survivor function call */ - "OnSlammedSurvivor" + "CTerrorPlayer::OnSlammedSurvivor" { "library" "server" "linux" "@_ZN13CTerrorPlayer17OnSlammedSurvivorEPS_bb" @@ -3104,22 +3568,10 @@ /* Search "ChargerZombie.ImpactHard" */ } - /* - * CTerrorPlayer::OnLeptOnSurvivor(CTerrorPlayer*) - Jockey hit Survivor function call - */ - "OnLeptOnSurvivor" - { - "library" "server" - "linux" "@_ZN13CTerrorPlayer16OnLeptOnSurvivorEPS_" - "windows" "\x55\x8B\x2A\xA1\x2A\x2A\x2A\x2A\x83\x2A\x2A\x83\x2A\x2A\x2A\x57\x8B\x2A\x0F\x85\x2A\x2A\x2A\x2A\x56" - /* 55 8B ? A1 ? ? ? ? 83 ? ? 83 ? ? ? 57 8B ? 0F 85 ? ? ? ? 56 */ - /* Search: "JockeyZombie.Ride" */ // Found by "SilverShot". - } - /* * CTerrorGameRules::ClearScavengeScores(bool) */ - "GameRulesClearScavengeScores" + "CTerrorGameRules::ClearScavengeScores" { "library" "server" "linux" "@_ZN16CTerrorGameRules19ClearScavengeScoresEb" @@ -3131,7 +3583,7 @@ /* * CTerrorGameRules::ClearRoundDurations(void) */ - "GameRulesClearRoundDurations" + "CTerrorGameRules::ClearRoundDurations" { "library" "server" "linux" "@_ZN16CTerrorGameRules19ClearRoundDurationsEv" @@ -3142,7 +3594,7 @@ /* * CDirectorVersusMode::ClearTeamScoresNonVirtual(bool) */ - "DirectorClearTeamScores" + "CDirectorVersusMode::ClearTeamScoresNonVirtual" { "library" "server" "linux" "@_ZN19CDirectorVersusMode25ClearTeamScoresNonVirtualEb" @@ -3169,7 +3621,7 @@ * survivorCharacterType is likely int, 0-3 or 1-4 * function can be found via the CDirectorVersusMode::UpdateMarkersReached(void) function, unique string "versus_marker_reached" */ - "GetVersusCompletionPerCharacter" + "CTerrorGameRules::GetVersusCompletionPerCharacter" { "library" "server" "linux" "@_ZNK16CTerrorGameRules31GetVersusCompletionPerCharacterE21SurvivorCharacterTypei" @@ -3182,7 +3634,7 @@ * * Found using AreTeamsFlipped and NotifyNetWorkStateChanged - but im not sure its the right one */ - "RecordInfectedDamageForVersus" + "CTerrorGameRules::RecordInfectedDamageForVersus" { "library" "server" "linux" "@_ZN16CTerrorGameRules29RecordInfectedDamageForVersusEi" @@ -3197,7 +3649,7 @@ /* * SurvivorBot::IsReachable(CBaseEntity *)const */ - "IsReachable_Entity" + "SurvivorBot::IsReachable" { "library" "server" "linux" "@_ZNK11SurvivorBot11IsReachableEP11CBaseEntity" @@ -3208,7 +3660,7 @@ /* * CNavArea::IsBlocked(int, bool)const */ - "CNavArea_IsBlocked" + "CNavArea::IsBlocked" { "library" "server" "linux" "@_ZNK8CNavArea9IsBlockedEib" @@ -3233,7 +3685,7 @@ * CDirectorMusicBanks::OnRoundStart * Has unique string "Event.Reveal" */ - "DirectorMusicBanks_OnRoundStart" + "CDirectorMusicBanks::OnRoundStart" { "library" "server" "windows" "\x55\x8B\xEC\x83\xEC\x2A\x56\x57\x8B\xF9\x8B\x0D\x2A\x2A\x2A\x2A\xE8\x2A\x2A\x2A\x2A\x84\xC0\x0F" @@ -3260,7 +3712,10 @@ /* 55 8B EC A1 ? ? ? ? 83 78 30 00 56 8B F1 74 */ } - "CVEngineServer_CreateFakeClient" + /* + * CVEngineServer::CreateFakeClient(CVEngineServer *this, const char *) + */ + "CVEngineServer::CreateFakeClient" { "library" "engine" "linux" "@_ZN14CVEngineServer16CreateFakeClientEPKc" @@ -3297,7 +3752,10 @@ "linux" "@_ZL20m_WeaponInfoDatabase" } - /* We can find the WeaponInfoDatabase address in this sub on Windows + /* + * ReadWeaponDataFromFileForSlot(int, char *s, int, int) + * + * We can find the WeaponInfoDatabase address in this sub on Windows * * Look for "scripts/%s", should be the ref that's furthest into a func. * OR @@ -3356,7 +3814,7 @@ /* * CBaseServer::FillServerInfo(SVC_ServerInfo *) */ - "FillServerInfo" + "CBaseServer::FillServerInfo" { "library" "engine" "linux" "@_ZN11CBaseServer14FillServerInfoER14SVC_ServerInfo" @@ -3368,7 +3826,7 @@ /* * CBaseServer::GetClient(int) */ - "CBaseServer_GetClient" + "CBaseServer::GetClient" { "library" "engine" "linux" "@_ZN11CBaseServer9GetClientEi" @@ -3408,7 +3866,7 @@ * CBaseServer::SetReservationCookie(uint64_t, char*, va_list) * - clear the reservation by setting a cookie of 0 */ - "SetReservationCookie" + "CBaseServer::SetReservationCookie" { "library" "engine" "linux" "@_ZN11CBaseServer20SetReservationCookieEyPKcz" @@ -3594,7 +4052,7 @@ } /* CTerrorPlayer::RoundRespawn */ - "RoundRespawn" + "CTerrorPlayer::RoundRespawn" { "library" "server" "linux" "@_ZN13CTerrorPlayer12RoundRespawnEv" @@ -3634,7 +4092,7 @@ /* * CBasePlayer::WaterMove(void) */ - "WaterMove" + "CBasePlayer::WaterMove" { "library" "server" "linux" "@_ZN11CBasePlayer9WaterMoveEv" @@ -3646,7 +4104,7 @@ * InfectedShoved::OnShoved(InfectedShoved *this, Infected *, CBaseEntity *) * Have to hook each common infected to enable. Feature not planned. */ - "InfectedShoved" + "InfectedShoved::OnShoved" { "library" "server" "linux" "@_ZN14InfectedShoved8OnShovedEP8InfectedP11CBaseEntity" diff --git a/addons/sourcemod/plugins/anticheat/l4d2_user_commands.smx b/addons/sourcemod/plugins/anticheat/l4d2_user_commands.smx index 317cd40a16ba2eece1ccb26770a4a113db5f2ad4..a16052923431ebd9d8255a4dc5953888166ebf47 100644 GIT binary patch delta 6196 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 Kfru*Soc{yaU^JQl delta 6172 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 diff --git a/addons/sourcemod/plugins/left4dhooks.smx b/addons/sourcemod/plugins/left4dhooks.smx index b4d3ff86ca0c8bba19112f5a468a9d240a994ac9..54790468ccf9471a899319c87efd5efe91c4968c 100644 GIT binary patch literal 83678 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 G=>Gr!2-5`s literal 77865 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%0A>cfSl!g%QTBh5Rr27_0_p>BR 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 HF!}u-6aUug diff --git a/addons/sourcemod/plugins/optional/l4d2_playstats.smx b/addons/sourcemod/plugins/optional/l4d2_playstats.smx index 37f97c8105b7cafef72c8bed2a724d9debf63ebc..678216351455395884a9181087d1ebb01544f803 100644 GIT binary patch literal 75999 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

    ^M2fY%xgRg7Uagk32-OgfI-Q16iYNQD5b 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 literal 18816 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

    {R4t9D+d|W+4UwsvCA19Kz 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 D<*!%e diff --git a/addons/sourcemod/scripting/1v1.sp b/addons/sourcemod/scripting/1v1.sp index 5bc21f047..a360a2af8 100644 --- a/addons/sourcemod/scripting/1v1.sp +++ b/addons/sourcemod/scripting/1v1.sp @@ -54,18 +54,18 @@ public void Event_PlayerHurt(Event hEvent, const char[] sEventName, bool bDontBr } int iAttacker = GetClientOfUserId(hEvent.GetInt("attacker")); - if (!IsClientAndInGame(iAttacker) || GetClientTeam(iAttacker) != view_as(L4D2Team_Infected)) { + if (!IsClientAndInGame(iAttacker) || GetClientTeam(iAttacker) != L4D2Team_Infected) { return; } int iZclass = GetEntProp(iAttacker, Prop_Send, "m_zombieClass"); - if (iZclass < view_as(L4D2Infected_Smoker) || iZclass > view_as(L4D2Infected_Charger)) { + if (iZclass < L4D2Infected_Smoker || iZclass > L4D2Infected_Charger) { return; } int iVictim = GetClientOfUserId(hEvent.GetInt("userid")); - if (!IsClientAndInGame(iVictim) || GetClientTeam(iVictim) != view_as(L4D2Team_Survivor)) { + if (!IsClientAndInGame(iVictim) || GetClientTeam(iVictim) != L4D2Team_Survivor) { return; } diff --git a/addons/sourcemod/scripting/TickrateFixes.sp b/addons/sourcemod/scripting/TickrateFixes.sp index a49546cd0..d2c5b4e06 100644 --- a/addons/sourcemod/scripting/TickrateFixes.sp +++ b/addons/sourcemod/scripting/TickrateFixes.sp @@ -32,7 +32,7 @@ #define ENTITY_MAX_NAME 64 //Tracking -enum DoorsTypeTracked +enum /*DoorsTypeTracked*/ { DoorsTypeTracked_None = -1, DoorsTypeTracked_Prop_Door_Rotating = 0, @@ -48,7 +48,7 @@ static const char g_szDoors_Type_Tracked[][MAX_NAME_LENGTH] = #if SOURCEMOD_V_MINOR > 9 enum struct DoorsData { - DoorsTypeTracked DoorsData_Type; + int DoorsData_Type; float DoorsData_Speed; bool DoorsData_ForceClose; } @@ -59,7 +59,7 @@ DoorsData #else enum DoorsData { - DoorsTypeTracked:DoorsData_Type, + DoorsData_Type, Float:DoorsData_Speed, bool:DoorsData_ForceClose }; @@ -175,7 +175,7 @@ public void Hook_DoorSpawnPost(int iEntity) // Save Original Settings. for (int i = 0; i < sizeof(g_szDoors_Type_Tracked); i++) { if (strcmp(sClassName, g_szDoors_Type_Tracked[i], false) == 0) { - Door_GetSettings(iEntity, view_as(i)); + Door_GetSettings(iEntity, i); } } @@ -343,14 +343,14 @@ void Door_GetSettingsAll() for (int i = 0;i < sizeof(g_szDoors_Type_Tracked); i++) { while ((iEntity = FindEntityByClassname(iEntity, g_szDoors_Type_Tracked[i])) != INVALID_ENT_REFERENCE) { - Door_GetSettings(iEntity, view_as(i)); + Door_GetSettings(iEntity, i); } iEntity = -1; } } -void Door_GetSettings(int iEntity, DoorsTypeTracked iDoorType) +void Door_GetSettings(int iEntity, int iDoorType) { #if SOURCEMOD_V_MINOR > 9 g_ddDoors[iEntity].DoorsData_Type = iDoorType; diff --git a/addons/sourcemod/scripting/aitankgank.sp b/addons/sourcemod/scripting/aitankgank.sp index 91d510b71..c0be9c622 100644 --- a/addons/sourcemod/scripting/aitankgank.sp +++ b/addons/sourcemod/scripting/aitankgank.sp @@ -50,4 +50,6 @@ public Action Timed_CheckAndKill(Handle hTimer, any iNewTank) if (IsFakeClient(iNewTank) && IsPlayerAlive(iNewTank)) { ForcePlayerSuicide(iNewTank); } + + return Plugin_Stop; } diff --git a/addons/sourcemod/scripting/archive/include/l4d2util_stocks.inc b/addons/sourcemod/scripting/archive/include/l4d2util_stocks.inc index b112cb79b..79a884ae4 100644 --- a/addons/sourcemod/scripting/archive/include/l4d2util_stocks.inc +++ b/addons/sourcemod/scripting/archive/include/l4d2util_stocks.inc @@ -5,7 +5,7 @@ //Author - A1m` -stock bool L4D2Util_IsValidClient(int client) +stock bool IsValidClientIndex(int client) { return (client > 0 && client <= MaxClients); } diff --git a/addons/sourcemod/scripting/botpopstop.sp b/addons/sourcemod/scripting/botpopstop.sp index c641e8f09..e0e38f9d8 100644 --- a/addons/sourcemod/scripting/botpopstop.sp +++ b/addons/sourcemod/scripting/botpopstop.sp @@ -3,7 +3,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define USE_GIVEPLAYERITEM 0 // Works correctly only in the latest version of sourcemod 1.11 (GivePlayerItem sourcemod native) @@ -58,10 +58,10 @@ public void Event_WeaponFire(Event hEvent, const char[] sEventName, bool bDontBr int iWeaponArrayIndex = -1; switch (iWeaponId) { - case view_as(WEPID_PAIN_PILLS): { + case WEPID_PAIN_PILLS: { iWeaponArrayIndex = ePILL_INDEX; } - case view_as(WEPID_ADRENALINE): { + case WEPID_ADRENALINE: { iWeaponArrayIndex = eADREN_INDEX; } default: { @@ -71,7 +71,7 @@ public void Event_WeaponFire(Event hEvent, const char[] sEventName, bool bDontBr g_iBotUsedCount[iClient][iWeaponArrayIndex]++; - int iEntity = GetPlayerWeaponSlot(iClient, view_as(L4D2WeaponSlot_LightHealthItem)); + int iEntity = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_LightHealthItem); RemovePlayerItem(iClient, iEntity); #if SOURCEMOD_V_MINOR > 8 @@ -95,7 +95,7 @@ public void Event_PlayerJoined(Event hEvent, const char[] sEventName, bool bDont void RestoreItems(int iClient, int iLeavingBot) { - int iCurrentWeapon = GetPlayerWeaponSlot(iClient, view_as(L4D2WeaponSlot_LightHealthItem)); + int iCurrentWeapon = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_LightHealthItem); for (int j = 0; j < eITEM_SIZE; j++) { if (g_iBotUsedCount[iLeavingBot][j] < 1) { diff --git a/addons/sourcemod/scripting/caster_assister.sp b/addons/sourcemod/scripting/caster_assister.sp index 1a4d274c9..91637c03f 100644 --- a/addons/sourcemod/scripting/caster_assister.sp +++ b/addons/sourcemod/scripting/caster_assister.sp @@ -162,37 +162,35 @@ public Action:SetVerticalIncrement_Cmd(client, args) public Action:OnPlayerRunCmd(client, &buttons) { - if (IsValidClient(client) && GetClientTeam(client) == 1) - { - if (buttons & IN_USE) - { - MoveUp(client, verticalIncrement[client]); - } - else if (buttons & IN_RELOAD) - { - MoveUp(client, -verticalIncrement[client]); - } - } + if (IsValidClient(client) && GetClientTeam(client) == 1) + { + if (buttons & IN_USE) + { + MoveUp(client, verticalIncrement[client]); + } + else if (buttons & IN_RELOAD) + { + MoveUp(client, -verticalIncrement[client]); + } + } + + return Plugin_Continue; } -public bool IsSpeedValid(float speed) +bool IsSpeedValid(float speed) { - return speed >= 0 && speed <= MAX_SPEED; + return (speed >= 0 && speed <= MAX_SPEED); } -stock MoveUp(client, Float:distance) +void MoveUp(int client, float distance) { - decl Float:origin[3]; - GetClientAbsOrigin(client, origin); - origin[2] += distance; - TeleportEntity(client, origin, NULL_VECTOR, NULL_VECTOR); + float origin[3]; + GetClientAbsOrigin(client, origin); + origin[2] += distance; + TeleportEntity(client, origin, NULL_VECTOR, NULL_VECTOR); } -stock bool:IsValidClient(client) -{ - if (client <= 0 || client > MaxClients || !IsClientConnected(client)) - { - return false; - } - return IsClientInGame(client); -} \ No newline at end of file +bool IsValidClient(int client) +{ + return (client > 0 && client <= MaxClients && IsClientInGame(client)); +} diff --git a/addons/sourcemod/scripting/caster_system.sp b/addons/sourcemod/scripting/caster_system.sp index 002c8a329..fb10c9622 100644 --- a/addons/sourcemod/scripting/caster_system.sp +++ b/addons/sourcemod/scripting/caster_system.sp @@ -33,7 +33,9 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max { CreateNative("IsClientCaster", Native_IsClientCaster); CreateNative("IsIDCaster", Native_IsIDCaster); + RegPluginLibrary("caster_system"); + return APLRes_Success; } public void OnPluginStart() @@ -169,6 +171,8 @@ public Action Timer_ReconnectCasters(Handle timer, ArrayList aList) int client = GetClientOfUserId(aList.Get(i)); if (client > 0) ReconnectClient(client); } + + return Plugin_Stop; } public Action L4D2_OnClientDisableAddons(const char[] SteamID) @@ -194,6 +198,8 @@ public Action CasterCheck(Handle timer, int userid) CPrintToChat(client, "%t", "CasterCheck2"); ChangeClientTeam(client, L4D2Team_Spectator); } + + return Plugin_Stop; } // ======================== @@ -312,6 +318,8 @@ public Action NotCasting_Cmd(int client, int args) public Action Reconnect(Handle timer, int client) { if (IsClientConnected(client)) ReconnectClient(client); + + return Plugin_Stop; } public Action ResetCaster_Cmd(int client, int args) @@ -497,4 +505,6 @@ public Action Timer_KickSpecs(Handle timer) KickClient(i, "%t", "KickSpecsReason"); } + + return Plugin_Stop; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/code_patcher.sp b/addons/sourcemod/scripting/code_patcher.sp index b780f9d1e..5b1d08725 100644 --- a/addons/sourcemod/scripting/code_patcher.sp +++ b/addons/sourcemod/scripting/code_patcher.sp @@ -85,7 +85,7 @@ public Action CodePatchListCommand(int args) if (iSize == 0) { PrintToServer("No patches applied"); - return; + return Plugin_Handled; } for (int i = 0; i < iSize; ++i) { @@ -98,13 +98,15 @@ public Action CodePatchListCommand(int args) PrintToServer("%d. %s\t0x%x: %s", i+1, name, addr, formattedBytes); } + + return Plugin_Handled; } public Action CodePatchPatchCommand(int args) { if (GetCmdArgs() != 1) { PrintToServer("syntax: codepatch_patch "); - return; + return Plugin_Handled; } char name[MAX_PATCH_NAME_LENGTH + 1]; @@ -114,7 +116,7 @@ public Action CodePatchPatchCommand(int args) if (patchId != -1) { PrintToServer("Patch '%s' is already loaded", name); - return; + return Plugin_Handled; } char key[MAX_PATCH_NAME_LENGTH + 32]; @@ -123,52 +125,52 @@ public Action CodePatchPatchCommand(int args) Format(key, sizeof(key), "%s_signature", name); if (!GameConfGetKeyValue(hGameConfig, key, value, sizeof(value))) { PrintToServer("Could not find key '%s'", key); - return; + return Plugin_Handled; } Address addr = GameConfGetAddress(hGameConfig, value); if (!addr) { PrintToServer("Could not load signature '%s'", value); - return; + return Plugin_Handled; } Format(key, sizeof(key), "%s_offset", name); if (!GameConfGetKeyValue(hGameConfig, key, value, sizeof(value))) { PrintToServer("Could not find key '%s'", key); - return; + return Plugin_Handled; } int offset = GameConfGetOffset(hGameConfig, value); if (offset == -1) { PrintToServer("Could not load offset '%s'", value); - return; + return Plugin_Handled; } Format(key, sizeof(key), "%s_length_%s", name, (bIsWindows) ? "windows" : "linux"); if (!GameConfGetKeyValue(hGameConfig, key, value, sizeof(value))) { PrintToServer("Could not find key '%s'", key); - return; + return Plugin_Handled; } int length = StringToInt(value); if (length < 1 || length > MAX_PATCH_SIZE) { PrintToServer("Too %s patch bytes for '%s'", (length < 1) ? "few" : "many", name); - return; + return Plugin_Handled; } Format(key, sizeof(key), "%s_bytes_%s", name, (bIsWindows) ? "windows" : "linux"); if (!GameConfGetKeyValue(hGameConfig, key, value, sizeof(value))) { PrintToServer("Could not find key '%s'", key); - return; + return Plugin_Handled; } char[] bytes = new char[length]; if (!ParseBytes(value, bytes, length)) { PrintToServer("Failed to parse patch bytes for '%s'", name); - return; + return Plugin_Handled; } addr += view_as

    (offset); @@ -179,13 +181,14 @@ public Action CodePatchPatchCommand(int args) FormatBytes(bytes, length, formattedBytes); PrintToServer("Applied patch '%s' [ %s] at 0x%x", name, formattedBytes, addr); + return Plugin_Handled; } public Action CodePatchUnpatchCommand(int args) { if (GetCmdArgs() != 1) { PrintToServer("syntax: codepatch_unpatch "); - return; + return Plugin_Handled; } char name[MAX_PATCH_NAME_LENGTH + 1]; @@ -195,12 +198,13 @@ public Action CodePatchUnpatchCommand(int args) if (patchId == -1) { PrintToServer("Patch '%s' is not loaded", name); - return; + return Plugin_Handled; } RevertPatch(name); PrintToServer("Reverted patch '%s'", name); + return Plugin_Handled; } static int GetPackedByte(int cell, int i) diff --git a/addons/sourcemod/scripting/dhooks-test.sp b/addons/sourcemod/scripting/dhooks-test.sp index d5008ca6a..d617132f0 100644 --- a/addons/sourcemod/scripting/dhooks-test.sp +++ b/addons/sourcemod/scripting/dhooks-test.sp @@ -187,6 +187,8 @@ public MRESReturn OnTakeDamage(int pThis, DHookReturn hReturn, DHookParam hParam hParams.SetObjectVar(1, 48, ObjectValueType_Float, 0.0); PrintToChat(pThis, "Pimping your hp"); } + + return MRES_Ignored; } // int CBaseCombatCharacter::GiveAmmo(int, int, bool) diff --git a/addons/sourcemod/scripting/double_getup.sp b/addons/sourcemod/scripting/double_getup.sp index 98f246169..5a2308854 100644 --- a/addons/sourcemod/scripting/double_getup.sp +++ b/addons/sourcemod/scripting/double_getup.sp @@ -36,7 +36,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include // Needed for IdentifySurvivor calls. I use survivor indices rather than client indices in case someone leaves while incapped (with a pending getup). #include // Needed for forcing players to have a getup animation. @@ -77,16 +77,16 @@ bool lateLoad; int - pendingGetups[view_as(SurvivorCharacter_Size)] = {0, ...}, // This is used to track the number of pending getups. The collective opinion is that you should have at most 1. - interrupt[view_as(SurvivorCharacter_Size)] = {false, ...}, // If the player was getting up, and that getup is interrupted. This alows us to break out of the GetupTimer loop. - currentSequence[view_as(SurvivorCharacter_Size)] = {0, ...}; // Kept to track when a player changes sequences, i.e. changes animations. + pendingGetups[SurvivorCharacter_Size] = {0, ...}, // This is used to track the number of pending getups. The collective opinion is that you should have at most 1. + interrupt[SurvivorCharacter_Size] = {false, ...}, // If the player was getting up, and that getup is interrupted. This alows us to break out of the GetupTimer loop. + currentSequence[SurvivorCharacter_Size] = {0, ...}; // Kept to track when a player changes sequences, i.e. changes animations. static const int // Nick, Rochelle, Coach, Ellis, Bill, Zoey, Louis, Francis //correct order - tankFlyAnim[view_as(SurvivorCharacter_Size)] = {628, 636, 628, 633, 536, 545, 536, 539}; //correct order + tankFlyAnim[SurvivorCharacter_Size] = {628, 636, 628, 633, 536, 545, 536, 539}; //correct order ePlayerState - playerState[view_as(SurvivorCharacter_Size)] = {eUPRIGHT, ...}; // Since there are multiple sequences for each animation, this acts as a simpler way to track a player's state. + playerState[SurvivorCharacter_Size] = {eUPRIGHT, ...}; // Since there are multiple sequences for each animation, this acts as a simpler way to track a player's state. public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { @@ -132,7 +132,7 @@ public void OnClientPostAdminCheck(int client) public void round_start(Event hEvent, const char[] name, bool dontBroadcast) { - for (int survivor = 0; survivor < view_as(SurvivorCharacter_Size); survivor++) { + for (int survivor = 0; survivor < SurvivorCharacter_Size; survivor++) { playerState[survivor] = eUPRIGHT; } } @@ -141,7 +141,7 @@ public void round_start(Event hEvent, const char[] name, bool dontBroadcast) public void smoker_land(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -154,7 +154,7 @@ public void smoker_land(Event hEvent, const char[] name, bool dontBroadcast) public void jockey_land(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -165,7 +165,7 @@ public void jockey_land(Event hEvent, const char[] name, bool dontBroadcast) public void jockey_clear(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -179,7 +179,7 @@ public void jockey_clear(Event hEvent, const char[] name, bool dontBroadcast) public void smoker_clear(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -196,7 +196,7 @@ public void smoker_clear(Event hEvent, const char[] name, bool dontBroadcast) public void hunter_clear(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -218,7 +218,7 @@ public void hunter_clear(Event hEvent, const char[] name, bool dontBroadcast) // If a player is impacted during a charged, they should have 1 getup. public void multi_charge(Event hEvent, const char[] name, bool dontBroadcast) { - SurvivorCharacter survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("victim"))); + int survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("victim"))); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -233,7 +233,7 @@ public void multi_charge(Event hEvent, const char[] name, bool dontBroadcast) // If a player is cleared from a charger, they should have 1 getup. public void charger_land_instant(Event hEvent, const char[] name, bool dontBroadcast) { - SurvivorCharacter survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("victim"))); + int survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("victim"))); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -249,7 +249,7 @@ public void charger_land_instant(Event hEvent, const char[] name, bool dontBroad // This event defines when a player transitions from being insta-charged to being pummeled. public void charger_land(Event hEvent, const char[] name, bool dontBroadcast) { - SurvivorCharacter survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("victim"))); + int survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("victim"))); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -265,7 +265,7 @@ public void charger_land(Event hEvent, const char[] name, bool dontBroadcast) public void charger_clear(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -281,7 +281,7 @@ public void charger_clear(Event hEvent, const char[] name, bool dontBroadcast) // If a player is incapped, mark that down. This will interrupt their animations, if they have any. public void player_incap(Event hEvent, const char[] name, bool dontBroadcast) { - SurvivorCharacter survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("userid"))); + int survivor = IdentifySurvivor(GetClientOfUserId(hEvent.GetInt("userid"))); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -298,7 +298,7 @@ public void player_incap(Event hEvent, const char[] name, bool dontBroadcast) public void player_revive(Event hEvent, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("subject")); - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return; } @@ -310,7 +310,7 @@ public void player_revive(Event hEvent, const char[] name, bool dontBroadcast) // A catch-all to handle damage that is not associated with an event. I use this instead of player_hurt because it ignores godframes. public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype) { - SurvivorCharacter survivor = IdentifySurvivor(victim); + int survivor = IdentifySurvivor(victim); if (survivor == SurvivorCharacter_Invalid) { return Plugin_Continue; } @@ -357,7 +357,7 @@ void _TankLandTimer(int client) public Action TankLandTimer(Handle hTimer, any client) { - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return Plugin_Stop; } @@ -369,7 +369,7 @@ public Action TankLandTimer(Handle hTimer, any client) return Plugin_Continue; } - int iAnimation = (longerTankPunchGetup.BoolValue) ? view_as(ANIM_SHOVED_BY_TEAMMATE) : view_as(ANIM_TANK_PUNCH_GETUP); // 96 is the tank punch getup. + int iAnimation = (longerTankPunchGetup.BoolValue) ? ANIM_SHOVED_BY_TEAMMATE : ANIM_TANK_PUNCH_GETUP; // 96 is the tank punch getup. if (playerState[survivor] == eTANK_PUNCH_JOCKEY_FIX) { // When punched out of a jockey, the player goes into land (fly+1) for an arbitrary number of frames, then enters land (fly+2) for an arbitrary number of frames. Once they're done "landing" we give them the getup they deserve. @@ -402,7 +402,7 @@ void _GetupTimer(int client) public Action GetupTimer(Handle hTimer, any client) { - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return Plugin_Stop; } @@ -433,10 +433,10 @@ public Action GetupTimer(Handle hTimer, any client) #endif if (longerTankPunchGetup.BoolValue) { - L4D2Direct_DoAnimationEvent(client, view_as(ANIM_SHOVED_BY_TEAMMATE)); + L4D2Direct_DoAnimationEvent(client, ANIM_SHOVED_BY_TEAMMATE); playerState[survivor] = eCHARGER_GETUP; } else { - L4D2Direct_DoAnimationEvent(client, view_as(ANIM_TANK_PUNCH_GETUP)); // 96 is the tank punch getup. + L4D2Direct_DoAnimationEvent(client, ANIM_TANK_PUNCH_GETUP); // 96 is the tank punch getup. playerState[survivor] = eTANK_PUNCH_GETUP; } @@ -464,7 +464,7 @@ void _CancelGetup(int client) public Action CancelGetup(Handle hTimer, any client) { - SurvivorCharacter survivor = IdentifySurvivor(client); + int survivor = IdentifySurvivor(client); if (survivor == SurvivorCharacter_Invalid) { return Plugin_Stop; } @@ -485,7 +485,7 @@ public Action CancelGetup(Handle hTimer, any client) } // If the player is in any of the getup states. -bool isGettingUp(SurvivorCharacter survivor) +bool isGettingUp(int survivor) { switch (playerState[survivor]) { case (eHUNTER_GETUP): { diff --git a/addons/sourcemod/scripting/eq_finale_tanks.sp b/addons/sourcemod/scripting/eq_finale_tanks.sp index f2223c89c..67d60c62d 100644 --- a/addons/sourcemod/scripting/eq_finale_tanks.sp +++ b/addons/sourcemod/scripting/eq_finale_tanks.sp @@ -7,6 +7,7 @@ #define MAP_NAME_MAX_LENGTH 64 +#if !defined _l4dh_included // from https://developer.valvesoftware.com/wiki/L4D2_Director_Scripts enum { @@ -29,6 +30,7 @@ enum FINALE_GAUNTLET_BOSS = 16, FINALE_GAUNTLET_ESCAPE = 17 }; +#endif enum TankSpawningScheme { diff --git a/addons/sourcemod/scripting/ghost_hurt.sp b/addons/sourcemod/scripting/ghost_hurt.sp index b6f1660d1..5b7896cd7 100644 --- a/addons/sourcemod/scripting/ghost_hurt.sp +++ b/addons/sourcemod/scripting/ghost_hurt.sp @@ -59,6 +59,8 @@ public Action L4D_OnFirstSurvivorLeftSafeArea(int iClient) if (!g_bReadyUpAvailable) { EnableGhostHurt(); } + + return Plugin_Continue; } public void OnMapStart() @@ -75,6 +77,8 @@ public Action Cmd_ResetGhostHurt(int iArgs) { DisableGhostHurt(); PrintToServer("DisableGhostHurt()"); + + return Plugin_Handled; } void DisableGhostHurt() diff --git a/addons/sourcemod/scripting/holdout_bonus.sp b/addons/sourcemod/scripting/holdout_bonus.sp index 9fbe82fc0..46c10b7eb 100644 --- a/addons/sourcemod/scripting/holdout_bonus.sp +++ b/addons/sourcemod/scripting/holdout_bonus.sp @@ -237,10 +237,12 @@ public OnRoundIsLive() public Action: L4D_OnFirstSurvivorLeftSafeArea( client ) { - if ( !g_bReadyUpAvailable ) - { - RoundReallyStarting(); - } + if ( !g_bReadyUpAvailable ) + { + RoundReallyStarting(); + } + + return Plugin_Continue; } // penalty_bonus: requesting final update before setting score, pass it the holdout bonus @@ -259,25 +261,27 @@ public PBONUS_RequestFinalUpdate( &update ) // this is not called before penalty_bonus, so useless public Action:L4D2_OnEndVersusModeRound(bool:countSurvivors) { - if ( g_bHoldoutThisRound ) - { - if ( g_bHoldoutActive ) - { - // game ended while holdout was active! wipe before they made it - apply partial bonus - HoldOutEnds(); - } - - // display the puny bonus (if enabled) - new iReport = GetConVarInt(g_hCvarReportMode); - if (iReport && iReport != REPORT_ONLYEVENT && GetConVarBool(g_hCvarPointsMode) ) - { - DisplayBonusToAll(); - } - } - - g_bInRound = false; - g_bSecondHalf = true; - g_bPlayersLeftStart = false; + if ( g_bHoldoutThisRound ) + { + if ( g_bHoldoutActive ) + { + // game ended while holdout was active! wipe before they made it - apply partial bonus + HoldOutEnds(); + } + + // display the puny bonus (if enabled) + new iReport = GetConVarInt(g_hCvarReportMode); + if (iReport && iReport != REPORT_ONLYEVENT && GetConVarBool(g_hCvarPointsMode) ) + { + DisplayBonusToAll(); + } + } + + g_bInRound = false; + g_bSecondHalf = true; + g_bPlayersLeftStart = false; + + return Plugin_Continue; } stock RoundReallyStarting() diff --git a/addons/sourcemod/scripting/include/colors.inc b/addons/sourcemod/scripting/include/colors.inc index 97ef477a1..6cc27bdde 100644 --- a/addons/sourcemod/scripting/include/colors.inc +++ b/addons/sourcemod/scripting/include/colors.inc @@ -647,7 +647,7 @@ stock void CShowActivity(int client, const char[] format, any ...) if (!value) { - return 1; + return; } for (int i = 1; i <= MaxClients; i++) @@ -695,7 +695,7 @@ stock void CShowActivity(int client, const char[] format, any ...) } } - return 1; + return; } /** @@ -756,7 +756,7 @@ stock void CShowActivityEx(int client, const char[] tag, const char[] format, an if (!value) { - return 1; + return; } for (int i = 1; i <= MaxClients; i++) @@ -803,7 +803,7 @@ stock void CShowActivityEx(int client, const char[] tag, const char[] format, an } } - return 1; + return; } /** @@ -874,7 +874,7 @@ stock void CShowActivity2(int client, const char[] tag, const char[] format, any if (!value) { - return 1; + return; } for (int i = 1; i <= MaxClients; i++) @@ -921,5 +921,5 @@ stock void CShowActivity2(int client, const char[] tag, const char[] format, any } } - return 1; + return; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/include/l4d2util_constants.inc b/addons/sourcemod/scripting/include/l4d2util_constants.inc index ba8de39f4..deba83aef 100644 --- a/addons/sourcemod/scripting/include/l4d2util_constants.inc +++ b/addons/sourcemod/scripting/include/l4d2util_constants.inc @@ -3,7 +3,22 @@ #endif #define l4d2util_constants_inc_ -enum L4D2_Team +#define ENTITY_MAX_NAME_LENGTH 64 + +enum +{ + HITGROUP_GENERIC = 0, + HITGROUP_HEAD = 1, + HITGROUP_CHEST = 2, + HITGROUP_STOMACH = 3, + HITGROUP_LEFTARM = 4, + HITGROUP_RIGHTARM = 5, + HITGROUP_LEFTLEG = 6, + HITGROUP_RIGHTLEG = 7, + HITGROUP_GEAR = 10 +}; + +enum /*L4D2_Team*/ { L4D2Team_None = 0, L4D2Team_Spectator, @@ -14,7 +29,7 @@ enum L4D2_Team }; //The official order of characters in the game -enum L4D2_Infected +enum /*L4D2_Infected*/ { L4D2Infected_Common = 0, L4D2Infected_Smoker = 1, @@ -30,7 +45,7 @@ enum L4D2_Infected L4D2Infected_Size //10 size }; -stock const char L4D2_InfectedNames[view_as(L4D2Infected_Size)][] = +stock const char L4D2_InfectedNames[L4D2Infected_Size][] = { "Common", "Smoker", @@ -44,7 +59,7 @@ stock const char L4D2_InfectedNames[view_as(L4D2Infected_Size)][] = "Survivor" }; -stock const char L4D2_TeamName[view_as(L4D2Team_Size)][] = +stock const char L4D2_TeamName[L4D2Team_Size][] = { "None", "Spectator", @@ -52,7 +67,7 @@ stock const char L4D2_TeamName[view_as(L4D2Team_Size)][] = "Infected" }; -enum L4D2_Gender +enum /*L4D2_Gender*/ { L4D2Gender_Neutral = 0, L4D2Gender_Male = 1, @@ -67,7 +82,7 @@ enum L4D2_Gender L4D2Gender_Mechanic = 10, //Ellis L4D2Gender_Ceda = 11, L4D2Gender_Crawler = 12, //Mudman - L4D2Gender_Undistractable = 13, //Workman + L4D2Gender_Undistractable = 13, //Workman (class not reacting to the pipe bomb) L4D2Gender_Fallen = 14, L4D2Gender_Riot_Control = 15, //RiotCop L4D2Gender_Clown = 16, @@ -81,7 +96,7 @@ enum L4D2_Gender L4D2Gender_MaxSize //23 size }; -enum L4D2WeaponSlot +enum /*L4D2WeaponSlot*/ { L4D2WeaponSlot_Primary, L4D2WeaponSlot_Secondary, @@ -95,7 +110,7 @@ enum L4D2WeaponSlot // Weapon ID enumerations. // These values are *NOT* arbitrary! // They are used in game as the weaponid for weapon_spawn entities -enum WeaponId +enum /*WeaponId*/ { WEPID_NONE, // 0 WEPID_PISTOL, // 1 @@ -158,7 +173,7 @@ enum WeaponId }; // These values are arbitrary -enum MeleeWeaponId +enum /*MeleeWeaponId*/ { WEPID_MELEE_NONE, WEPID_KNIFE, @@ -182,7 +197,7 @@ enum MeleeWeaponId }; // Weapon names for each of the weapons, used in identification. -stock const char WeaponNames[view_as(WEPID_SIZE)][] = +stock const char WeaponNames[WEPID_SIZE][] = { "weapon_none", "weapon_pistol", "weapon_smg", // 0 "weapon_pumpshotgun", "weapon_autoshotgun", "weapon_rifle", // 3 @@ -206,7 +221,7 @@ stock const char WeaponNames[view_as(WEPID_SIZE)][] = }; // Long weapon names -stock const char LongWeaponNames[view_as(WEPID_SIZE)][] = +stock const char LongWeaponNames[WEPID_SIZE][] = { "None", "Pistol", "Uzi", // 0 "Pump", "Autoshotgun", "M-16", // 3 @@ -230,7 +245,7 @@ stock const char LongWeaponNames[view_as(WEPID_SIZE)][] = }; // Internal names for melee weapons -stock const char MeleeWeaponNames[view_as(WEPID_MELEES_SIZE)][] = +stock const char MeleeWeaponNames[WEPID_MELEES_SIZE][] = { "", "knife", @@ -251,7 +266,7 @@ stock const char MeleeWeaponNames[view_as(WEPID_MELEES_SIZE)][] = "pitchfork" }; -stock const char LongMeleeWeaponNames[view_as(WEPID_MELEES_SIZE)][] = +stock const char LongMeleeWeaponNames[WEPID_MELEES_SIZE][] = { "None", "Knife", @@ -274,7 +289,7 @@ stock const char LongMeleeWeaponNames[view_as(WEPID_MELEES_SIZE)][] = // World weapon models for each of the weapons. Useful for making new weapon spawns. // Some models are left blank because no single model can be given, the model is known or none exist. -stock const char WeaponModels[view_as(WEPID_SIZE)][] = +stock const char WeaponModels[WEPID_SIZE][] = { "", "/w_models/weapons/w_pistol_B.mdl", @@ -347,7 +362,7 @@ stock const char WeaponModels[view_as(WEPID_SIZE)][] = "" }; -stock const char MeleeWeaponModels[view_as(WEPID_MELEES_SIZE)][] = +stock const char MeleeWeaponModels[WEPID_MELEES_SIZE][] = { "", "/w_models/weapons/w_knife_t.mdl", @@ -368,7 +383,7 @@ stock const char MeleeWeaponModels[view_as(WEPID_MELEES_SIZE)][] = "/weapons/melee/w_pitchfork.mdl" }; -stock const int WeaponSlots[view_as(WEPID_SIZE)] = +stock const int WeaponSlots[WEPID_SIZE] = { -1, // WEPID_NONE 1, // WEPID_PISTOL @@ -433,7 +448,7 @@ stock const int WeaponSlots[view_as(WEPID_SIZE)] = * this may work correctly with a netprop 'm_survivorCharacter'. * We need to find out the type of map l4d1 or l4d2... */ -enum SurvivorCharacter +enum /*SurvivorCharacter*/ { SurvivorCharacter_Invalid = -1, @@ -449,7 +464,7 @@ enum SurvivorCharacter SurvivorCharacter_Size //8 size }; -stock const char SurvivorNames[view_as(SurvivorCharacter_Size)][] = +stock const char SurvivorNames[SurvivorCharacter_Size][] = { "Nick", "Rochelle", @@ -462,7 +477,7 @@ stock const char SurvivorNames[view_as(SurvivorCharacter_Size)][] = }; // Models for each of the characters -stock const char SurvivorModels[view_as(SurvivorCharacter_Size)][] = +stock const char SurvivorModels[SurvivorCharacter_Size][] = { "models/survivors/survivor_gambler.mdl", //MODEL_NICK "models/survivors/survivor_producer.mdl", //MODEL_ROCHELLE @@ -476,7 +491,7 @@ stock const char SurvivorModels[view_as(SurvivorCharacter_Size)][] = // Animation IDs used by CTerrorPlayer::DoAnimationEvent // Gaps do not mean the animation doesn't exist, just that I don't know what it maps to. -enum Animation +enum /*Animation*/ { ANIM_RELOAD_PISTOL_UZI_SNIPER = 4, ANIM_RELOAD_SHOTGUN = 5, @@ -526,5 +541,5 @@ enum Animation ANIM_TANK_PUNCH_GETUP = 96, ANIM_IDLE = 98, - //ANIMATION_SIZE //99 size + ANIMATION_SIZE //99 size }; diff --git a/addons/sourcemod/scripting/include/l4d2util_infected.inc b/addons/sourcemod/scripting/include/l4d2util_infected.inc index dfedb5bf7..fae03deb0 100644 --- a/addons/sourcemod/scripting/include/l4d2util_infected.inc +++ b/addons/sourcemod/scripting/include/l4d2util_infected.inc @@ -11,7 +11,7 @@ #define UTIL_ARRAY_INDEX_TIMESTAMP 1 // Internal array of strings for timer ability timer entity classnames -stock const char L4D2_InfectedTimerEntities[view_as(L4D2Infected_Size)][] = +stock const char L4D2_InfectedTimerEntities[L4D2Infected_Size][] = { "", "ability_tongue", //Smoker @@ -26,7 +26,7 @@ stock const char L4D2_InfectedTimerEntities[view_as(L4D2Infected_Size)][] = }; // Internal array of strings for Infected victim netprops -stock const char L4D2_InfectedVictimNetprops[view_as(L4D2Infected_Size)][] = +stock const char L4D2_InfectedVictimNetprops[L4D2Infected_Size][] = { "", "m_tongueVictim", //Smoker @@ -48,7 +48,7 @@ stock const char L4D2_InfectedVictimNetprops[view_as(L4D2Infected_Size)][] */ stock bool IsInfected(int client) { - return (IsClientInGame(client) && GetClientTeam(client) == view_as(L4D2Team_Infected)); + return (IsClientInGame(client) && GetClientTeam(client) == L4D2Team_Infected); } /** @@ -59,7 +59,7 @@ stock bool IsInfected(int client) */ stock bool IsValidInfected(int client) { - return (L4D2Util_IsValidClient(client) && IsClientInGame(client) && GetClientTeam(client) == view_as(L4D2Team_Infected)); + return (IsValidClientIndex(client) && IsClientInGame(client) && GetClientTeam(client) == L4D2Team_Infected); } /** @@ -69,9 +69,9 @@ stock bool IsValidInfected(int client) * @param client client ID * @return class ID */ -stock L4D2_Infected GetInfectedClass(int client) +stock int GetInfectedClass(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_zombieClass")); + return GetEntProp(client, Prop_Send, "m_zombieClass"); } /** @@ -82,7 +82,7 @@ stock L4D2_Infected GetInfectedClass(int client) */ stock bool IsInfectedGhost(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isGhost")); + return view_as(GetEntProp(client, Prop_Send, "m_isGhost", 1)); } /** @@ -93,9 +93,9 @@ stock bool IsInfectedGhost(int client) * @param iBufLen size of sBuffer * @noreturn */ -stock void GetInfectedClassName(L4D2_Infected iClass, char[] sBuffer, const int iBufLen) +stock void GetInfectedClassName(int iClass, char[] sBuffer, const int iBufLen) { - strcopy(sBuffer, iBufLen, L4D2_InfectedNames[view_as(iClass)]); + strcopy(sBuffer, iBufLen, L4D2_InfectedNames[iClass]); } /** @@ -120,8 +120,8 @@ stock int GetInfectedAbilityEntity(int owner) */ stock bool GetInfectedAbilityTimer(int client, float ×tamp, float &duration) { - L4D2_Infected zClass = GetInfectedClass(client); - if (strlen(L4D2_InfectedTimerEntities[view_as(zClass)]) == 0) { + int zClass = GetInfectedClass(client); + if (strlen(L4D2_InfectedTimerEntities[zClass]) == 0) { return false; } @@ -151,9 +151,9 @@ stock bool GetInfectedAbilityTimer(int client, float ×tamp, float &duration */ stock bool SetInfectedAbilityTimer(int client, float ×tamp, float &duration) { - L4D2_Infected zClass = GetInfectedClass(client); + int zClass = GetInfectedClass(client); - if (strlen(L4D2_InfectedTimerEntities[view_as(zClass)]) == 0) { + if (strlen(L4D2_InfectedTimerEntities[zClass]) == 0) { return false; } @@ -181,13 +181,13 @@ stock bool SetInfectedAbilityTimer(int client, float ×tamp, float &duration */ stock int GetInfectedVictim(int client) { - L4D2_Infected zClass = GetInfectedClass(client); + int zClass = GetInfectedClass(client); - if (strlen(L4D2_InfectedVictimNetprops[view_as(zClass)]) == 0) { + if (strlen(L4D2_InfectedVictimNetprops[zClass]) == 0) { return -1; } - return GetEntPropEnt(client, Prop_Send, L4D2_InfectedVictimNetprops[view_as(zClass)]); + return GetEntPropEnt(client, Prop_Send, L4D2_InfectedVictimNetprops[zClass]); } /** @@ -196,7 +196,7 @@ stock int GetInfectedVictim(int client) * @param entity * @return L4D_Gender */ -stock L4D2_Gender GetGender(int entity) +stock int GetGender(int entity) { - return view_as(GetEntProp(entity, Prop_Send, "m_Gender")); + return GetEntProp(entity, Prop_Send, "m_Gender"); } diff --git a/addons/sourcemod/scripting/include/l4d2util_stocks.inc b/addons/sourcemod/scripting/include/l4d2util_stocks.inc index b112cb79b..70df4a93d 100644 --- a/addons/sourcemod/scripting/include/l4d2util_stocks.inc +++ b/addons/sourcemod/scripting/include/l4d2util_stocks.inc @@ -3,9 +3,11 @@ #endif #define l4d2util_stocks_inc_ +#include + //Author - A1m` -stock bool L4D2Util_IsValidClient(int client) +stock bool IsValidClientIndex(int client) { return (client > 0 && client <= MaxClients); } @@ -40,18 +42,6 @@ stock int L4D2Util_Clamp(int inc, int low, int high) return (inc > high) ? high : ((inc < low) ? low : inc); } -/* Unsafe functions -stock any L4D2Utill_GetMin(any a, any b) -{ - return (a < b) ? a : b; -} - -stock any L4D2Utill_GetMax(any a, any b) -{ - return (a > b) ? a : b; -} -*/ - stock int L4D2Util_IntToPercentInt(int iVar, int iVarMax) { if (iVar > iVarMax) { @@ -108,3 +98,39 @@ stock void String_ToLower(char[] str, const int MaxSize) str[iSize] = '\0'; } + +stock void HitgroupToString(int iHitGroup, char[] sDestination, const int iMaxLength) +{ + char sBuffer[32] = "GENERIC"; + switch (iHitGroup) { + case HITGROUP_GENERIC: { //0 + sBuffer = "generic"; + } + case HITGROUP_HEAD: { //1 + sBuffer = "head"; + } + case HITGROUP_CHEST: { //2 + sBuffer = "chest"; + } + case HITGROUP_STOMACH: { //3 + sBuffer = "stomach"; + } + case HITGROUP_LEFTARM: { //4 + sBuffer = "left arm"; + } + case HITGROUP_RIGHTARM: { //5 + sBuffer = "right arm"; + } + case HITGROUP_LEFTLEG: { //6 + sBuffer = "left leg"; + } + case HITGROUP_RIGHTLEG: { //7 + sBuffer = "right leg"; + } + case HITGROUP_GEAR: { //10 + sBuffer = "gear"; + } + } + + strcopy(sDestination, iMaxLength, sBuffer); +} diff --git a/addons/sourcemod/scripting/include/l4d2util_survivors.inc b/addons/sourcemod/scripting/include/l4d2util_survivors.inc index 88f346e87..da6b3498d 100644 --- a/addons/sourcemod/scripting/include/l4d2util_survivors.inc +++ b/addons/sourcemod/scripting/include/l4d2util_survivors.inc @@ -43,7 +43,7 @@ stock bool IsSurvivorAttacked(int survivor) */ stock bool IsSurvivor(int client) { - return (IsClientInGame(client) && GetClientTeam(client) == view_as(L4D2Team_Survivor)); + return (IsClientInGame(client) && GetClientTeam(client) == L4D2Team_Survivor); } /** @@ -54,7 +54,7 @@ stock bool IsSurvivor(int client) */ stock bool IsValidSurvivor(int client) { - return (L4D2Util_IsValidClient(client) && IsSurvivor(client)); + return (IsValidClientIndex(client) && IsSurvivor(client)); } /** @@ -65,7 +65,7 @@ stock bool IsValidSurvivor(int client) */ stock bool IsIncapacitated(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isIncapacitated")); + return view_as(GetEntProp(client, Prop_Send, "m_isIncapacitated", 1)); } /** @@ -124,8 +124,8 @@ stock int GetSurvivorIncapCount(int client) */ stock bool IsHangingFromLedge(int client) { - return (view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge")) - || view_as(GetEntProp(client, Prop_Send, "m_isFallingFromLedge"))); + return (view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge", 1)) + || view_as(GetEntProp(client, Prop_Send, "m_isFallingFromLedge", 1))); } /** @@ -137,7 +137,7 @@ stock bool IsHangingFromLedge(int client) stock void InitSurvivorModelTrie() { hSurvivorModelsTrie = new StringMap(); - for (int i = 0; i < view_as(SurvivorCharacter_Size); i++) { + for (int i = 0; i < SurvivorCharacter_Size; i++) { hSurvivorModelsTrie.SetValue(SurvivorModels[i], i); } } @@ -147,9 +147,9 @@ stock void InitSurvivorModelTrie() * @remark SurvivorCharacter_Invalid on errors * * @param client Survivor client to identify - * @return SurvivorCharacter index identifying the survivor, or SurvivorCharacter_Invalid if not identified. + * @return int index identifying the survivor, or SurvivorCharacter_Invalid if not identified. */ -stock SurvivorCharacter IdentifySurvivor(int client) +stock int IdentifySurvivor(int client) { if (!client || !IsSurvivor(client)) { return SurvivorCharacter_Invalid; @@ -166,15 +166,15 @@ stock SurvivorCharacter IdentifySurvivor(int client) * @remark SurvivorCharacter_Invalid on errors, uses SurvivorModelTrie * * @param model Player model to identify - * @return SurvivorCharacter index identifying the model, or SurvivorCharacter_Invalid if not identified. + * @return int index identifying the model, or SurvivorCharacter_Invalid if not identified. */ -stock SurvivorCharacter ClientModelToSC(const char[] model) +stock int ClientModelToSC(const char[] model) { if (hSurvivorModelsTrie == null) { InitSurvivorModelTrie(); } - SurvivorCharacter sc; + int sc; if (hSurvivorModelsTrie.GetValue(model, sc)) { return sc; } @@ -186,19 +186,19 @@ stock SurvivorCharacter ClientModelToSC(const char[] model) * Get the name of a survivor character. * Will write to string 'None' in case of error. * - * @param character SurvivorCharacter to get the name of + * @param character int to get the name of * @param buffer buffer to store name * @param length length of buffer * @return bool false if SurvivorCharacter_Invalid, otherwise true */ -stock bool GetSurvivorName(SurvivorCharacter character, char[] buffer, const int length) +stock bool GetSurvivorName(int character, char[] buffer, const int length) { if (character == SurvivorCharacter_Invalid) { strcopy(buffer, length, "None"); return false; } - strcopy(buffer, length, SurvivorNames[view_as(character)]); + strcopy(buffer, length, SurvivorNames[character]); return true; } @@ -214,13 +214,13 @@ stock bool GetSurvivorName(SurvivorCharacter character, char[] buffer, const int */ stock bool GetClientSurvivorName(int client, char[] buffer, const int length) { - SurvivorCharacter character = IdentifySurvivor(client); + int character = IdentifySurvivor(client); if (character == SurvivorCharacter_Invalid) { strcopy(buffer, length, "None"); return false; } - strcopy(buffer, length, SurvivorNames[view_as(character)]); + strcopy(buffer, length, SurvivorNames[character]); return true; } diff --git a/addons/sourcemod/scripting/include/l4d2util_tanks.inc b/addons/sourcemod/scripting/include/l4d2util_tanks.inc index 79ff1669b..d8f4d3c16 100644 --- a/addons/sourcemod/scripting/include/l4d2util_tanks.inc +++ b/addons/sourcemod/scripting/include/l4d2util_tanks.inc @@ -14,8 +14,13 @@ stock bool IsTank(int client) { return (IsClientInGame(client) - && view_as(GetClientTeam(client)) == L4D2Team_Infected - && GetInfectedClass(client) == L4D2Infected_Tank); + && GetClientTeam(client) == L4D2Team_Infected + && GetEntProp(client, Prop_Send, "m_zombieClass") == L4D2Infected_Tank); +} + +stock bool IsValidTank(int client) +{ + return (IsValidClientIndex(client) && IsTank(client)); } /** @@ -83,7 +88,7 @@ stock void SetTankFrustration(int iTankClient, int iFrustration) */ stock bool IsEntityOnFire(int entity) { - return view_as(GetEntityFlags(entity) & FL_ONFIRE); + return ((GetEntityFlags(entity) & FL_ONFIRE) != 0); } /** diff --git a/addons/sourcemod/scripting/include/l4d2util_weapons.inc b/addons/sourcemod/scripting/include/l4d2util_weapons.inc index 46319bd14..61c3c7a56 100644 --- a/addons/sourcemod/scripting/include/l4d2util_weapons.inc +++ b/addons/sourcemod/scripting/include/l4d2util_weapons.inc @@ -6,12 +6,12 @@ #include #include -#define GETWEAPONNAME(%0) (IsValidWeaponId(view_as(%0)) ? (WeaponNames[view_as(%0)]) : "") -#define GETLONGWEAPONNAME(%0) (IsValidWeaponId(view_as(%0)) ? (LongWeaponNames[view_as(%0)]) : "") -#define GETMELEEWEAPONNAME(%0) (IsValidMeleeWeaponId(view_as(%0)) ? (MeleeWeaponNames[view_as(%0)]) : "") -#define GETLONGMELEEWEAPONNAME(%0) (IsValidMeleeWeaponId(view_as(%0)) ? (LongMeleeWeaponNames[view_as(%0)]) : "") -#define GETWEAPONMODEL(%0) (HasValidWeaponModel(view_as(%0)) ? (WeaponModels[view_as(%0)]) : "") -#define GETMELEEWEAPONMODEL(%0) (HasValidMeleeWeaponModel(view_as(%0)) ? (MeleeWeaponModels[view_as(%0)]) : "") +#define GETWEAPONNAME(%0) (IsValidWeaponId(%0) ? (WeaponNames[%0]) : "") +#define GETLONGWEAPONNAME(%0) (IsValidWeaponId(%0) ? (LongWeaponNames[%0]) : "") +#define GETMELEEWEAPONNAME(%0) (IsValidMeleeWeaponId(%0) ? (MeleeWeaponNames[%0]) : "") +#define GETLONGMELEEWEAPONNAME(%0) (IsValidMeleeWeaponId(%0) ? (LongMeleeWeaponNames[%0]) : "") +#define GETWEAPONMODEL(%0) (HasValidWeaponModel(%0) ? (WeaponModels[%0]) : "") +#define GETMELEEWEAPONMODEL(%0) (HasValidMeleeWeaponModel(%0) ? (MeleeWeaponModels[%0]) : "") stock static StringMap hWeaponNamesTrie = null; stock static StringMap hMeleeWeaponNamesTrie = null; @@ -21,14 +21,14 @@ stock void InitWeaponNamesTrie() { hWeaponNamesTrie = new StringMap(); - for (int i = 0; i < view_as(WEPID_SIZE); i++) { + for (int i = 0; i < WEPID_SIZE; i++) { hWeaponNamesTrie.SetValue(WeaponNames[i], i); } hMeleeWeaponNamesTrie = new StringMap(); hMeleeWeaponModelsTrie = new StringMap(); - for (int i = 0; i < view_as(WEPID_MELEES_SIZE); i++) { + for (int i = 0; i < WEPID_MELEES_SIZE; i++) { hMeleeWeaponNamesTrie.SetValue(MeleeWeaponNames[i], i); hMeleeWeaponModelsTrie.SetString(MeleeWeaponModels[i], MeleeWeaponNames[i]); } @@ -54,7 +54,7 @@ stock void L4D2Weapons_Init() * @param wepid WeaponId to check for validity * @return True if wepid is valid, false otherwise. */ -stock bool IsValidWeaponId(WeaponId wepid) +stock bool IsValidWeaponId(int wepid) { return (wepid >= WEPID_NONE && wepid < WEPID_SIZE); } @@ -66,7 +66,7 @@ stock bool IsValidWeaponId(WeaponId wepid) * @param wepid MeleeWeaponId to check for validity * @return True if wepid is valid, false otherwise. */ -stock bool IsValidMeleeWeaponId(MeleeWeaponId wepid) +stock bool IsValidMeleeWeaponId(int wepid) { return (wepid >= WEPID_MELEE_NONE && wepid < WEPID_MELEES_SIZE); } @@ -77,7 +77,7 @@ stock bool IsValidMeleeWeaponId(MeleeWeaponId wepid) * @param wepid MeleeWeaponId to check for a known weapon model for. * @return True if a valid weapon model exists for wepid, false otherwise. */ -stock bool HasValidMeleeWeaponModel(MeleeWeaponId wepid) +stock bool HasValidMeleeWeaponModel(int wepid) { return (IsValidMeleeWeaponId(wepid) && MeleeWeaponModels[wepid][0] != '\0'); } @@ -88,7 +88,7 @@ stock bool HasValidMeleeWeaponModel(MeleeWeaponId wepid) * @param wepid WeaponId to get the slot for. * @return Slot number (0-4) or -1 for invalid WeaponId or no slot */ -stock int GetSlotFromWeaponId(WeaponId wepid) +stock int GetSlotFromWeaponId(int wepid) { return (IsValidWeaponId(wepid)) ? WeaponSlots[wepid] : -1; } @@ -100,7 +100,7 @@ stock int GetSlotFromWeaponId(WeaponId wepid) * @param wepid WeaponId to check for a known weapon model for. * @return True if a valid weapon model exists for wepid, false otherwise. */ -stock bool HasValidWeaponModel(WeaponId wepid) +stock bool HasValidWeaponModel(int wepid) { return (IsValidWeaponId(wepid) && WeaponModels[wepid][0] != '\0'); } @@ -109,9 +109,9 @@ stock bool HasValidWeaponModel(WeaponId wepid) * Tries to look up a WeaponId for a given Weapon Name. * * @param weaponName Weapon name string to look up Id from - * @return The corresponding WeaponId if found, else WEPID_NONE + * @return int The corresponding WeaponId if found, else WEPID_NONE */ -stock WeaponId WeaponNameToId(const char[] weaponName) +stock int WeaponNameToId(const char[] weaponName) { if (hWeaponNamesTrie == null) { InitWeaponNamesTrie(); @@ -119,7 +119,7 @@ stock WeaponId WeaponNameToId(const char[] weaponName) int id; if (hWeaponNamesTrie.GetValue(weaponName, id)) { - return view_as(id); + return id; } return WEPID_NONE; @@ -133,7 +133,7 @@ stock WeaponId WeaponNameToId(const char[] weaponName) * @param length Max length which can be written to the buffer. * @return Number of bytes written to buffer, or 0 for invalid weaponId. */ -stock void GetWeaponName(WeaponId wepid, char[] nameBuffer, const int length) +stock void GetWeaponName(int wepid, char[] nameBuffer, const int length) { strcopy(nameBuffer, length, GETWEAPONNAME(wepid)); } @@ -146,7 +146,7 @@ stock void GetWeaponName(WeaponId wepid, char[] nameBuffer, const int length) * @param length Max length which can be written to the buffer. * @return Number of bytes written to buffer, or 0 for invalid weaponId. */ -stock void GetMeleeWeaponName(MeleeWeaponId wepid, char[] nameBuffer, const int length) +stock void GetMeleeWeaponName(int wepid, char[] nameBuffer, const int length) { strcopy(nameBuffer, length, GETMELEEWEAPONNAME(wepid)); } @@ -159,7 +159,7 @@ stock void GetMeleeWeaponName(MeleeWeaponId wepid, char[] nameBuffer, const int * @param length Max length which can be written to the buffer. * @return Number of bytes written to buffer, or 0 for invalid weaponId. */ -stock void GetLongWeaponName(WeaponId wepid, char[] nameBuffer, const int length) +stock void GetLongWeaponName(int wepid, char[] nameBuffer, const int length) { strcopy(nameBuffer, length, GETLONGWEAPONNAME(wepid)); } @@ -172,7 +172,7 @@ stock void GetLongWeaponName(WeaponId wepid, char[] nameBuffer, const int length * @param length Max length which can be written to the buffer. * @return Number of bytes written to buffer, or 0 for invalid weaponId. */ -stock void GetLongMeleeWeaponName(MeleeWeaponId wepid, char[] nameBuffer, const int length) +stock void GetLongMeleeWeaponName(int wepid, char[] nameBuffer, const int length) { strcopy(nameBuffer, length, GETLONGMELEEWEAPONNAME(wepid)); } @@ -186,7 +186,7 @@ stock void GetLongMeleeWeaponName(MeleeWeaponId wepid, char[] nameBuffer, const * @param length Max length which can be written to the buffer. * @return Number of bytes written to buffer, or 0 for invalid weaponid or no weapon model available. */ -stock void GetMeleeWeaponModel(MeleeWeaponId wepid, char[] modelBuffer, const int length) +stock void GetMeleeWeaponModel(int wepid, char[] modelBuffer, const int length) { strcopy(modelBuffer, length, GETMELEEWEAPONMODEL(wepid)); } @@ -234,7 +234,7 @@ stock bool GetMeleeWeaponNameFromEntity(int entity, char[] buffer, const int len * @param length Max length which can be written to the buffer. * @return Number of bytes written to buffer, or 0 for invalid weaponid or no weapon model available. */ -stock void GetWeaponModel(WeaponId wepid, char[] modelBuffer, const int length) +stock void GetWeaponModel(int wepid, char[] modelBuffer, const int length) { strcopy(modelBuffer, length, GETWEAPONMODEL(wepid)); } @@ -244,9 +244,9 @@ stock void GetWeaponModel(WeaponId wepid, char[] modelBuffer, const int length) * @remark Should work on most weapon ents--even spawns, singles, held, etc. * * @param entity Index of entity to identify - * @return WeaponID for the entity if it is a weapon, WEPID_NONE otherwise + * @return int for the entity if it is a weapon, WEPID_NONE otherwise */ -stock WeaponId IdentifyWeapon(int entity) +stock int IdentifyWeapon(int entity) { if (!entity || !IsValidEntity(entity) || !IsValidEdict(entity)) { return WEPID_NONE; @@ -258,7 +258,7 @@ stock WeaponId IdentifyWeapon(int entity) } if (strcmp(class, "weapon_spawn") == 0) { - return view_as(GetEntProp(entity, Prop_Send, "m_weaponID")); + return GetEntProp(entity, Prop_Send, "m_weaponID"); } int len = strlen(class); @@ -275,16 +275,16 @@ stock WeaponId IdentifyWeapon(int entity) * Identifies a melee weapon spawn or weapon entity as a MeleeWeaponId * @remark Should work on most weapon ents--even spawns, singles, held, etc. * - * @param entity Index of entity to identify - * @return MeleeWeaponId for the entity if it is a weapon, WEPID_MELEE_NONE otherwise + * @param entity Index of entity to identify + * @return int for the entity if it is a weapon, WEPID_MELEE_NONE otherwise */ -stock MeleeWeaponId IdentifyMeleeWeapon(int entity) +stock int IdentifyMeleeWeapon(int entity) { if (IdentifyWeapon(entity) != WEPID_MELEE) { return WEPID_MELEE_NONE; } - char sName[128]; + char sName[64]; if (!GetMeleeWeaponNameFromEntity(entity, sName, sizeof(sName))) { return WEPID_MELEE_NONE; } @@ -295,7 +295,7 @@ stock MeleeWeaponId IdentifyMeleeWeapon(int entity) int id; if (hMeleeWeaponNamesTrie.GetValue(sName, id)) { - return view_as(id); + return id; } return WEPID_MELEE_NONE; @@ -312,7 +312,7 @@ stock MeleeWeaponId IdentifyMeleeWeapon(int entity) * @param model World model to use for the weapon spawn * @return entity of the new weapon spawn, or -1 on errors. */ -stock int ConvertWeaponSpawn(int entity, WeaponId wepid, int count = 5, const char[] model = "") +stock int ConvertWeaponSpawn(int entity, int wepid, int count = 5, const char[] model = "") { if (!IsValidEntity(entity)) { return -1; @@ -339,7 +339,7 @@ stock int ConvertWeaponSpawn(int entity, WeaponId wepid, int count = 5, const ch SetEntProp(entity, Prop_Send, "m_weaponID", wepid); - static char buf[PLATFORM_MAX_PATH - 16], modelName[PLATFORM_MAX_PATH]; + char buf[PLATFORM_MAX_PATH - 16], modelName[PLATFORM_MAX_PATH]; if (model[0] != '\0') { SetEntityModel(entity, model); } else { diff --git a/addons/sourcemod/scripting/include/left4dhooks.inc b/addons/sourcemod/scripting/include/left4dhooks.inc index 43faac1b7..19445ee09 100644 --- a/addons/sourcemod/scripting/include/left4dhooks.inc +++ b/addons/sourcemod/scripting/include/left4dhooks.inc @@ -169,6 +169,7 @@ public void __pl_l4dh_SetNTVOptional() MarkNativeAsOptional("L4D2_SpawnWitchBride"); // l4d2weapons.inc + MarkNativeAsOptional("L4D_GetWeaponID"); MarkNativeAsOptional("L4D2_IsValidWeapon"); MarkNativeAsOptional("L4D2_GetIntWeaponAttribute"); MarkNativeAsOptional("L4D2_GetFloatWeaponAttribute"); @@ -347,6 +348,30 @@ enum STATE_INTRO_CAMERA } +// From: https://developer.valvesoftware.com/wiki/L4D2_Director_Scripts +// For the "L4D2_ChangeFinaleStage" and "L4D2_GetCurrentFinaleStage" natives and "L4D2_OnChangeFinaleStage" forward. +enum +{ + FINALE_GAUNTLET_1 = 0, + FINALE_HORDE_ATTACK_1 = 1, + FINALE_HALFTIME_BOSS = 2, + FINALE_GAUNTLET_2 = 3, + FINALE_HORDE_ATTACK_2 = 4, + FINALE_FINAL_BOSS = 5, + FINALE_HORDE_ESCAPE = 6, + FINALE_CUSTOM_PANIC = 7, + FINALE_CUSTOM_TANK = 8, + FINALE_CUSTOM_SCRIPTED = 9, + FINALE_CUSTOM_DELAY = 10, + FINALE_CUSTOM_CLEAROUT = 11, + FINALE_GAUNTLET_START = 12, + FINALE_GAUNTLET_HORDE = 13, + FINALE_GAUNTLET_HORDE_BONUSTIME = 14, + FINALE_GAUNTLET_BOSS_INCOMING = 15, + FINALE_GAUNTLET_BOSS = 16, + FINALE_GAUNTLET_ESCAPE = 17 +} + @@ -687,9 +712,108 @@ forward Action L4D_OnGetMissionVSBossSpawning(float &spawn_pos_min, float &spawn * * @param tank the player who was a tank * @param newtank a player who has become a new tank + * + * @noreturn */ forward void L4D_OnReplaceTank(int tank, int newtank); +/** + * @brief Called whenever CTankClaw::DoSwing(CTankClaw *this) is invoked + * @remarks When a tank is swinging to punch. + * + * @param tank tank client index + * @param rock the claw entity index + * + * @noreturn + */ +forward void L4D_TankClaw_DoSwing_Pre(int tank, int claw); + +/** + * @brief Called whenever CTankClaw::DoSwing(CTankClaw *this) is invoked + * @remarks When a tank is swinging to punch. + * + * @param tank tank client index + * @param rock the claw entity index + * + * @noreturn + */ +forward void L4D_TankClaw_DoSwing_Post(int tank, int claw); + +/** + * @brief Called whenever CTankClaw::GroundPound() is invoked + * @remarks When hitting the ground (maybe only when hitting an incapped player) + * @remarks The forwards "L4D_TankClaw_OnPlayerHit_Pre" and "L4D_TankClaw_OnPlayerHit_Post" trigger after this, allowing identification of victim + * @remarks The forwards "L4D_TankClaw_DoSwing_Pre" and "L4D_TankClaw_DoSwing_Post" can trigger after this + * + * @param tank tank client index + * @param rock the claw entity index + * + * @noreturn + */ +forward void L4D_TankClaw_GroundPound_Pre(int tank, int claw); + +/** + * @brief Called whenever CTankClaw::GroundPound() is invoked + * @remarks When hitting the ground (maybe only when hitting an incapped player) + * @remarks The forwards "L4D_TankClaw_OnPlayerHit_Pre" and "L4D_TankClaw_OnPlayerHit_Post" trigger before this + * @remarks The forwards "L4D_TankClaw_DoSwing_Pre" and "L4D_TankClaw_DoSwing_Post" can trigger after this + * + * @param tank tank client index + * @param rock the claw entity index + * + * @noreturn + */ +forward void L4D_TankClaw_GroundPound_Post(int tank, int claw); + +/** + * @brief Called whenever CTankClaw::OnPlayerHit(CTerrorPlayer*, bool) is invoked + * @remarks When a tank swings and punches a player. + * + * @param tank tank client index + * @param rock the claw entity index + * + * @return Plugin_Handled to block the target player from being stumbled, Plugin_Continue otherwise. + */ +forward Action L4D_TankClaw_OnPlayerHit_Pre(int tank, int claw, int player); + +/** + * @brief Called whenever CTankClaw::OnPlayerHit(CTerrorPlayer*, bool) is invoked + * @remarks When a tank swings and punches a player. + * + * @param tank tank client index + * @param rock the claw entity index + * @param player the player being hit + * + * @noreturn + */ +forward void L4D_TankClaw_OnPlayerHit_Post(int tank, int claw, int player); + +/** + * @brief Called whenever CTankRock::Detonate() is invoked + * @remarks When a tank rock hits something and explodes. + * + * @param tank tank client index + * @param rock the rock entity index + * + * @noreturn + */ +forward void L4D_TankRock_OnDetonate(int tank, int rock); + +/** + * @brief Called whenever CTankRock::OnRelease(Vector const&, QAngle const&, Vector const&, Vector const&) is invoked + * @remarks When a tank rock is thrown. + * + * @param tank tank client index + * @param rock the rock entity index + * @param vecPos the position vector of the rock + * @param vecAng the angle vector of the rock + * @param vecVel the velocity vector of the rock + * @param vecRot the rotation vector of the rock + * + * @return Plugin_Changed to modify the vector values, Plugin_Continue otherwise. + */ +forward Action L4D_TankRock_OnRelease(int tank, int rock, float vecPos[3], float vecAng[3], float vecVel[3], float vecRot[3]); + /** * @brief Called whenever CDirector::TryOfferingTankBot is invoked * @remarks Is used for displaying the "X gets Tank" window and transferring Tank control @@ -767,6 +891,22 @@ forward Action L4D2_OnSelectTankAttack(int client, int &sequence); // L4D2 only. forward Action L4D_OnStartMeleeSwing(int client, bool boolean); +/** + * @brief Called whenever CTerrorMeleeWeapon::GetDamageForVictim() is invoked + * @remarks Called to calculate the damage when a melee weapon hits something + * @remarks A headshot on Common Infected will still kill them. + * @remarks Could maybe set the weapon attribute "L4D2BoolMeleeWeapon_Decapitates" to avoid killing on headshot. Please report success if you try + * + * @param client the client swinging the melee weapon + * @param weapon the weapon entity index + * @param victim the victim being hit by the melee weapon + * @param damage the amount of damage to inflict on the victim + * + * @return Plugin_Handled to block, Plugin_Changed to change damage, Plugin_Continue otherwise + */ +// L4D2 only. +forward Action L4D2_MeleeGetDamageForVictim(int client, int weapon, int victim, float &damage); + /** * @brief Called whenever CDirectorScriptedEventManager::SendInRescueVehicle(void) is invoked * @remarks Called when the last Finale stage is reached and the Rescue means becomes 'available'. @@ -779,11 +919,12 @@ forward Action L4D2_OnSendInRescueVehicle(); /** * @brief Called whenever CDirectorScriptedEventManager::ChangeFinaleStage is invoked - * - * @param FinaleStageType integer value * @remarks Called when the director stage changes * @remarks some values for FinaleStageType: 1 - Finale Started; 6 - Rescue Vehicle Ready; 7 - Zombie Hordes; 8 - Tank; 10 - Combat Respite (nothing spawns) * @remarks SendInRescueVehicle does not depend on Finale Stage being 6, that only signals endless Hordes/Tanks + * @remarks Can use the "FINALE_*" enums (search for them above) for the finaleType value. + * + * @param FinaleStageType integer value * * @return Plugin_Handled to block, Plugin_Changed to change finaleType, Plugin_Continue otherwise */ @@ -958,6 +1099,140 @@ forward Action L4D_OnMaterializeFromGhostPre(int client); */ forward Action L4D_OnMaterializeFromGhost(int client); +/** + * @brief Called whenever CPipeBombProjectile::Create is invoked + * @remarks Called when a PipeBomb projectile is being created + * + * @param client the client who is throwing the grenade (can be 0) + * @param vecPos the position vector of the projectile + * @param vecAng the angle vector of the projectile + * @param vecVel the velocity vector of the projectile + * @param vecRot the rotation vector of the projectile + * + * @return Plugin_Handled to block the grenade creation, Plugin_Changed to modify the vector values, Plugin_Continue otherwise. + */ +forward Action L4D_PipeBombProjectile_Pre(int client, float vecPos[3], float vecAng[3], float vecVel[3], float vecRot[3]); + +/** + * @brief Called whenever CPipeBombProjectile::Create is invoked + * @remarks Called when a PipeBomb projectile has been created + * + * @param client the client who is throwing the grenade (can be 0) + * @param projectile the projectile entity index (can be 0 if blocked in the pre hook) + * @param vecPos the position vector of the projectile + * @param vecAng the angle vector of the projectile + * @param vecVel the velocity vector of the projectile + * @param vecRot the rotation vector of the projectile + * + * @noreturn + */ +forward void L4D_PipeBombProjectile_Post(int client, int projectile, float vecPos[3], float vecAng[3], float vecVel[3], float vecRot[3]); + +/** + * @brief Called whenever CTerrorPlayer::Extinguish() is invoked + * @remarks Called when a player (Survivor or Special Infected) is about to be extinguished + * + * @param client the client who is about to be extinguished + * + * @return Plugin_Handled to block extinguishing, Plugin_Continue otherwise + */ +forward Action L4D_PlayerExtinguish(int client); + +/** + * @brief Called whenever CBreakableProp::Break() is invoked + * @remarks Called when a physics prop is broken + * @note When a propanetank explodes, it will create and explode another prop_physics and the attacker entity will be 0. Maybe only L4D2 has this issue. + * + * @param prop the physics entity index which broke + * @param entity the client or entity who caused the prop to break (could be 0) + * + * @noreturn + */ +forward void L4D_CBreakableProp_Break(int prop, int entity); + +/** + * @brief Called whenever CGasCan::Event_Killed() is invoked + * @remarks Called when a gascan is broken + * + * @param gascan the gascan entity index + * + * @noreturn + */ + // L4D2 only. +forward void L4D2_CGasCan_EventKilled(int gascan, int inflictor, int attacker); + +/** + * @brief Called whenever CGasCan::OnActionComplete() is invoked + * @remarks Called when someone completes pouring a gascan into a nozzle + * + * @param client the client pouring + * @param gascan the gascan entity index that is being consumed + * @param nozzle the nozzle being poured into + * + * @return Plugin_Handled to block adding to Scavenge score (see "Scavenge Score Fix" plugin for more details), Plugin_Continue otherwise + */ + // L4D2 only. +forward Action L4D2_CGasCan_ActionComplete(int client, int gascan, int nozzle); + +/** + * @brief Called whenever CInsectSwarm::CanHarm() is invoked + * @remarks Called when Spitter Acid is determining if a client or entity can be damaged + * + * @param acid the acid entity index causing the damage + * @param spitter the Spitter or client who created the acid (can be 0) + * @param entity the client or entity index being checked if it can be damaged + * + * @return Plugin_Handled to block allowing damage to an entity, Plugin_Continue otherwise + */ + // L4D2 only. +forward Action L4D2_CInsectSwarm_CanHarm(int acid, int spitter, int entity); + +/** + * @brief Called whenever CTerrorPlayer::OnPouncedOnSurvivor() is invoked + * @remarks Called when a Survivor player is about to be pounced on by a Hunter + * + * @param victim the client who's being pounced + * @param attacker the Hunter pouncing on someone + * + * @return Plugin_Handled to block, Plugin_Continue otherwise + */ +forward Action L4D_OnPouncedOnSurvivor(int victim, int attacker); + +/** + * @brief Called whenever CTerrorPlayer::GrabVictimWithTongue() is invoked + * @remarks Called when a Survivor player is about to be grabbed by a Smoker + * + * @param victim the client who's being grabbed + * @param attacker the Smoker grabbing someone + * + * @return Plugin_Handled to block, Plugin_Continue otherwise + */ +forward Action L4D_OnGrabWithTongue(int victim, int attacker); + +/** + * @brief Called whenever CTerrorPlayer::OnLeptOnSurvivor() is invoked + * @remarks Called when a Survivor player is about to be ridden by a Jockey + * + * @param victim the client who's being grabbed + * @param attacker the Jockey grabbing someone + * + * @return Plugin_Handled to block, Plugin_Continue otherwise + */ + // L4D2 only. +forward Action L4D2_OnJockeyRide(int victim, int attacker); + +/** + * @brief Called whenever CTerrorPlayer::OnStartCarryingVictim() is invoked + * @remarks Called when a Survivor player is about to be carried by a Charger + * + * @param victim the client who's being grabbed + * @param attacker the Charger picking up someone + * + * @return Plugin_Handled to block, Plugin_Continue otherwise + */ + // L4D2 only. +forward Action L4D2_OnStartCarryingVictim(int victim, int attacker); + /** * @brief Called whenever CTerrorPlayer::OnVomitedUpon is invoked * @remarks Called when a Survivor player is covered in Boomer bile, or when using "Bile the World" plugin by "AtomicStryker" @@ -971,7 +1246,7 @@ forward Action L4D_OnVomitedUpon(int victim, int &attacker, bool &boomerExplosio /** * @brief Called whenever CTerrorPlayer::OnHitByVomitJar is invoked - * @remarks Called a Special Infected is hit from a Bilejar explosion + * @remarks Called when a Special Infected is hit from a Bilejar explosion * * @param victim the client who's now it * @param attacker the attacker who caused the vomit @@ -1026,7 +1301,7 @@ forward void L4D2_OnWaterMove(int client); * * @return Current game mode. */ -forward Action L4D_OnGameModeChange(int gamemode); +forward void L4D_OnGameModeChange(int gamemode); /** * @brief Called when CTerrorPlayer::Fling(Vector const&, PlayerAnimEvent_t, CBaseCombatCharacter*, float) is invoked. @@ -1344,7 +1619,7 @@ native bool L4D_HasPlayerControlledZombies(); * @remarks Does not attach the "Fuse" or "Light" particles, see the "left4dhooks_test" plugin for example on attaching these * @remarks Also used in the "PipeBomb Shove" plugin by Silvers * - * @param client Client id to attribute the projectile to for damage credit + * @param client Client id to attribute the projectile to for damage credit. Passing 0 (world) is allowed * @param vecPos Vector coordinate of the projectile on creation * @param vecAng Vector velocity and direction of the projectile * @@ -1355,7 +1630,7 @@ native int L4D_PipeBombPrj(int client, const float vecPos[3], const float vecAng /** * @brief Creates an activated Molotov projectile. * - * @param client Client id to attribute the projectile to for damage credit + * @param client Client id to attribute the projectile to for damage credit Passing 0 (world) is allowed * @param vecPos Vector coordinate of the projectile on creation * @param vecAng Vector velocity and direction of the projectile * @@ -1366,7 +1641,7 @@ native int L4D_MolotovPrj(int client, const float vecPos[3], const float vecAng[ /** * @brief Creates an activated VomitJar projectile. * - * @param client Client id to attribute the projectile to for damage credit + * @param client Client id to attribute the projectile to for damage credit Passing 0 (world) is allowed * @param vecPos Vector coordinate of the projectile on creation * @param vecAng Vector velocity and direction of the projectile * @@ -1378,7 +1653,7 @@ native int L4D2_VomitJarPrj(int client, const float vecPos[3], const float vecAn /** * @brief Creates an activated Grenade Launcher projectile. * - * @param client Client id to attribute the projectile to for damage credit + * @param client Client id to attribute the projectile to for damage credit Passing 0 (world) is allowed * @param vecPos Vector coordinate of the projectile on creation * @param vecAng Vector velocity and direction of the projectile * @@ -1390,7 +1665,7 @@ native int L4D2_GrenadeLauncherPrj(int client, const float vecPos[3], const floa /** * @brief Creates a Spitter goo projectile. * - * @param client Client id to attribute the projectile to for damage credit + * @param client Client id to attribute the projectile to for damage credit Passing 0 (world) is allowed * @param vecPos Vector coordinate of the projectile on creation * @param vecAng Vector velocity and direction of the projectile * @@ -1462,6 +1737,7 @@ native bool L4D_IsFinaleEscapeInProgress(); * @brief Returns the current Finale stage type. * @remarks some values for FinaleStageType: 1 - Finale Started; 6 - Rescue Vehicle Ready; 7 - Zombie Hordes; 8 - Tank; 10 - Combat Respite (nothing spawns) * @remarks Seems to return 18 for non-finale maps + * @remarks Can use the "FINALE_*" enums (search for them above) for the finaleType value. * * @return finaleType stage value */ @@ -1807,6 +2083,7 @@ native void L4D2_SendInRescueVehicle(); * @remarks Changes the Finale stage * @remarks some values for FinaleStageType: 1 - Finale Started; 6 - Rescue Vehicle Ready; 7 - Zombie Hordes; 8 - Tank; 10 - Combat Respite (nothing spawns) * @remarks will fire the forward of the same function + * @remarks Can use the "FINALE_*" enums (search for them above) for the finaleType value. * * @param FinaleStageType integer value * @@ -2206,7 +2483,7 @@ native float L4D2_ITimerGetElapsedTime(L4D2IntervalTimer timer); * 2020 Update2: Now works in Left4DHooks. Glitchy animation bug when reloading an already full weapon. * 2021 Update3: Fix plugin for modified ammo clips found here: https://forums.alliedmods.net/showthread.php?t=327105 -A note regarding Clipsize: Any nonstandard value will NOT be in effect at weapon pickup, which means the client +A note regarding Clipsize: Any non-standard value will NOT be in effect at weapon pickup, which means the client has to reload once to achieve the modified value. To fix this, add a weapon pickup hook in your plugin (eg "player_use") and use something like this with a small timer delay of 0.1 seconds or more (dont you love this engine). @@ -2269,6 +2546,16 @@ enum L4D2FloatMeleeWeaponAttributes +/** + * @brief Returns the weapon ID for a specific classname + * @remarks Can specify either "rifle" or "weapon_rifle" for example + * + * @param weaponName Weapon classname to check up on + * + * @return -1 if not found, otherwise returns weaponID + */ +native int L4D_GetWeaponID(const char[] weaponName); + /** * @brief Checks for a given weapon string to exist in the WeaponInformationDatabase * @remarks Throws an error if Database is unavailable @@ -2277,7 +2564,6 @@ enum L4D2FloatMeleeWeaponAttributes * * @return True if weapon is found, false if not */ -// L4D2 only. native bool L4D2_IsValidWeapon(const char[] weaponName); /** @@ -2289,7 +2575,6 @@ native bool L4D2_IsValidWeapon(const char[] weaponName); * * @return The value read. */ -// L4D2 only. native int L4D2_GetIntWeaponAttribute(const char[] weaponName, L4D2IntWeaponAttributes attr); /** @@ -2301,7 +2586,6 @@ native int L4D2_GetIntWeaponAttribute(const char[] weaponName, L4D2IntWeaponAttr * * @return The value read. */ -// L4D2 only. native float L4D2_GetFloatWeaponAttribute(const char[] weaponName, L4D2FloatWeaponAttributes attr); /** @@ -2314,7 +2598,6 @@ native float L4D2_GetFloatWeaponAttribute(const char[] weaponName, L4D2FloatWeap * * @noreturn */ -// L4D2 only. native void L4D2_SetIntWeaponAttribute(const char[] weaponName, L4D2IntWeaponAttributes attr, int value); /** @@ -2327,7 +2610,6 @@ native void L4D2_SetIntWeaponAttribute(const char[] weaponName, L4D2IntWeaponAtt * * @noreturn */ -// L4D2 only. native void L4D2_SetFloatWeaponAttribute(const char[] weaponName, L4D2FloatWeaponAttributes attr, float value); @@ -3319,6 +3601,7 @@ native bool L4D_BecomeGhost(int client); /** * @brief Enter ghost/dead mode. Some state values may have different results. Unknown. * @remarks 6 and 8 are commonly used by the game. + * @remarks Can use the "STATE_*" enums (search for them above). * * @param client Client ID of the player to affect * diff --git a/addons/sourcemod/scripting/include/smac.inc b/addons/sourcemod/scripting/include/smac.inc new file mode 100644 index 000000000..8c2243227 --- /dev/null +++ b/addons/sourcemod/scripting/include/smac.inc @@ -0,0 +1,129 @@ +/* + SourceMod Anti-Cheat + Copyright (C) 2011-2016 SMAC Development Team + Copyright (C) 2007-2011 CodingDirect LLC + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if defined _smac_included + #endinput +#endif +#define _smac_included + +#include + +/* Globals */ +#define SMAC_VERSION "0.8.7.3" +#define SMAC_URL "https://github.com/Silenci0/SMAC" +#define SMAC_AUTHOR "SMAC Development Team" +#define SMAC_MOD_ERROR "This module will not work for this mod and should be removed." + +enum GameType +{ + Game_Unknown = 0, + Game_CSS, + Game_TF2, + Game_DODS, + Game_INS, + Game_L4D, + Game_L4D2, + Game_HL2DM, + Game_FOF, + Game_HL2CTF, + Game_HIDDEN, + Game_ND, + Game_CSGO, + Game_ZPS, + Game_ZMR, + Game_BM +}; + +enum DetectionType +{ + Detection_Unknown = 0, + + // smac_aimbot + Detection_Aimbot = 100, + + // smac_autotrigger + Detection_AutoTrigger = 200, + + // smac_client + Detection_NameChangeSpam = 300, + + // smac_commands + Detection_CommandSpamming = 400, + Detection_BannedCommand, + + // smac_cvars + Detection_CvarViolation = 500, + + // smac_eyetest + Detection_UserCmdReuse = 600, + Detection_UserCmdTamperingTickcount, + Detection_UserCmdTamperingButtons, + Detection_Eyeangles, + + // smac_speedhack + Detection_Speedhack = 700, + + // smac_spinhack + Detection_Spinhack = 800, + + // smac_eac_banlist + Detection_GlobalBanned_EAC = 900, + + // smac_esea_banlist + Detection_GlobalBanned_ESEA = 1000, + + // smac_hl2dm_fixes + Detection_GravityGunExploit = 1100, +}; + +/* Natives */ +native GameType SMAC_GetGameType(); +native void SMAC_Log(const char[] format, any ...); +native void SMAC_LogAction(int client, const char[] format, any ...); +native void SMAC_Ban(int client, const char[] reason, any ...); +native void SMAC_PrintAdminNotice(const char[] format, any ...); +native ConVar SMAC_CreateConVar(const char[] name, const char[] defaultValue, const char[] description="",int flags = 0, bool hasMin = false, float min = 0.0, bool hasMax = false, float max = 0.0); +native Action SMAC_CheatDetected(int client, DetectionType type = Detection_Unknown, Handle info = INVALID_HANDLE); + +/* Forwards */ +forward Action SMAC_OnCheatDetected(int client, const char[] module, DetectionType type, Handle info); + +public SharedPlugin __pl_smac = +{ + name = "smac", + file = "smac.smx", +#if defined REQUIRE_PLUGIN + required = 1, +#else + required = 0, +#endif +}; + +#if !defined REQUIRE_PLUGIN +public void __pl_smac_SetNTVOptional() +{ + MarkNativeAsOptional("SMAC_GetGameType"); + MarkNativeAsOptional("SMAC_Log"); + MarkNativeAsOptional("SMAC_LogAction"); + MarkNativeAsOptional("SMAC_Ban"); + MarkNativeAsOptional("SMAC_PrintAdminNotice"); + MarkNativeAsOptional("SMAC_CreateConVar"); + MarkNativeAsOptional("SMAC_CheatDetected"); +} +#endif diff --git a/addons/sourcemod/scripting/include/smac_stocks.inc b/addons/sourcemod/scripting/include/smac_stocks.inc new file mode 100644 index 000000000..9ead95e26 --- /dev/null +++ b/addons/sourcemod/scripting/include/smac_stocks.inc @@ -0,0 +1,334 @@ +/* + SourceMod Anti-Cheat + Copyright (C) 2011-2016 SMAC Development Team + Copyright (C) 2007-2011 CodingDirect LLC + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#if defined _smac_stocks_included + #endinput +#endif +#define _smac_stocks_included + +/** + * Preprocessor directives + */ +#define MAX_EDICTS 2048 +#define MAX_ENTITIES 4096 + +#define MAX_MAPNAME_LENGTH 32 +#define MAX_AUTHID_LENGTH 64 + +// Hud Element hiding flags +#define HIDEHUD_WEAPONSELECTION (1 << 0) // Hide ammo count & weapon selection +#define HIDEHUD_FLASHLIGHT (1 << 1) +#define HIDEHUD_ALL (1 << 2) +#define HIDEHUD_HEALTH (1 << 3) // Hide health & armor / suit battery +#define HIDEHUD_PLAYERDEAD (1 << 4) // Hide when local player's dead +#define HIDEHUD_NEEDSUIT (1 << 5) // Hide when the local player doesn't have the HEV suit +#define HIDEHUD_MISCSTATUS (1 << 6) // Hide miscellaneous status elements (trains, pickup history, death notices, etc) +#define HIDEHUD_CHAT (1 << 7) // Hide all communication elements (saytext, voice icon, etc) +#define HIDEHUD_CROSSHAIR (1 << 8) // Hide crosshairs +#define HIDEHUD_VEHICLE_CROSSHAIR (1 << 9) // Hide vehicle crosshair +#define HIDEHUD_INVEHICLE (1 << 10) +#define HIDEHUD_BONUS_PROGRESS (1 << 11) // Hide bonus progress display (for bonus map challenges) +#define HIDEHUD_BITCOUNT 12 + +// Fade UserMessage bits +#define FFADE_IN 0x0001 // Just here so we don't pass 0 into the function +#define FFADE_OUT 0x0002 // Fade out (not in) +#define FFADE_MODULATE 0x0004 // Modulate (don't blend) +#define FFADE_STAYOUT 0x0008 // ignores the duration, stays faded out until new ScreenFade message received +#define FFADE_PURGE 0x0010 // Purges all other fades, replacing them with this one + +// Macros +#define IS_CLIENT(%1) (1 <= %1 <= MaxClients) +#define TIME_TO_TICK(%1) (RoundToNearest((%1) / GetTickInterval())) +#define TICK_TO_TIME(%1) ((%1) * GetTickInterval()) + +// Spectator movement modes +enum { + OBS_MODE_NONE = 0, // not in spectator mode + OBS_MODE_DEATHCAM, // special mode for death cam animation + OBS_MODE_FREEZECAM, // zooms to a target, and freeze-frames on them + OBS_MODE_FIXED, // view from a fixed camera position + OBS_MODE_IN_EYE, // follow a player in first person view + OBS_MODE_CHASE, // follow a player in third person view + OBS_MODE_ROAMING, // free roaming +}; + +/** + * General + */ +stock void GetPluginBasename(Handle plugin, char[] buffer,int maxlength) +{ + GetPluginFilename(plugin, buffer, maxlength); + + int check = -1; + if ((check = FindCharInString(buffer, '/', true)) != -1 || + (check = FindCharInString(buffer, '\\', true)) != -1) + { + Format(buffer, maxlength, "%s", buffer[check+1]); + } +} + +stock bool IsConVarDefault(ConVar convar) +{ + char sDefaultVal[16], sCurrentVal[16]; + GetConVarDefault(convar, sDefaultVal, sizeof(sDefaultVal)); + GetConVarString(convar, sCurrentVal, sizeof(sCurrentVal)); + + return StrEqual(sDefaultVal, sCurrentVal); +} + +stock void StringToLower(char[] input) +{ + int length = strlen(input); + + for (int i = 0; i < length; i++) + { + input[i] = CharToLower(input[i]); + } +} + +/** + * Clients + */ +stock bool IsClientNew(int client) +{ + // Client must be ingame. + return IsFakeClient(client) || GetGameTime() > GetClientTime(client); +} + +stock bool GetClientAbsVelocity(int client, float velocity[3]) +{ + static int offset = -1; + + if (offset == -1 && (offset = FindDataMapInfo(client, "m_vecAbsVelocity")) == -1) // FindDataMapOffs(client, "m_vecAbsVelocity")) == -1) + { + ZeroVector(velocity); + return false; + } + + GetEntDataVector(client, offset, velocity); + return true; +} + +stock int GetClientHudFlags(int client) +{ + return GetEntProp(client, Prop_Send, "m_iHideHUD"); +} + +stock int GetClientObserverMode(int client) +{ + static int offset = -1; + + if (offset == -1 && (offset = FindSendPropInfo("CBasePlayer", "m_iObserverMode")) == -1) //FindSendPropOffs("CBasePlayer", "m_iObserverMode")) == -1) + { + return OBS_MODE_NONE; + } + + return GetEntData(client, offset); +} + +stock int GetClientObserverTarget(int client) +{ + static int offset = -1; + + if (offset == -1 && (offset = FindSendPropInfo("CBasePlayer", "m_hObserverTarget")) == -1) + { + return -1; + } + + return GetEntDataEnt2(client, offset); +} + +/** + * Game Specific + */ +stock bool DODS_IsPlayerProne(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_bProne") || + GetEntPropFloat(client, Prop_Send, "m_flGoProneTime") > 0.0 || + GetEntPropFloat(client, Prop_Send, "m_flUnProneTime") > 0.0); +} + +stock bool L4D_IsPlayerGhost(int client) +{ + return view_as(GetEntProp(client, Prop_Send, "m_isGhost", 1)); +} + +// "Busy" implies that the client is not in their typical first-person state. +stock bool L4D_IsSurvivorBusy(int client) +{ + return GetEntityFlags(client) & FL_FROZEN || + GetClientHudFlags(client) & ~HIDEHUD_BONUS_PROGRESS || + GetEntProp(client, Prop_Send, "m_isIncapacitated") > 0 || + GetEntProp(client, Prop_Send, "m_knockdownReason") > 0 || + GetEntPropFloat(client, Prop_Send, "m_staggerDist") > 0.0 || + GetEntPropEnt(client, Prop_Send, "m_pounceAttacker") > 0 || + GetEntPropEnt(client, Prop_Send, "m_tongueOwner") > 0; +} + +stock bool L4D_IsInfectedBusy(int client) +{ + return GetEntPropFloat(client, Prop_Send, "m_vomitFadeStart") > GetGameTime() || + GetEntPropEnt(client, Prop_Send, "m_pounceVictim") > 0 || + GetEntPropEnt(client, Prop_Send, "m_tongueVictim") > 0; +} + +stock bool L4D2_IsSurvivorBusy(int client) +{ + return GetEntityFlags(client) & FL_FROZEN || + GetClientHudFlags(client) & ~HIDEHUD_BONUS_PROGRESS || + GetEntProp(client, Prop_Send, "m_isIncapacitated") > 0 || + GetEntProp(client, Prop_Send, "m_knockdownReason") > 0 || + GetEntPropFloat(client, Prop_Send, "m_staggerDist") > 0.0 || + GetEntPropEnt(client, Prop_Send, "m_pummelAttacker") > 0 || + GetEntPropEnt(client, Prop_Send, "m_carryAttacker") > 0 || + GetEntPropEnt(client, Prop_Send, "m_pounceAttacker") > 0 || + GetEntPropEnt(client, Prop_Send, "m_jockeyAttacker") > 0 || + GetEntPropEnt(client, Prop_Send, "m_tongueOwner") > 0; +} + +stock bool L4D2_IsInfectedBusy(int client) +{ + return GetEntProp(client, Prop_Send, "m_iGlowType") == 3 || + GetEntPropFloat(client, Prop_Send, "m_vomitFadeStart") > GetGameTime() || + GetEntPropEnt(client, Prop_Send, "m_pummelVictim") > 0 || + GetEntPropEnt(client, Prop_Send, "m_carryVictim") > 0 || + GetEntPropEnt(client, Prop_Send, "m_pounceVictim") > 0 || + GetEntPropEnt(client, Prop_Send, "m_jockeyVictim") > 0 || + GetEntPropEnt(client, Prop_Send, "m_tongueVictim") > 0; +} + +stock bool ND_IsPlayerCommander(int client) +{ + return GameRules_GetPropEnt("m_hCommanders", 0) == client || GameRules_GetPropEnt("m_hCommanders", 1) == client; +} + +/** + * Math + */ +stock void ZeroVector(float vec[3]) +{ + vec[0] = vec[1] = vec[2] = 0.0; +} + +stock bool IsVectorZero(const float vec[3]) +{ + return vec[0] == 0.0 && vec[1] == 0.0 && vec[2] == 0.0; +} + +stock bool IsVectorAlmostZero(const float vec[3], const float tolerance=0.1) +{ + return view_as(FloatAbs(vec[0]) <= tolerance && + FloatAbs(vec[1]) <= tolerance && + FloatAbs(vec[2]) <= tolerance); +} + +stock bool AreVectorsEqual(const float vec1[3], const float vec2[3]) +{ + return vec1[0] == vec2[0] && vec1[1] == vec2[1] && vec1[2] == vec2[2]; +} + +stock bool AreVectorsAlmostEqual(const float vec1[3], const float vec2[3], const float tolerance=0.1) +{ + return view_as(FloatAbs(vec1[0] - vec2[0]) <= tolerance && + FloatAbs(vec1[1] - vec2[1]) <= tolerance && + FloatAbs(vec1[2] - vec2[2]) <= tolerance); +} + +stock int AbsValue(int value) +{ + return (value >= 0) ? value : -value; +} + +stock any MinValue(any value, any min) +{ + return (value < min) ? min : value; +} + +stock any MaxValue(any value, any max) +{ + return (value > max) ? max : value; +} + +stock any ClampValue(any value, any min, any max) +{ + value = MinValue(value, min); + value = MaxValue(value, max); + + return value; +} + +stock int IPToLong(const char[] ip) +{ + char pieces[4][4]; + + if (ExplodeString(ip, ".", pieces, sizeof(pieces), sizeof(pieces[])) != 4) + { + return 0; + } + + return StringToInt(pieces[0]) << 24 | + StringToInt(pieces[1]) << 16 | + StringToInt(pieces[2]) << 8 | + StringToInt(pieces[3]); +} + +stock void LongToIP(int ip, char[] buffer,int size) +{ + FormatEx(buffer, size, "%d.%d.%d.%d", (ip >> 24) & 0xFF, (ip >> 16) & 0xFF, (ip >> 8) & 0xFF, ip & 0xFF); +} + +stock int MT_GetRandomInt(int min,int max) +{ + return RoundToNearest(GetURandomFloat() * float(max - min) + float(min)); +} + +stock float MT_GetRandomFloat(float min, float max) +{ + return GetURandomFloat() * (max - min) + min; +} + +stock void BfWriteSBitLong(Handle bf,int data,int numBits) +{ + for (int i = 0; i < numBits; i++) + { + BfWriteBool(bf, !!(data & (1 << i))); + } +} + +stock int BfReadSBitLong(Handle bf,int numBits) +{ + int[] bits = new int[numBits]; + int ret, i; + + for (i = 0; i < numBits; i++) + { + bits[i] = BfReadBool(bf); + } + + ret = bits[numBits-1] ? -1 : 0; + + for (i = numBits-1; i >= 0; i--) + { + ret <<= 1; + ret |= bits[i]; + } + + return ret; +} diff --git a/addons/sourcemod/scripting/infected_flow_warp.sp b/addons/sourcemod/scripting/infected_flow_warp.sp index a72ba2c0d..46d3d828c 100644 --- a/addons/sourcemod/scripting/infected_flow_warp.sp +++ b/addons/sourcemod/scripting/infected_flow_warp.sp @@ -1,16 +1,14 @@ #pragma semicolon 1 -#pragma newdecls required; +#pragma newdecls required #include #include #include -#include //String_ToLower & L4D2Util_IsValidClient +#define L4D2UTIL_STOCKS_ONLY 1 +#include //String_ToLower & IsValidSurvivor -#define TEAM_SURVIVOR 2 -#define TEAM_INFECTED 3 - -StringMap - hNameToCharIDTrie; +StringMap + hNameToCharIDTrie = null; public Plugin myinfo = { @@ -50,7 +48,7 @@ public Action WarpTo_Cmd(int client, int args) if (args == 0) { int fMaxFlowSurvivor = L4D_GetHighestFlowSurvivor(); //left4dhooks functional or left4downtown2 by A1m` - if (!L4D2Util_IsValidClient(fMaxFlowSurvivor) || !IsSurvivor(fMaxFlowSurvivor)) { + if (!IsValidSurvivor(fMaxFlowSurvivor)) { PrintToChat(client, "No survivor player could be found!"); return Plugin_Handled; } @@ -95,16 +93,9 @@ int GetClientOfCharID(int characterID) return 0; } -bool IsSurvivor(int client) -{ - return (IsClientInGame(client) - && GetClientTeam(client) == TEAM_SURVIVOR - && IsPlayerAlive(client)); -} - bool IsGhostInfected(int client) { - return (GetClientTeam(client) == TEAM_INFECTED + return (GetClientTeam(client) == L4D2Team_Infected && IsPlayerAlive(client) - && GetEntProp(client, Prop_Send, "m_isGhost")); + && GetEntProp(client, Prop_Send, "m_isGhost", 1)); } diff --git a/addons/sourcemod/scripting/l4d2_antibaiter.sp b/addons/sourcemod/scripting/l4d2_antibaiter.sp index 55dac6abe..0c7b5da30 100644 --- a/addons/sourcemod/scripting/l4d2_antibaiter.sp +++ b/addons/sourcemod/scripting/l4d2_antibaiter.sp @@ -24,7 +24,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #undef REQUIRE_PLUGIN #include @@ -62,9 +62,7 @@ float int m_PostMobDelayTimerOffset, z_max_player_zombies, - hordeDelayChecks; - -L4D2_Infected + hordeDelayChecks, zombieclass[MAXPLAYERS + 1]; public Plugin myinfo = @@ -181,14 +179,14 @@ public void OnAllPluginsLoaded() public void OnLibraryRemoved(const char[] szName) { - if (StrEqual(szName, "pause", true)) { + if (strcmp(szName, "pause", true) == 0) { IsPauseAvailable = false; } } public void OnLibraryAdded(const char[] szName) { - if (StrEqual(szName, "pause", true)) { + if (strcmp(szName, "pause", true) == 0) { IsPauseAvailable = true; } } @@ -229,7 +227,7 @@ public Action AntibaiterThink(Handle hTimer) && aliveSince[i] != -1.0 && GetGameTime() - aliveSince[i] >= timerStartDelay ) { #if DEBUG - PrintToChatAll("\x03[Antibaiter DEBUG] Eligible player \x04%N\x01 is a zombieclass \x05%d\x01 alive for \x05%fs\x01", i, view_as(zombieclass[i]), GetGameTime() - aliveSince[i]); + PrintToChatAll("\x03[Antibaiter DEBUG] Eligible player \x04%N\x01 is a zombieclass \x05%d\x01 alive for \x05%fs\x01", i, zombieclass[i], GetGameTime() - aliveSince[i]); #endif eligibleZombies++; diff --git a/addons/sourcemod/scripting/l4d2_blind_infected.sp b/addons/sourcemod/scripting/l4d2_blind_infected.sp index adcc46fa6..87c279499 100644 --- a/addons/sourcemod/scripting/l4d2_blind_infected.sp +++ b/addons/sourcemod/scripting/l4d2_blind_infected.sp @@ -4,7 +4,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define ENT_CHECK_INTERVAL 1.0 @@ -19,7 +19,7 @@ enum eArray_Size }; -static const WeaponId g_iIdsToBlock[] = +static const int g_iIdsToBlock[] = { WEPID_PISTOL, WEPID_SMG, @@ -91,7 +91,7 @@ public Action Timer_EntCheck(Handle hTimer) g_hBlockedEntities.SetArray(i, iCurrentEnt[0], sizeof(iCurrentEnt)); } } - + return Plugin_Continue; } @@ -104,7 +104,7 @@ public void RoundStart_Event(Event hEvent, const char[] sEventName, bool bDontBr public Action RoundStartDelay_Timer(Handle hTimer) { - WeaponId iWeapon; + int iWeapon; int iBhTemp[eArray_Size], iEntityCount = GetEntityCount(); for (int i = (MaxClients + 1); i < iEntityCount; i++) { @@ -124,11 +124,13 @@ public Action RoundStartDelay_Timer(Handle hTimer) } } } + + return Plugin_Stop; } public Action OnTransmit(int iEntity, int iClient) { - if (GetClientTeam(iClient) != view_as(L4D2Team_Infected)) { + if (GetClientTeam(iClient) != L4D2Team_Infected) { return Plugin_Continue; } @@ -150,7 +152,7 @@ bool IsVisibleToSurvivors(int iEntity) int iSurvCount = 0; for (int i = 1; i <= MaxClients && iSurvCount < 4; i++) { - if (IsClientInGame(i) && GetClientTeam(i) == view_as(L4D2Team_Survivor)) { + if (IsClientInGame(i) && GetClientTeam(i) == L4D2Team_Survivor) { iSurvCount++; if (IsPlayerAlive(i) && IsVisibleTo(i, iEntity)) { diff --git a/addons/sourcemod/scripting/l4d2_car_alarm_hittable_fix.sp b/addons/sourcemod/scripting/l4d2_car_alarm_hittable_fix.sp index 7914ad765..1a6f798cf 100644 --- a/addons/sourcemod/scripting/l4d2_car_alarm_hittable_fix.sp +++ b/addons/sourcemod/scripting/l4d2_car_alarm_hittable_fix.sp @@ -17,7 +17,7 @@ public Plugin myinfo = public void OnEntityCreated(int entity, const char[] classname) { // Hook Alarmed Cars. - if(!StrEqual(classname, "prop_car_alarm")) return; + if (!StrEqual(classname, "prop_car_alarm")) return; SDKHook(entity, SDKHook_Touch, OnAlarmCarTouch); } @@ -39,6 +39,8 @@ public Action OnAlarmCarTouch(int car, int entity) SDKUnhook(car, SDKHook_Touch, OnAlarmCarTouch); } } + + return Plugin_Continue; } public Action DisableAlarm(Handle timer, any car) @@ -55,6 +57,8 @@ public Action DisableAlarm(Handle timer, any car) } if (Tank != -1) SDKHooks_TakeDamage(car, Tank, Tank, 0.0); + + return Plugin_Stop; } stock bool IsValidTank(int client) diff --git a/addons/sourcemod/scripting/l4d2_charger_getup_fix.sp b/addons/sourcemod/scripting/l4d2_charger_getup_fix.sp index 284dc1115..0fe748b0c 100644 --- a/addons/sourcemod/scripting/l4d2_charger_getup_fix.sp +++ b/addons/sourcemod/scripting/l4d2_charger_getup_fix.sp @@ -57,10 +57,10 @@ ConVar g_hChargeDuration; int ChargerTarget[MAXPLAYERS+1]; bool bLateLoad, bWallSlamed[MAXPLAYERS+1], bInForcedGetUp[MAXPLAYERS+1], bIgnoreJockeyed[MAXPLAYERS+1]; - public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { bLateLoad = late; + return APLRes_Success; } public void OnPluginStart() @@ -183,16 +183,25 @@ void CancelGetUpAnimation(int client) public Action Timer_Uncheck(Handle timer, int client) { bWallSlamed[client] = false; + + return Plugin_Stop; } public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype, int &weapon, float damageForce[3], float damagePosition[3]) { - if (!inflictor || !IsValidEdict(victim) || !IsValidEdict(inflictor)) return; - if (!IsCharger(attacker) || !IsSurvivor(victim)) return; + if (!inflictor || !IsValidEdict(victim) || !IsValidEdict(inflictor)) { + return Plugin_Continue; + } + + if (!IsCharger(attacker) || !IsSurvivor(victim)) { + return Plugin_Continue; + } - static char classname[64]; + char classname[64]; GetClientWeapon(attacker, classname, sizeof(classname)); - if (strcmp(classname, "weapon_charger_claw") != 0) return; + if (strcmp(classname, "weapon_charger_claw") != 0) { + return Plugin_Continue; + } if (damage == 10.0 && GetVectorLength(damageForce) == 0.0) { @@ -203,6 +212,8 @@ public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &dam // (barely happen since charger cannot impact one in godframe) CreateTimer(0.1, Timer_Uncheck, victim); } + + return Plugin_Continue; } public void OnTakeDamagePost(int victim, int attacker, int inflictor, float damage, int damagetype) @@ -379,6 +390,8 @@ public Action BlueMoonCaseCheck(Handle timer, int chargerClient) ResetChargerTarget(chargerClient); ResetIgnoreJockeyed(survivorClient); + + return Plugin_Stop; } public void Event_ChargeCarryStart(Event event, const char[] name, bool dontBroadcast) diff --git a/addons/sourcemod/scripting/l4d2_collision_adjustments.sp b/addons/sourcemod/scripting/l4d2_collision_adjustments.sp index e583597fd..7917b8f9b 100644 --- a/addons/sourcemod/scripting/l4d2_collision_adjustments.sp +++ b/addons/sourcemod/scripting/l4d2_collision_adjustments.sp @@ -7,7 +7,7 @@ #define TEAM_SURVIVOR 2 bool - isPulled[MAXPLAYERS + 1] = false, + isPulled[MAXPLAYERS + 1] = {false, ...}, bRockFix, bPullThrough, bRockThroughIncap; diff --git a/addons/sourcemod/scripting/l4d2_drop_secondary.sp b/addons/sourcemod/scripting/l4d2_drop_secondary.sp index 580fde77d..b1444a85d 100644 --- a/addons/sourcemod/scripting/l4d2_drop_secondary.sp +++ b/addons/sourcemod/scripting/l4d2_drop_secondary.sp @@ -36,7 +36,7 @@ public Plugin myinfo = public void OnPluginStart() { - HookEvent("round_start", Event_RoundStart); + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); HookEvent("player_use", Event_OnPlayerUse, EventHookMode_Post); HookEvent("player_death", Event_OnPlayerDeath, EventHookMode_Pre); @@ -59,7 +59,7 @@ public void OnClientDisconnect(int client) sMeleeScript[client] = MELEE_NONE; } -public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcast) +public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) { for (int i = 1; i <= MaxClients; i++) { @@ -74,7 +74,7 @@ public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcas * THEIR SECONDARY AND MELEE SCRIPT * *****************************************************************************************/ -public Action Event_OnPlayerReplacedByBot(Event event, const char[] name, bool dontBroadcast) +public void Event_OnPlayerReplacedByBot(Event event, const char[] name, bool dontBroadcast) { int bot = GetClientOfUserId(event.GetInt("bot")) int player = GetClientOfUserId(event.GetInt("player")) @@ -87,7 +87,7 @@ public Action Event_OnPlayerReplacedByBot(Event event, const char[] name, bool d if (bDebug) CPrintToChatAll("{green}[{olive}OnPlayerReplacedByBot{green}] {default}- {blue}BOT {default}replaced {blue}%N {default}({green}Secondary: {olive}%s{default})", player, sSecondary[bot]); } -public Action Event_OnBotReplacedByPlayer(Event event, const char[] name, bool dontBroadcast) +public void Event_OnBotReplacedByPlayer(Event event, const char[] name, bool dontBroadcast) { int bot = GetClientOfUserId(event.GetInt("bot")) int player = GetClientOfUserId(event.GetInt("player")) @@ -105,7 +105,7 @@ public Action Event_OnBotReplacedByPlayer(Event event, const char[] name, bool d * THIS FIRES AND STORES A PLAYER'S SECONDARY * *****************************************************************************************/ -public Action Event_OnPlayerUse(Event event, const char[] name, bool dontBroadcast) +public void Event_OnPlayerUse(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); int targetid = event.GetInt("targetid"); @@ -151,6 +151,8 @@ public Action Event_OnPlayerDeath(Event event, const char[] name, bool dontBroad if (bDebug) CPrintToChatAll("{green}[{olive}OnPlayerDeath{green}] {default}- {blue}%N {default}({green}Secondary: {olive}%s{default})", victim, sSecondary[victim]); SpawnSecondary(victim); } + + return Plugin_Continue; } bool IsValidSurvivor(int client) diff --git a/addons/sourcemod/scripting/l4d2_fix_spawn_order.sp b/addons/sourcemod/scripting/l4d2_fix_spawn_order.sp index 498f9e525..50e711ed8 100644 --- a/addons/sourcemod/scripting/l4d2_fix_spawn_order.sp +++ b/addons/sourcemod/scripting/l4d2_fix_spawn_order.sp @@ -32,7 +32,7 @@ new spitterlimit; new maxSI; /* These class numbers are the same ones used internally in L4D2 */ -enum SIClass +enum /*SIClass*/ { SI_None=0, SI_Smoker=1, @@ -47,7 +47,7 @@ enum SIClass SI_MAX_SIZE }; -stock const String:g_sSIClassNames[view_as(SI_MAX_SIZE)][] = +stock const String:g_sSIClassNames[SI_MAX_SIZE][] = { "", "Smoker", "Boomer", "Hunter", "Spitter", "Jockey", "Charger", "Witch", "Tank" }; public Plugin:myinfo = @@ -167,9 +167,11 @@ public Action:L4D_OnFirstSurvivorLeftSafeArea(client) FillArray(g_SpawnsArray); bLive = true; } + + return Plugin_Continue; } -public L4D_OnEnterGhostState(client) +public void L4D_OnEnterGhostState(client) { // Is Game live? // Is Valid Client? @@ -203,9 +205,11 @@ public Action:L4D_OnTryOfferingTankBot(tank_index, &bool:enterStasis) // This method will work, but it will only work with Configs/Server setups that use L4D Tank Control CreateTimer(0.01, CheckTankie); } + + return Plugin_Continue; } -public L4D2_OnTankPassControl(oldTank, newTank, passCount) +public void L4D2_OnTankPassControl(oldTank, newTank, passCount) { if (!IsFakeClient(newTank)) { @@ -239,6 +243,8 @@ public Action:CheckTankie(Handle:timer) } } } + + return Plugin_Stop; } public cvarChanged(Handle:cvar, const String:oldValue[], const String:newValue[]) diff --git a/addons/sourcemod/scripting/l4d2_getup_slide_fix.sp b/addons/sourcemod/scripting/l4d2_getup_slide_fix.sp index 453dcab26..b6f3f9ca8 100644 --- a/addons/sourcemod/scripting/l4d2_getup_slide_fix.sp +++ b/addons/sourcemod/scripting/l4d2_getup_slide_fix.sp @@ -5,30 +5,29 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include +static const int getUpAnimations[SurvivorCharacter_Size][5] = +{ + //l4d2 + // 0: Nick, 1: Rochelle, 2: Coach, 3: Ellis + //[][4] = Flying animation from being hit by a tank + {620, 667, 671, 672, 629}, //Nick + {629, 674, 678, 679, 637}, //Rochelle + {621, 656, 660, 661, 629}, //Coach + {625, 671, 675, 676, 634}, //Ellis + + //l4d1 + // 4: Bill, 5: Zoey, 6: Louis, 7: Francis + {528, 759, 763, 764, 537}, //Bill + {537, 819, 823, 824, 546}, //Zoey + {528, 759, 763, 764, 537}, //Louis + {531, 762, 766, 767, 540} //Francis +}; + bool - isSurvivorStaggerBlocked[view_as(SurvivorCharacter_Size)]; - -static const int - getUpAnimations[view_as(SurvivorCharacter_Size)][5] = - { - //l4d2 - // 0: Nick, 1: Rochelle, 2: Coach, 3: Ellis - //[][4] = Flying animation from being hit by a tank - {620, 667, 671, 672, 629}, //Nick - {629, 674, 678, 679, 637}, //Rochelle - {621, 656, 660, 661, 629}, //Coach - {625, 671, 675, 676, 634}, //Ellis - - //l4d1 - // 4: Bill, 5: Zoey, 6: Louis, 7: Francis - {528, 759, 763, 764, 537}, //Bill - {537, 819, 823, 824, 546}, //Zoey - {528, 759, 763, 764, 537}, //Louis - {531, 762, 766, 767, 540} //Francis - }; + isSurvivorStaggerBlocked[SurvivorCharacter_Size]; public Plugin myinfo = { @@ -63,7 +62,7 @@ public void OnMapEnd() public void Event_BotPlayerReplace(Event hEvent, const char[] eName, bool dontBroadcast) { int player = GetClientOfUserId(hEvent.GetInt("player")); - SurvivorCharacter charIndex = IdentifySurvivor(player); + int charIndex = IdentifySurvivor(player); if (charIndex == SurvivorCharacter_Invalid) { return; } @@ -77,7 +76,7 @@ public void Event_BotPlayerReplace(Event hEvent, const char[] eName, bool dontBr public void Event_PlayerBotReplace(Event hEvent, const char[] eName, bool dontBroadcast) { int bot = GetClientOfUserId(hEvent.GetInt("bot")); - SurvivorCharacter charIndex = IdentifySurvivor(bot); + int charIndex = IdentifySurvivor(bot); if (charIndex == SurvivorCharacter_Invalid) { return; } @@ -90,7 +89,7 @@ public void Event_PlayerBotReplace(Event hEvent, const char[] eName, bool dontBr public void Event_PounceChargeEnd(Event hEvent, const char[] eName, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("victim")); - SurvivorCharacter charIndex = IdentifySurvivor(client); + int charIndex = IdentifySurvivor(client); if (charIndex == SurvivorCharacter_Invalid) { return; } @@ -104,11 +103,13 @@ public Action HookOnThink(Handle hTimer, any client) if (client && IsSurvivor(client)) { SDKHook(client, SDKHook_PostThink, OnThink); } + + return Plugin_Stop; } public void OnThink(int client) { - SurvivorCharacter charIndex = IdentifySurvivor(client); + int charIndex = IdentifySurvivor(client); if (charIndex == SurvivorCharacter_Invalid) { return; } @@ -122,11 +123,11 @@ public void OnThink(int client) public Action L4D2_OnStagger(int target, int source) { - if (L4D2Util_IsValidClient(source) && IsInfected(source)) { - L4D2_Infected sourceClass = GetInfectedClass(source); + if (IsValidInfected(source)) { + int sourceClass = GetInfectedClass(source); if (sourceClass == L4D2Infected_Hunter || sourceClass == L4D2Infected_Jockey) { - SurvivorCharacter charIndex = IdentifySurvivor(target); + int charIndex = IdentifySurvivor(target); if (charIndex == SurvivorCharacter_Invalid) { return Plugin_Continue; } @@ -142,11 +143,11 @@ public Action L4D2_OnStagger(int target, int source) public Action L4D2_OnPounceOrLeapStumble(int victim, int attacker) { - if (L4D2Util_IsValidClient(attacker) && IsInfected(attacker)) { - L4D2_Infected sourceClass = GetInfectedClass(attacker); + if (IsValidInfected(attacker)) { + int sourceClass = GetInfectedClass(attacker); if (sourceClass == L4D2Infected_Hunter || sourceClass == L4D2Infected_Jockey) { - SurvivorCharacter charIndex = IdentifySurvivor(victim); + int charIndex = IdentifySurvivor(victim); if (charIndex == SurvivorCharacter_Invalid) { return Plugin_Continue; } @@ -162,7 +163,7 @@ public Action L4D2_OnPounceOrLeapStumble(int victim, int attacker) void ResetStaggerBlocked() { - for (int i = 0; i < view_as(SurvivorCharacter_Size); i++) { + for (int i = 0; i < SurvivorCharacter_Size; i++) { isSurvivorStaggerBlocked[i] = false; } } diff --git a/addons/sourcemod/scripting/l4d2_getupfix.sp b/addons/sourcemod/scripting/l4d2_getupfix.sp index 25429ae85..04fad72e4 100644 --- a/addons/sourcemod/scripting/l4d2_getupfix.sp +++ b/addons/sourcemod/scripting/l4d2_getupfix.sp @@ -7,15 +7,6 @@ #include #include //#include -public Plugin myinfo = -{ - name = "L4D2 Get-Up Fix", - author = "Blade, ProdigySim, DieTeetasse, Stabby, Jahze, A1m`", - description = "Double/no/self-clear get-up fix.", - version = "1.7.4", - url = "https://github.com/SirPlease/L4D2-Competitive-Rework/" -} - #define ANIM_HUNTER_LENGTH 2.2 // frames: 64, fps: 30, length: 2.133 #define ANIM_CHARGER_STANDARD_LENGTH 2.9 // frames: 85, fps 30, length: 2.833 #define ANIM_CHARGER_SLAMMED_WALL_LENGTH 3.9 // frames 116 fps 30 = 3.867 @@ -48,7 +39,7 @@ int bArClientAlreadyChecked[MAXPLAYERS + 1]; //in the rare event of it being a game with multiple chargers and 2+ getting cleared on slam static const int - getUpAnimations[view_as(SurvivorCharacter_Size)][view_as(eINDEX_SIZE)] = + getUpAnimations[SurvivorCharacter_Size][eINDEX_SIZE] = { // l4d2 // 0: Nick, 1: Rochelle, 2: Coach, 3: Ellis @@ -65,7 +56,7 @@ static const int {531, 762, 766, 767} //Francis }, //incapped animations: 0 = single-pistol, 1 = dual pistols - incapAnimations[view_as(SurvivorCharacter_Size)][view_as(eINCAP_ANIMATIONS_SIZE)] = + incapAnimations[SurvivorCharacter_Size][eINCAP_ANIMATIONS_SIZE] = { // l4d2 // 0: Nick, 1: Rochelle, 2: Coach, 3: Ellis @@ -82,6 +73,15 @@ static const int {523, 524} //Francis }; +public Plugin myinfo = +{ + name = "L4D2 Get-Up Fix", + author = "Blade, ProdigySim, DieTeetasse, Stabby, Jahze, A1m`", //Add support sm1.11 - A1m` + description = "Double/no/self-clear get-up fix.", + version = "1.7.4", + url = "https://github.com/SirPlease/L4D2-Competitive-Rework/" +}; + public void OnPluginStart() { HookEvent("pounce_end", Event_PounceOrPummel); @@ -105,7 +105,7 @@ public Action Timer_ProcessClient(Handle hTimer, any client) void ProcessClient(int client) { - SurvivorCharacter charIndex = IdentifySurvivor(client); + int charIndex = IdentifySurvivor(client); if (charIndex == SurvivorCharacter_Invalid) { return; } @@ -147,7 +147,7 @@ public Action Timer_CheckClient(Handle hTimer, ArrayStack tempStack) int oldSequence = tempStack.Pop(); int client = tempStack.Pop(); - SurvivorCharacter charIndex = IdentifySurvivor(client); + int charIndex = IdentifySurvivor(client); if (charIndex == SurvivorCharacter_Invalid) { return Plugin_Stop; } @@ -192,7 +192,7 @@ public Action GetupTimer(Handle hTimer, any attacker) for (int i = 1; i <= MaxClients; i++) { if (IsSurvivor(i) && !bArClientAlreadyChecked[i]) { int seq = GetEntProp(i, Prop_Send, "m_nSequence"); - SurvivorCharacter character = IdentifySurvivor(i); + int character = IdentifySurvivor(i); if (character == SurvivorCharacter_Invalid) { return Plugin_Stop; diff --git a/addons/sourcemod/scripting/l4d2_godframes_control_merge.sp b/addons/sourcemod/scripting/l4d2_godframes_control_merge.sp index f0029d83a..772380769 100644 --- a/addons/sourcemod/scripting/l4d2_godframes_control_merge.sp +++ b/addons/sourcemod/scripting/l4d2_godframes_control_merge.sp @@ -77,10 +77,10 @@ int g_iEnabledFlags = 0, g_iBlockZeroDmg = 0, g_iLastHealth[MAXPLAYERS + 1][UNDO_SIZE][2], // The Undo Damage array, with correlated arrays for holding the last revive count and current undo index - g_iLastReviveCount[MAXPLAYERS + 1] = {0, ... }; - g_iCurrentUndo[MAXPLAYERS + 1] = {0, ... }; - g_iTargetTempHealth[MAXPLAYERS + 1] = {0, ... }; // Healing is weird, so this keeps track of our target OR the target's temp health - g_iLastPerm[MAXPLAYERS + 1] = {100, ... }; // The permanent damage fraction requires some coordination between OnTakeDamage and player_hurt + g_iLastReviveCount[MAXPLAYERS + 1] = {0, ... }, + g_iCurrentUndo[MAXPLAYERS + 1] = {0, ... }, + g_iTargetTempHealth[MAXPLAYERS + 1] = {0, ... }, // Healing is weird, so this keeps track of our target OR the target's temp health + g_iLastPerm[MAXPLAYERS + 1] = {100, ... }, // The permanent damage fraction requires some coordination between OnTakeDamage and player_hurt g_iLastTemp[MAXPLAYERS + 1] = {0, ... }; float @@ -253,7 +253,8 @@ public void OnClientPutInServer(int iClient) // // ////////////////////////////////////////////////////////////////////////////////////////////////////////////////// */ -public Action Timed_SetFrustration(Handle hTimer, any iClient) { +public Action Timed_SetFrustration(Handle hTimer, any iClient) +{ if (IsTank(iClient) && IsPlayerAlive(iClient)) { int iFrust = GetEntProp(iClient, Prop_Send, "m_frustration"); iFrust += g_iFrustrationOffset[iClient]; @@ -267,13 +268,15 @@ public Action Timed_SetFrustration(Handle hTimer, any iClient) { SetEntProp(iClient, Prop_Send, "m_frustration", iFrust); g_iFrustrationOffset[iClient] = 0; } + + return Plugin_Stop; } public Action OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, float &fDamage, \ int &iDamagetype, int &iWeapon, float fDamageForce[3], float fDamagePosition[3]) { if (!IsValidSurvivor(iVictim) || !IsValidEdict(iAttacker) || !IsValidEdict(iInflictor)) { - return Plugin_Continue; + return Plugin_Continue; } CountdownTimer cTimerGod = L4D2Direct_GetInvulnerabilityTimer(iVictim); // left4dhooks @@ -426,7 +429,7 @@ public Action OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, float & } } - if (L4D2Util_IsValidClient(iAttacker) && IsTank(iAttacker)) { + if (IsValidClientIndex(iAttacker) && IsTank(iAttacker)) { if (strcmp(sClassname, "prop_physics") == 0|| strcmp(sClassname, "prop_car_alarm") == 0) { if (g_hRageHittables.BoolValue) { g_iFrustrationOffset[iAttacker] = -100; @@ -480,6 +483,8 @@ public Action Timed_ResetGlow(Handle hTimer, any iClient) SetEntityRenderMode(iClient, RENDER_NORMAL); SetEntityRenderColor(iClient, 255, 255, 255, 255); } + + return Plugin_Stop; } public void OnMapStart() @@ -599,6 +604,8 @@ public Action Event_PlayerIncapStart(Event hEvent, const char[] sEventName, bool UndoDamage(iVictim); } } + + return Plugin_Continue; } // If a bot is guilty of creating a friendly fire event, undo it @@ -621,6 +628,8 @@ public Action Event_FriendlyFire(Event hEvent, const char[] sEventName, bool bDo public Action StupidGuiltyBotDelay(Handle hTimer, any iClient) { g_bStupidGuiltyBots[iClient] = false; + + return Plugin_Stop; } // While a Charger is carrying a Survivor, undo any friendly fire done to them @@ -653,6 +662,8 @@ public Action Event_ChargerCarryEnd(Event hEvent, const char[] sEventName, bool public Action ChargerCarryFFDelay(Handle hTimer, any iClient) { g_bChargerCarryNoFF[iClient] = false; + + return Plugin_Stop; } // For health kit undo, we must remember the target in HealBegin diff --git a/addons/sourcemod/scripting/l4d2_hittable_control.sp b/addons/sourcemod/scripting/l4d2_hittable_control.sp index 613942c9b..fd92f2ef5 100644 --- a/addons/sourcemod/scripting/l4d2_hittable_control.sp +++ b/addons/sourcemod/scripting/l4d2_hittable_control.sp @@ -144,8 +144,8 @@ public void OnPluginStart() } } - HookEvent("round_start", Event_RoundStart); - HookEvent("finale_radio_start", Event_FinaleStart); + HookEvent("round_start", Event_RoundStart, EventHookMode_PostNoCopy); + HookEvent("finale_radio_start", Event_FinaleStart, EventHookMode_PostNoCopy); hUnbreakableForklifts.AddChangeHook(ConVarChanged_UnbreakableForklifts); } @@ -157,12 +157,13 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max RegPluginLibrary("l4d2_hittable_control"); return APLRes_Success; } + public void OnClientPutInServer(int client) { SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); } -public Action Event_RoundStart(Event event, const char[] name, bool dontBroadcast) +public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) { // Reset everything to make sure we don't run into issues when a map is restarted (as GameTime resets) for (int i = 1; i <= MaxClients; i++) @@ -205,6 +206,8 @@ public Action PatchBreakableForklifts(Handle timer) SetEntProp(forklift, Prop_Data, "m_takedamage", 1); } } + + return Plugin_Stop; } public Action UnpatchBreakableForklifts(Handle timer) @@ -223,6 +226,8 @@ public Action UnpatchBreakableForklifts(Handle timer) SetEntProp(forklift, Prop_Data, "m_takedamage", 3); } } + + return Plugin_Stop; } public void ConVarChanged_UnbreakableForklifts(ConVar hConVar, const char[] sOldValue, const char[] sNewValue) @@ -238,11 +243,11 @@ public void ConVarChanged_UnbreakableForklifts(ConVar hConVar, const char[] sOld } -public any Native_UnbreakableForklifts(Handle plugin, int numParams) { +public int Native_UnbreakableForklifts(Handle plugin, int numParams) { return GetConVarBool(hUnbreakableForklifts); } -public Action Event_FinaleStart(Event event, const char[] name, bool dontBroadcast) +public void Event_FinaleStart(Event event, const char[] name, bool dontBroadcast) { // Hittable damage is only reduced once the finale is triggered int triggerFinale = -1; diff --git a/addons/sourcemod/scripting/l4d2_hybrid_scoremod.sp b/addons/sourcemod/scripting/l4d2_hybrid_scoremod.sp index e37123f40..b2461b30a 100644 --- a/addons/sourcemod/scripting/l4d2_hybrid_scoremod.sp +++ b/addons/sourcemod/scripting/l4d2_hybrid_scoremod.sp @@ -86,7 +86,7 @@ public OnPluginStart() HookConVarChange(hCvarBonusPerSurvivorMultiplier, CvarChanged); HookConVarChange(hCvarPermanentHealthProportion, CvarChanged); - HookEvent("round_start", EventHook:RoundStartEvent, EventHookMode_PostNoCopy); + HookEvent("round_start", RoundStartEvent, EventHookMode_PostNoCopy); HookEvent("player_ledge_grab", OnPlayerLedgeGrab); HookEvent("player_hurt", OnPlayerHurt); HookEvent("revive_success", OnPlayerRevived, EventHookMode_Post); @@ -165,7 +165,7 @@ public OnClientDisconnect(client) SDKUnhook(client, SDKHook_OnTakeDamagePost, OnTakeDamagePost); } -public RoundStartEvent() +public void RoundStartEvent(Event hEvent, const char[] sEventName, bool bDontBroadcast) { for (new i = 0; i <= MAXPLAYERS; i++) { @@ -285,7 +285,7 @@ public OnPlayerLedgeGrab(Handle:event, const String:name[], bool:dontBroadcast) iLostTempHealth[InSecondHalfOfRound()] += L4D2Direct_GetPreIncapHealthBuffer(client); } -public Action OnPlayerRevived(Handle:event, const String:name[], bool:dontBroadcast) +public void OnPlayerRevived(Handle:event, const String:name[], bool:dontBroadcast) { bool bLedge = GetEventBool(event, "ledge_hang"); if (!bLedge) return; @@ -301,7 +301,7 @@ public void Revival(int client) iLostTempHealth[InSecondHalfOfRound()] -= GetSurvivorTemporaryHealth(client); } -public Action:OnPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) +public void OnPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) { new victim = GetClientOfUserId(GetEventInt(event, "userid")); new attacker = GetClientOfUserId(GetEventInt(event, "attacker")); @@ -315,18 +315,18 @@ public Action:OnPlayerHurt(Handle:event, const String:name[], bool:dontBroadcast // Player can't be Incapped. // Damage has to be from manipulated Shotgun FF. (Plasma) // Damage has to be higher than the Survivor's permanent health. - if (!IsSurvivor(victim) || !IsSurvivor(attacker) || IsPlayerIncap(victim) || damagetype != DMG_PLASMA || fFakeDamage < GetSurvivorPermanentHealth(victim)) return Plugin_Continue; - + if (!IsSurvivor(victim) || !IsSurvivor(attacker) || IsPlayerIncap(victim) || damagetype != DMG_PLASMA || fFakeDamage < GetSurvivorPermanentHealth(victim)) { + return; + } + iTempHealth[victim] = GetSurvivorTemporaryHealth(victim); if (fFakeDamage > iTempHealth[victim]) fFakeDamage = iTempHealth[victim]; iLostTempHealth[InSecondHalfOfRound()] += fFakeDamage; iTempHealth[victim] = GetSurvivorTemporaryHealth(victim) - fFakeDamage; - - return Plugin_Continue; } -public OnTakeDamagePost(victim, attacker, inflictor, Float:damage, damagetype) +public void OnTakeDamagePost(victim, attacker, inflictor, Float:damage, damagetype) { if (!IsSurvivor(victim)) return; @@ -419,6 +419,8 @@ public Action:PrintRoundEndStats(Handle:timer) PrintToChatAll("%s\x05Teams have performed absolutely equal! Impossible to decide a clear round winner", PLUGIN_TAG); } } + + return Plugin_Stop; } Float:GetSurvivorHealthBonus() diff --git a/addons/sourcemod/scripting/l4d2_hybrid_scoremod_zone.sp b/addons/sourcemod/scripting/l4d2_hybrid_scoremod_zone.sp index b6eba0f78..f46323d43 100644 --- a/addons/sourcemod/scripting/l4d2_hybrid_scoremod_zone.sp +++ b/addons/sourcemod/scripting/l4d2_hybrid_scoremod_zone.sp @@ -85,7 +85,7 @@ public OnPluginStart() HookConVarChange(hCvarBonusPerSurvivorMultiplier, CvarChanged); HookConVarChange(hCvarPermanentHealthProportion, CvarChanged); - HookEvent("round_start", EventHook:RoundStartEvent, EventHookMode_PostNoCopy); + HookEvent("round_start", RoundStartEvent, EventHookMode_PostNoCopy); HookEvent("player_ledge_grab", OnPlayerLedgeGrab); HookEvent("player_incapacitated", OnPlayerIncapped); HookEvent("player_hurt", OnPlayerHurt); @@ -165,7 +165,7 @@ public OnClientDisconnect(client) SDKUnhook(client, SDKHook_OnTakeDamagePost, OnTakeDamagePost); } -public RoundStartEvent() +public void RoundStartEvent(Event hEvent, const char[] sEventName, bool bDontBroadcast) { for (new i = 0; i <= MAXPLAYERS; i++) { @@ -294,14 +294,18 @@ public OnPlayerIncapped(Handle:event, const String:name[], bool:dontBroadcast) } } -public Action OnPlayerRevived(Handle:event, const String:name[], bool:dontBroadcast) +public void OnPlayerRevived(Handle:event, const String:name[], bool:dontBroadcast) { bool bLedge = GetEventBool(event, "ledge_hang"); - if (!bLedge) return; - + if (!bLedge) { + return; + } + int client = GetClientOfUserId(GetEventInt(event, "subject")); - if (!IsSurvivor(client)) return; - + if (!IsSurvivor(client)) { + return; + } + RequestFrame(Revival, client); } @@ -428,6 +432,8 @@ public Action:PrintRoundEndStats(Handle:timer) PrintToChatAll("%s\x05Teams have performed absolutely equal! Impossible to decide a clear round winner", PLUGIN_TAG); } } + + return Plugin_Stop; } Float:GetSurvivorHealthBonus() diff --git a/addons/sourcemod/scripting/l4d2_jockey_jumpcap_patch.sp b/addons/sourcemod/scripting/l4d2_jockey_jumpcap_patch.sp index 7ec49f462..c973b5042 100644 --- a/addons/sourcemod/scripting/l4d2_jockey_jumpcap_patch.sp +++ b/addons/sourcemod/scripting/l4d2_jockey_jumpcap_patch.sp @@ -93,7 +93,7 @@ public MRESReturn CLeap_OnTouch(int ability, Handle hParams) bool IsAbilityActive(int ability) { - return view_as(GetEntProp(ability, Prop_Send, "m_isLeaping")); + return view_as(GetEntProp(ability, Prop_Send, "m_isLeaping", 1)); } bool IsJockey(int client) @@ -107,8 +107,8 @@ bool IsJockey(int client) bool IsSurvivor(int client) { - return (client > 0 - && client <= MaxClients - && IsClientInGame(client) + return (client > 0 + && client <= MaxClients + && IsClientInGame(client) && GetClientTeam(client) == TEAM_SURVIVOR); } diff --git a/addons/sourcemod/scripting/l4d2_jockey_skeet.sp b/addons/sourcemod/scripting/l4d2_jockey_skeet.sp index b588b6940..0adee4946 100644 --- a/addons/sourcemod/scripting/l4d2_jockey_skeet.sp +++ b/addons/sourcemod/scripting/l4d2_jockey_skeet.sp @@ -99,7 +99,8 @@ public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &dam } CreateTimer(0.1, ResetDamageCounter, victim); } - return Plugin_Continue; + + return Plugin_Continue; } public Action ResetDamageCounter(Handle hTimer, any jockey) @@ -107,6 +108,8 @@ public Action ResetDamageCounter(Handle hTimer, any jockey) for (int i = 1; i <= MaxClients; i++) { inflictedDamage[jockey][i] = 0.0; } + + return Plugin_Stop; } bool IsSurvivor(int client) diff --git a/addons/sourcemod/scripting/l4d2_ladderblock.sp b/addons/sourcemod/scripting/l4d2_ladderblock.sp index b9198255d..852b0c141 100644 --- a/addons/sourcemod/scripting/l4d2_ladderblock.sp +++ b/addons/sourcemod/scripting/l4d2_ladderblock.sp @@ -45,7 +45,7 @@ ConVar bool g_bLoadLate = false, - g_iInCharge[MAXPLAYERS + 1] = {0, ...}; + g_iInCharge[MAXPLAYERS + 1] = {false, ...}; public Plugin myinfo = { diff --git a/addons/sourcemod/scripting/l4d2_m2_control_eq.sp b/addons/sourcemod/scripting/l4d2_m2_control_eq.sp index c21e2b724..c8ff618e8 100644 --- a/addons/sourcemod/scripting/l4d2_m2_control_eq.sp +++ b/addons/sourcemod/scripting/l4d2_m2_control_eq.sp @@ -2,7 +2,7 @@ #pragma newdecls required #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #include @@ -70,8 +70,7 @@ public void OutSkilled(Event hEvent, const char[] eName, bool dontBroadcast) return; } - int penaltyIncrease; - L4D2_Infected zClass = GetInfectedClass(shovee); + int penaltyIncrease, zClass = GetInfectedClass(shovee); switch (zClass) { case L4D2Infected_Hunter: { penaltyIncrease = hPenaltyIncreaseHunterCvar.IntValue; @@ -98,8 +97,7 @@ public void OutSkilled(Event hEvent, const char[] eName, bool dontBroadcast) L4D2Direct_SetShovePenalty(shover, penalty); L4D2Direct_SetNextShoveTime(shover, CalcNextShoveTime(penalty, maxPenalty)); - if (zClass == L4D2Infected_Smoker - || (zClass == L4D2Infected_Hunter && g_NoHunterM2)) { + if (zClass == L4D2Infected_Smoker || (zClass == L4D2Infected_Hunter && g_NoHunterM2)) { return; } @@ -115,7 +113,7 @@ public Action ResetAbilityTimer(Handle hTimer, any shovee_userid) float timestamp, duration; if (!GetInfectedAbilityTimer(shovee, timestamp, duration)) { - return; + return Plugin_Stop; } duration = GetGameTime() + recharge + STAGGER_TIME_EPS; @@ -123,6 +121,8 @@ public Action ResetAbilityTimer(Handle hTimer, any shovee_userid) SetInfectedAbilityTimer(shovee, duration, recharge); } } + + return Plugin_Stop; } float CalcNextShoveTime(int currentPenalty, int maxPenalty) diff --git a/addons/sourcemod/scripting/l4d2_map_transitions.sp b/addons/sourcemod/scripting/l4d2_map_transitions.sp index 4ed2baf81..eaab94b0e 100644 --- a/addons/sourcemod/scripting/l4d2_map_transitions.sp +++ b/addons/sourcemod/scripting/l4d2_map_transitions.sp @@ -144,6 +144,8 @@ public void OnMapStart() public Action Timer_OnMapStartDelay(Handle hTimer) { SetScores(); + + return Plugin_Stop; } void SetScores() diff --git a/addons/sourcemod/scripting/l4d2_melee_damage_control.sp b/addons/sourcemod/scripting/l4d2_melee_damage_control.sp index f7efd8f81..3455e3d70 100644 --- a/addons/sourcemod/scripting/l4d2_melee_damage_control.sp +++ b/addons/sourcemod/scripting/l4d2_melee_damage_control.sp @@ -148,7 +148,7 @@ public Action Hook_OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, fl } int iZclass = GetEntProp(iVictim, Prop_Send, "m_zombieClass", 4); - if (iZclass <= view_as(L4D2Infected_Jockey)) { + if (iZclass <= L4D2Infected_Jockey) { if (g_bMeleeDmgFixEnable) { #if DEBUG @@ -160,7 +160,7 @@ public Action Hook_OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, fl fDamage = float(GetClientHealth(iVictim)); return Plugin_Changed; } - } else if (iZclass == view_as(L4D2Infected_Charger)) { + } else if (iZclass == L4D2Infected_Charger) { if (g_fChargerMeleeDamage > 0.0) { float fHealth = float(GetClientHealth(iVictim)); @@ -174,7 +174,7 @@ public Action Hook_OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, fl fDamage = (fHealth < g_fChargerMeleeDamage) ? fHealth : g_fChargerMeleeDamage; // Deal requested Damage to Chargers. return Plugin_Changed; } - } else if (iZclass == view_as(L4D2Infected_Tank)) { + } else if (iZclass == L4D2Infected_Tank) { if (g_fTankMeleeNerfDamage > 0.0) { #if DEBUG @@ -213,7 +213,7 @@ bool IsSurvivor(int iClient) return (iClient > 0 && iClient <= MaxClients && IsClientInGame(iClient) - && GetClientTeam(iClient) == view_as(L4D2Team_Survivor)); + && GetClientTeam(iClient) == L4D2Team_Survivor); } bool IsInfected(int iClient) @@ -221,5 +221,5 @@ bool IsInfected(int iClient) return (iClient > 0 && iClient <= MaxClients && IsClientInGame(iClient) - && GetClientTeam(iClient) == view_as(L4D2Team_Infected)); + && GetClientTeam(iClient) == L4D2Team_Infected); } diff --git a/addons/sourcemod/scripting/l4d2_nobackjumps.sp b/addons/sourcemod/scripting/l4d2_nobackjumps.sp index 13a2a2272..a26288134 100644 --- a/addons/sourcemod/scripting/l4d2_nobackjumps.sp +++ b/addons/sourcemod/scripting/l4d2_nobackjumps.sp @@ -69,7 +69,7 @@ public void ResetEvent(Event hEvent, const char[] eName, bool dontBroadcast) } } -public Action OnPlayerJump(Event hEvent, const char[] eName, bool dontBroadcast) +public void OnPlayerJump(Event hEvent, const char[] eName, bool dontBroadcast) { int client = GetClientOfUserId(hEvent.GetInt("userid")); @@ -92,7 +92,7 @@ public MRESReturn CLunge_ActivateAbility(int ability) bool IsOutwardJump(int client) { bool IsGround = view_as(GetEntityFlags(client) & FL_ONGROUND); - bool IsAttemptingToPounce = view_as(GetEntProp(client, Prop_Send, "m_isAttemptingToPounce")); + bool IsAttemptingToPounce = view_as(GetEntProp(client, Prop_Send, "m_isAttemptingToPounce", 1)); return (!IsAttemptingToPounce && !IsGround); } @@ -109,5 +109,5 @@ bool IsHunter(int client) bool IsGhost(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isGhost")); + return view_as(GetEntProp(client, Prop_Send, "m_isGhost", 1)); } diff --git a/addons/sourcemod/scripting/l4d2_nosecondchances.sp b/addons/sourcemod/scripting/l4d2_nosecondchances.sp index d8c2307bd..0311ef67a 100644 --- a/addons/sourcemod/scripting/l4d2_nosecondchances.sp +++ b/addons/sourcemod/scripting/l4d2_nosecondchances.sp @@ -15,6 +15,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ + #pragma semicolon 1 #pragma newdecls required @@ -89,4 +90,6 @@ public Action Timer_KillBotDelay(Handle hTimer, any iUserID) if (iBot > 0 && IsPlayerAlive(iBot) && ShouldBeKicked(iBot)) { ForcePlayerSuicide(iBot); } + + return Plugin_Stop; } diff --git a/addons/sourcemod/scripting/l4d2_nosey_parker.sp b/addons/sourcemod/scripting/l4d2_nosey_parker.sp index 336bd29dc..df94d492f 100644 --- a/addons/sourcemod/scripting/l4d2_nosey_parker.sp +++ b/addons/sourcemod/scripting/l4d2_nosey_parker.sp @@ -24,7 +24,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define TEAM_SURVIVOR 2 @@ -120,7 +120,7 @@ public void Event_PlayerDeath(Event hEvent, const char[] sEventName, bool bDontB g_iDamage[i][iClient] = 0; } - if (iZClass == view_as(L4D2Infected_Smoker)) { + if (iZClass == L4D2Infected_Smoker) { ClearTimer(); } } @@ -186,6 +186,7 @@ public Action CheckSurvivorState(Handle hTimer, ArrayStack hEventMembers) // delete hEventMembers; // TIMER_HNDL_CLOSE, the timer will do for us g_hTongueParalyzeTimer = null; + return Plugin_Stop; } public void Event_SmokerAttackSecond(Event hEvent, const char[] sEventName, bool bDontBroadcast) @@ -235,14 +236,14 @@ void PrintInflictedDamage(int iSurvivor, int iInfected) int IsTargetedSi(int iClient) { - L4D2_Infected iZClass = view_as(GetEntProp(iClient, Prop_Send, "m_zombieClass")); + int iZClass = GetEntProp(iClient, Prop_Send, "m_zombieClass"); if (iZClass == L4D2Infected_Smoker || iZClass == L4D2Infected_Hunter || iZClass == L4D2Infected_Jockey || iZClass == L4D2Infected_Charger ) { - return view_as(iZClass); + return iZClass; } return -1; diff --git a/addons/sourcemod/scripting/l4d2_penalty_bonus.sp b/addons/sourcemod/scripting/l4d2_penalty_bonus.sp index 824b7a8c0..b6a0c7a19 100644 --- a/addons/sourcemod/scripting/l4d2_penalty_bonus.sp +++ b/addons/sourcemod/scripting/l4d2_penalty_bonus.sp @@ -275,6 +275,8 @@ public Action L4D2_OnEndVersusModeRound(bool bCountSurvivors) g_bSetSameChange = false; SetBonus(); + + return Plugin_Continue; } // Bonus @@ -405,6 +407,8 @@ public int Native_ResetRoundBonus(Handle hPlugin, int iNumParams) g_iSameChange = 0; g_bSetSameChange = true; + + return 1; } public int Native_SetRoundBonus(Handle hPlugin, int iNumParams) @@ -423,6 +427,8 @@ public int Native_SetRoundBonus(Handle hPlugin, int iNumParams) if (g_hCvarReportChange.BoolValue) { ReportChange(0, -1, true); } + + return 1; } public int Native_AddRoundBonus(Handle hPlugin, int iNumParams) @@ -448,6 +454,8 @@ public int Native_AddRoundBonus(Handle hPlugin, int iNumParams) ReportChange(iBonus); } } + + return 1; } public int Native_GetDefibsUsed(Handle hPlugin, int iNumParams) @@ -460,4 +468,6 @@ public int Native_SetDefibPenalty(Handle hPlugin, int iNumParams) int iPenalty = GetNativeCell(1); g_iOriginalPenalty = iPenalty; + + return 1; } diff --git a/addons/sourcemod/scripting/l4d2_pickup.sp b/addons/sourcemod/scripting/l4d2_pickup.sp index 962237df6..0bedca680 100644 --- a/addons/sourcemod/scripting/l4d2_pickup.sp +++ b/addons/sourcemod/scripting/l4d2_pickup.sp @@ -31,7 +31,7 @@ #include #include //#include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include //#include #include @@ -156,24 +156,32 @@ public Action DelayUse(Handle hTimer, any client) { bTanked[client] = false; hTanked[client] = null; + + return Plugin_Stop; } public Action DelaySwitchHealth(Handle hTimer, any client) { bCantSwitchHealth[client] = false; hHealth[client] = null; + + return Plugin_Stop; } public Action DelaySwitchSecondary(Handle hTimer, any client) { bCantSwitchSecondary[client] = false; hSecondary[client] = null; + + return Plugin_Stop; } public Action DelayValveSwitch(Handle hTimer, any client) { bPreventValveSwitch[client] = false; hValveSwitch[client] = null; + + return Plugin_Stop; } @@ -224,7 +232,7 @@ public Action WeaponCanSwitchTo(int client, int weapon) char sWeapon[64]; GetEntityClassname(weapon, sWeapon, sizeof(sWeapon)); - WeaponId wep = WeaponNameToId(sWeapon); + int wep = WeaponNameToId(sWeapon); // Health Items. if ((iSwitchFlags[client] & FLAGS_SWITCH_PILLS) && (wep == WEPID_PAIN_PILLS || wep == WEPID_ADRENALINE) && bCantSwitchHealth[client]) { @@ -248,12 +256,12 @@ public Action WeaponEquip(int client, int weapon) // Weapon Currently Using char weapon_name[64]; GetClientWeapon(client, weapon_name, sizeof(weapon_name)); - WeaponId wepname = WeaponNameToId(weapon_name); + int wepname = WeaponNameToId(weapon_name); // New Weapon char sWeapon[64]; GetEntityClassname(weapon, sWeapon, sizeof(sWeapon)); - WeaponId wep = WeaponNameToId(sWeapon); + int wep = WeaponNameToId(sWeapon); // Health Items. if (wep == WEPID_PAIN_PILLS || wep == WEPID_ADRENALINE) { @@ -274,6 +282,7 @@ public Action WeaponEquip(int client, int weapon) hSecondary[client] = CreateTimer(0.1, DelaySwitchSecondary, client); } } + return Plugin_Continue; } @@ -282,10 +291,11 @@ public Action WeaponDrop(int client, int weapon) if (!IsValidEntity(weapon)) { return Plugin_Continue; } + // Weapon Currently Using char weapon_name[64]; GetClientWeapon(client, weapon_name, sizeof(weapon_name)); - WeaponId wepname = WeaponNameToId(weapon_name); + int wepname = WeaponNameToId(weapon_name); // Secondary Weapon //int Secondary = GetPlayerWeaponSlot(client, 1); @@ -293,7 +303,7 @@ public Action WeaponDrop(int client, int weapon) // Weapon Dropping char sWeapon[64]; GetEntityClassname(weapon, sWeapon, sizeof(sWeapon)); - WeaponId wep = WeaponNameToId(sWeapon); + int wep = WeaponNameToId(sWeapon); // Check if Player is Alive/Incapped and just dropped his secondary for a different one if (!IsPlayerIncapacitated(client) && IsPlayerAlive(client)) { diff --git a/addons/sourcemod/scripting/l4d2_playstats.sp b/addons/sourcemod/scripting/l4d2_playstats.sp index d618a0234..00ac5a30b 100644 --- a/addons/sourcemod/scripting/l4d2_playstats.sp +++ b/addons/sourcemod/scripting/l4d2_playstats.sp @@ -869,6 +869,7 @@ public Action Timer_RoundStart(Handle hTimer) ClearPlayerTeam(g_iCurTeam); //PrintDebug(2, "Event_RoundStart (roundhalf: %i: survivor team: %i (cur survivor: %i))", (g_bSecondHalf) ? 1 : 0, g_iCurTeam, GetCurrentTeamSurvivor()); + return Plugin_Stop; } public void Event_RoundEnd(Event hEvent, const char[] eName, bool dontBroadcast) @@ -1098,6 +1099,8 @@ public Action L4D_OnFirstSurvivorLeftSafeArea(int client) if (!g_bReadyUpAvailable) { RoundReallyStarting(); } + + return Plugin_Continue; } void RoundReallyStarting() @@ -1710,6 +1713,8 @@ public Action Timer_TeamChanged(Handle hTimer) { g_bTeamChanged = false; UpdatePlayerCurrentTeam(); + + return Plugin_Stop; } /* @@ -1844,7 +1849,9 @@ public Action Event_PlayerHurt(Event hEvent, const char[] eName, bool dontBroadc vicIndex = attIndex; } else { vicIndex = GetPlayerIndexForClient(victim); - if (vicIndex == -1) { return Plugin_Continue; } + if (vicIndex == -1) { + return Plugin_Continue; + } } // record amounts @@ -2164,6 +2171,8 @@ public Action Timer_CheckTankDeath(Handle hTimer, any client_oldTank) HandleTankTimeEnd(); } } + + return Plugin_Stop; } void HandleTankTimeEnd() @@ -2801,6 +2810,8 @@ public Action Timer_ResetStats(Handle hTimer, any roundOnly) { // reset stats (for current team) ResetStats(view_as(roundOnly)); + + return Plugin_Stop; } // team -1 = clear both; failedround = campaign mode only @@ -3306,7 +3317,7 @@ void DisplayStatsMVPChat(int client, bool bRound = true, bool bTeam = true, int char printBuffer[1024], tmpBuffer[512], strLines[8][192]; int i, j, x; - printBuffer = GetMVPChatString(bRound, bTeam, iTeam); + GetMVPChatString(printBuffer, sizeof(printBuffer), bRound, bTeam, iTeam); // PrintToChatAll has a max length. Split it in to individual lines to output separately int intPieces = ExplodeString(printBuffer, "\n", strLines, sizeof(strLines), sizeof(strLines[])); @@ -3528,12 +3539,10 @@ void DisplayStatsMVPChat(int client, bool bRound = true, bool bTeam = true, int } } -char GetMVPChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) +void GetMVPChatString(char[] printBuffer, const int iLen, bool bRound = true, bool bTeam = true, int iTeam = -1) { - char printBuffer[1024]; char tmpBuffer[512]; - - printBuffer = ""; + printBuffer[0] = '\0'; // SI damage already sorted, sort CI and FF too SortPlayersMVP(bRound, SORT_SI, bTeam, iTeam); @@ -3576,7 +3585,7 @@ char GetMVPChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) // report if (mvp_SI == -1 && mvp_Common == -1 && !(iBrevityFlags & BREV_SI && iBrevityFlags & BREV_CI)) { Format(tmpBuffer, sizeof(tmpBuffer), "[MVP%s]: (not enough action yet)\n", (bRound) ? "" : " - Game"); - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iLen, tmpBuffer); } else { if (!(iBrevityFlags & BREV_SI)) { if (mvp_SI > -1) { @@ -3617,10 +3626,10 @@ char GetMVPChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) ); } - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iLen, tmpBuffer); } else { Format(tmpBuffer, sizeof(tmpBuffer), "[MVP%s] SI: \x03(nobody)\x01\n", (bRound) ? "" : " - Game"); - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iLen, tmpBuffer); } } @@ -3655,7 +3664,7 @@ char GetMVPChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) ); } - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iLen, tmpBuffer); } } } @@ -3667,7 +3676,7 @@ char GetMVPChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) (bRound) ? "" : " - Game" ); - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iLen, tmpBuffer); } else { Format(tmpBuffer, sizeof(tmpBuffer), "[LVP%s] FF:\x03 %s \x01(\x05%d \x01dmg)\n", (bRound) ? "" : " - Game", @@ -3675,11 +3684,9 @@ char GetMVPChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) (bRound) ? g_strRoundPlayerData[mvp_FF][team][plyFFGiven] : g_strPlayerData[mvp_FF][plyFFGiven] ); - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iLen, tmpBuffer); } } - - return printBuffer; } void DisplayStatsMVP(int client, bool bTank = false, bool bMore = false, bool bRound = true, bool bTeam = true, int iTeam = -1) @@ -3897,7 +3904,7 @@ void DisplayStatsFunFactChat(int client, bool bRound = true, bool bTeam = true, char printBuffer[1024], strLines[8][192]; int i, j; - printBuffer = GetFunFactChatString(bRound, bTeam, iTeam); + GetFunFactChatString(printBuffer, sizeof(printBuffer), bRound, bTeam, iTeam); // only print if we got something if (!strlen(printBuffer)) { @@ -3931,22 +3938,18 @@ void DisplayStatsFunFactChat(int client, bool bRound = true, bool bTeam = true, } } -char GetFunFactChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) +void GetFunFactChatString(char[] printBuffer, const int iLen, bool bRound = true, bool bTeam = true, int iTeam = -1) { - char printBuffer[1024]; - - printBuffer = ""; + printBuffer[0] = '\0'; // use current survivor team -- or previous team in second half before starting int team = (iTeam != -1) ? iTeam : ((g_bSecondHalf && !g_bPlayersLeftStart) ? ((g_iCurTeam) ? 0 : 1) : g_iCurTeam); - int i, j; - int wTotal = 0; - int wPicks[256]; + int i, j, wTotal = 0, wPicks[256]; - int wTypeHighPly[FFACT_MAXTYPES+1]; - int wTypeHighVal[FFACT_MAXTYPES+1]; - int wTypeHighTeam[FFACT_MAXTYPES+1]; + int wTypeHighPly[FFACT_MAXTYPES + 1]; + int wTypeHighVal[FFACT_MAXTYPES + 1]; + int wTypeHighTeam[FFACT_MAXTYPES + 1]; // for each type, check whether / and how weighted int wTmp = 0; @@ -4099,7 +4102,7 @@ char GetFunFactChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) } if (!wTotal) { - return printBuffer; + return; } // pick one, format it @@ -4109,28 +4112,28 @@ char GetFunFactChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) switch (wPick) { case FFACT_TYPE_CROWN: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01crowned \x05%d \x01witches.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01crowned \x05%d \x01witches.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_DRAWCROWN: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01draw-crowned \x05%d \x01witches.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01draw-crowned \x05%d \x01witches.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_SKEETS: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01skeeted \x05%d \x01hunters.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01skeeted \x05%d \x01hunters.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_MELEESKEETS: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01skeeted \x05%d \x01hunter%s with a melee weapon.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01skeeted \x05%d \x01hunter%s with a melee weapon.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick], @@ -4138,42 +4141,42 @@ char GetFunFactChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) ); } case FFACT_TYPE_M2: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01shoved \x05%d \x01special infected.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01shoved \x05%d \x01special infected.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_MELEETANK: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01got \x05%d \x01melee swings on the tank.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01got \x05%d \x01melee swings on the tank.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_CUT: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01cut \x05%d \x01tongue cuts.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01cut \x05%d \x01tongue cuts.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_POP: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01popped \x05%d \x01boomers.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01popped \x05%d \x01boomers.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_DEADSTOP: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01deadstopped \x05%d \x01hunters.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01deadstopped \x05%d \x01hunters.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_LEVELS: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01fully leveled \x05%d \x01chargers.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01fully leveled \x05%d \x01chargers.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] @@ -4181,21 +4184,21 @@ char GetFunFactChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) } // infected case FFACT_TYPE_HUNTERDP: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01landed \x05%d \x01highpounces with hunters.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01landed \x05%d \x01highpounces with hunters.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_JOCKEYDP: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01landed \x05%d \x01highpounces with jockeys.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01landed \x05%d \x01highpounces with jockeys.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_DCHARGE: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01death-charged \x05%d \x01 survivor%s.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01death-charged \x05%d \x01 survivor%s.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick], @@ -4203,29 +4206,27 @@ char GetFunFactChatString(bool bRound = true, bool bTeam = true, int iTeam = -1) ); } case FFACT_TYPE_SCRATCH: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01did a total of \x05%d \x01damage by scratching (standing) survivors.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01did a total of \x05%d \x01damage by scratching (standing) survivors.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_BOOMDMG: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01got a total of \x05%d \x01damage by common hits on boomed (standing) survivors.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01got a total of \x05%d \x01damage by common hits on boomed (standing) survivors.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } case FFACT_TYPE_SPITDMG: { - Format(printBuffer, sizeof(printBuffer), "[%s fact] \x04%s \x01did a total of \x05%d \x01spit-damage on (standing) survivors.\n", + Format(printBuffer, iLen, "[%s fact] \x04%s \x01did a total of \x05%d \x01spit-damage on (standing) survivors.\n", (bRound) ? "Round" : "Game", g_sPlayerName[ wTypeHighPly[wPick] ], wTypeHighVal[wPick] ); } } - - return printBuffer; } // display player accuracy stats: details => tank/si/etc @@ -6547,6 +6548,8 @@ public Action Timer_AutomaticRoundEndPrint(Handle hTimer) AutomaticPrintPerClient(g_iCookieValue[client], client); } } + + return Plugin_Stop; } // set iTeam to -2 to force printing for all players (where possible) (-1 = current team) - setting client to -2 prints to file (and never needs a delay) @@ -6865,6 +6868,8 @@ public Action Timer_DelayedPrint(Handle hTimer, Handle pack) // send non-recursive print call ('first' true must be set for no further delays) AutomaticPrintPerClient(flags, client, team, true, true, bSortedRound, bSortedGame); + + return Plugin_Stop; } /* @@ -7076,7 +7081,7 @@ bool IsPlayerIncapacitated(int client) bool IsHangingFromLedge(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge") || GetEntProp(client, Prop_Send, "m_isFallingFromLedge")); + return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge", 1) || GetEntProp(client, Prop_Send, "m_isFallingFromLedge", 1)); } bool IsPlayerIncapacitatedAtAll(int client) @@ -7125,6 +7130,8 @@ int GetUprightSurvivors() public Action Timer_WriteStats(Handle hTimer, any iTeam) { WriteStatsToFile(iTeam, true); + + return Plugin_Stop; } // write round stats to a text file diff --git a/addons/sourcemod/scripting/l4d2_riotcops.sp b/addons/sourcemod/scripting/l4d2_riotcops.sp index 21f164fa4..bd17c22ab 100644 --- a/addons/sourcemod/scripting/l4d2_riotcops.sp +++ b/addons/sourcemod/scripting/l4d2_riotcops.sp @@ -24,7 +24,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define PARISH_PREFIX "c5m" @@ -75,7 +75,7 @@ public Action RiotCopTraceAttack(int iVictim, int &iAttacker, int &iInflictor, f return Plugin_Continue; } - if (!L4D2Util_IsValidClient(iAttacker) || !IsSurvivor(iAttacker)) { + if (!IsValidSurvivor(iAttacker)) { return Plugin_Continue; } diff --git a/addons/sourcemod/scripting/l4d2_saferoom_item_remove.sp b/addons/sourcemod/scripting/l4d2_saferoom_item_remove.sp index a871d6a4a..f8e0e44f8 100644 --- a/addons/sourcemod/scripting/l4d2_saferoom_item_remove.sp +++ b/addons/sourcemod/scripting/l4d2_saferoom_item_remove.sp @@ -15,11 +15,11 @@ enum enum { - eITEM_KILLABLE = 0, - eITEM_KILLABLE_HEALTH = (1 << 0), //1 - eITEM_KILLABLE_WEAPON = (1 << 1), //2 - eITEM_KILLABLE_MELEE = (1 << 2), //4 - eITEM_KILLABLE_OTHER = (1 << 3) //8 + eITEM_KILLABLE = 0, // 0 + eITEM_KILLABLE_HEALTH = (1 << 0), // 1 + eITEM_KILLABLE_WEAPON = (1 << 1), // 2 + eITEM_KILLABLE_MELEE = (1 << 2), // 4 + eITEM_KILLABLE_OTHER = (1 << 3) // 8 }; ConVar @@ -103,6 +103,7 @@ public Action Timer_DelayedOnRoundStart(Handle hTimer) } LogMessage("Removed %i saferoom item(s) (start: %i; end: %i).", iCountStart + iCountEnd, iCountStart, iCountEnd); + return Plugin_Stop; } void PrepareTrie() diff --git a/addons/sourcemod/scripting/l4d2_scoremod.sp b/addons/sourcemod/scripting/l4d2_scoremod.sp index 6e9b8b5bb..09930dbc2 100644 --- a/addons/sourcemod/scripting/l4d2_scoremod.sp +++ b/addons/sourcemod/scripting/l4d2_scoremod.sp @@ -10,8 +10,7 @@ #define DEBUG_SM 0 - -public Plugin:myinfo = +public Plugin myinfo = { name = "L4D2 Scoremod", author = "CanadaRox, ProdigySim", @@ -65,7 +64,9 @@ new iDifference; public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { CreateNative("HealthBonus", _Native_HealthBonus); + RegPluginLibrary("l4d2_scoremod"); + return APLRes_Success; } public int _Native_HealthBonus(Handle plugin, int numParams) diff --git a/addons/sourcemod/scripting/l4d2_setscores.sp b/addons/sourcemod/scripting/l4d2_setscores.sp index b7319a5b8..d0cb87d99 100644 --- a/addons/sourcemod/scripting/l4d2_setscores.sp +++ b/addons/sourcemod/scripting/l4d2_setscores.sp @@ -210,7 +210,7 @@ void SetScores(const int survScore, const int infectScore, const int iAdminIndex } //Handler for the vote -public int VoteActionHandler(Handle vote, BuiltinVoteAction action, int param1, int param2) { +public void VoteActionHandler(Handle vote, BuiltinVoteAction action, int param1, int param2) { switch (action) { case BuiltinVoteAction_End: { voteHandler = null; diff --git a/addons/sourcemod/scripting/l4d2_shadow_removal.sp b/addons/sourcemod/scripting/l4d2_shadow_removal.sp index 6a34b6015..67ad41f8a 100644 --- a/addons/sourcemod/scripting/l4d2_shadow_removal.sp +++ b/addons/sourcemod/scripting/l4d2_shadow_removal.sp @@ -1,22 +1,25 @@ +#pragma semicolon 1 +#pragma newdecls required + #include #include -public Plugin:myinfo = +public Plugin myinfo = { name = "L4D2 Shadow Removal", author = "Sir", description = "A plugin that removes Shadows so that Survivors can't see Infected Players their shadows through walls and the like.", - version = "1.0", - url = "Nope" + version = "1.1", + url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; -public OnMapStart() -{ - CreateEntityByName("shadow_control"); - new ent = -1; - while((ent = FindEntityByClassname(ent, "shadow_control")) != -1) - { - SetVariantInt(1); - AcceptEntityInput(ent, "SetShadowsDisabled"); - } -} \ No newline at end of file +public void OnMapStart() +{ + CreateEntityByName("shadow_control"); + + int iEnt = -1; + while((iEnt = FindEntityByClassname(iEnt, "shadow_control")) != -1) { + SetVariantInt(1); + AcceptEntityInput(iEnt, "SetShadowsDisabled"); + } +} diff --git a/addons/sourcemod/scripting/l4d2_si_ffblock.sp b/addons/sourcemod/scripting/l4d2_si_ffblock.sp index 2573b8deb..0fc87013a 100644 --- a/addons/sourcemod/scripting/l4d2_si_ffblock.sp +++ b/addons/sourcemod/scripting/l4d2_si_ffblock.sp @@ -104,7 +104,7 @@ public Action Hook_WitchOnTakeDamage(int iVictim, int &iAttacker, int &iInflicto sClassName, iVictim, iAttacker, iAttacker, L4D2_InfectedNames[iZClass], iZClass, iInflictor, fDamage, iDamagetype); #endif - return (iZClass == view_as(L4D2Infected_Tank)) ? Plugin_Continue : Plugin_Handled; + return (iZClass == L4D2Infected_Tank) ? Plugin_Continue : Plugin_Handled; } public void OnClientPutInServer(int iClient) @@ -129,7 +129,7 @@ public Action Hook_PlayerOnTakeDamage(int iVictim, int &iAttacker, int &iInflict iVictim, iVictim, iAttacker, iAttacker, L4D2_InfectedNames[iZClass], iZClass, iInflictor, fDamage, iDamagetype); #endif - return (iZClass == view_as(L4D2Infected_Tank) && g_bAllowTankFF) ? Plugin_Continue : Plugin_Handled; + return (iZClass == L4D2Infected_Tank && g_bAllowTankFF) ? Plugin_Continue : Plugin_Handled; } bool IsInfected(int iClient) @@ -137,7 +137,7 @@ bool IsInfected(int iClient) return (iClient > 0 && iClient <= MaxClients && IsClientInGame(iClient) - && GetClientTeam(iClient) == view_as(L4D2Team_Infected)); + && GetClientTeam(iClient) == L4D2Team_Infected); } bool IsWitch(int iEntity) diff --git a/addons/sourcemod/scripting/l4d2_si_staggers.sp b/addons/sourcemod/scripting/l4d2_si_staggers.sp index cccb37684..ce89253e0 100644 --- a/addons/sourcemod/scripting/l4d2_si_staggers.sp +++ b/addons/sourcemod/scripting/l4d2_si_staggers.sp @@ -24,11 +24,13 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define DEBUG 0 +#define ENTITY_NAME_MAX_LENTH 64 + #define BLOCK_BOOMER (1 << 0) #define BLOCK_CHARGER (1 << 1) #define BLOCK_WITCH (1 << 2) @@ -82,7 +84,7 @@ public Action L4D2_OnStagger(int target, int source) return Plugin_Continue; } - if (GetInfectedZClass(source) == view_as(L4D2Infected_Boomer) && !(iActiveFlags & BLOCK_BOOMER)) { // Is the Boomer eligible? + if (GetInfectedZClass(source) == L4D2Infected_Boomer && !(iActiveFlags & BLOCK_BOOMER)) { // Is the Boomer eligible? return Plugin_Continue; } @@ -90,24 +92,24 @@ public Action L4D2_OnStagger(int target, int source) return Plugin_Continue; } - if (GetClientTeam(target) == view_as(L4D2Team_Survivor) && IsSurvivorAttacked(target)) { // Capped Survivors should not get staggered + if (GetClientTeam(target) == L4D2Team_Survivor && IsSurvivorAttacked(target)) { // Capped Survivors should not get staggered return Plugin_Handled; } - if (GetClientTeam(target) != view_as(L4D2Team_Infected)) { // We'll only need SI for the following checks + if (GetClientTeam(target) != L4D2Team_Infected) { // We'll only need SI for the following checks return Plugin_Continue; } - if (source == -1 && GetInfectedZClass(target) != view_as(L4D2Infected_Charger)) { // Allow Charger selfstaggers through + if (source == -1 && GetInfectedZClass(target) != L4D2Infected_Charger) { // Allow Charger selfstaggers through return Plugin_Handled; } - if (source <= MaxClients && GetInfectedZClass(source) == view_as(L4D2Infected_Boomer)) { // Cancel any staggers caused by a Boomer explosion + if (source <= MaxClients && GetInfectedZClass(source) == L4D2Infected_Boomer) { // Cancel any staggers caused by a Boomer explosion return Plugin_Handled; } if ((iActiveFlags & BLOCK_WITCH) && source != -1) { // Return early if we don't have a valid edict. - char classname[64]; + char classname[ENTITY_NAME_MAX_LENTH]; GetEdictClassname(source, classname, sizeof(classname)); if (StrContains(classname, "witch") != -1) { // Cancel any staggers caused by a running Witch or Witch Bride(if eligible) return Plugin_Handled; diff --git a/addons/sourcemod/scripting/l4d2_slowdown_control.sp b/addons/sourcemod/scripting/l4d2_slowdown_control.sp index 52b24e7a2..69b07393e 100644 --- a/addons/sourcemod/scripting/l4d2_slowdown_control.sp +++ b/addons/sourcemod/scripting/l4d2_slowdown_control.sp @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ + #pragma semicolon 1 #pragma newdecls required @@ -142,7 +143,7 @@ void CvarsToType() fJockeyMinMountedSpeed = hCvarJockeyMinMoundedSpeed.FloatValue; } -public Action TankSpawn(Event event, const char[] name, bool dontBroadcast) +public void TankSpawn(Event event, const char[] name, bool dontBroadcast) { if (!tankInPlay) { tankInPlay = true; @@ -152,7 +153,7 @@ public Action TankSpawn(Event event, const char[] name, bool dontBroadcast) } } -public Action TankDeath(Event event, const char[] name, bool dontBroadcast) +public void TankDeath(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(GetEventInt(event, "userid")); if (client > 0 && IsInfected(client) && IsTank(client)) { @@ -169,9 +170,11 @@ public Action Timer_CheckTank(Handle timer) PrintToChatAll("\x05Water Slowdown\x01 has been restored to normal."); } } + + return Plugin_Stop; } -public Action RoundStart(Event event, const char[] name, bool dontBroadcast) +public void RoundStart(Event event, const char[] name, bool dontBroadcast) { tankInPlay = false; HookCrouchTriggers(); @@ -221,7 +224,7 @@ public void CrouchSpeedEndTouch(const char[] output, int caller, int activator, * Slowdown from gunfire: Tank & SI * **/ -public Action PlayerHurt(Event event, const char[] name, bool dontBroadcast) +public void PlayerHurt(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(GetEventInt(event, "userid")); if (client > 0 && IsInfected(client)) { @@ -474,7 +477,7 @@ bool IsTank(int client) float fScaleFloat(float inc, float low, float high) { - /* @A1m: + /* * This macros has been removed because it is considered unsafe. * Besides, there are problems when assembling in sourcemod 1.11. * The compiler ignores the data type when assembling. @@ -488,7 +491,7 @@ float fScaleFloat(float inc, float low, float high) float fScaleFloat2(float inc, float low, float high) { - /* @A1m: + /* * This macros has been removed because it is considered unsafe. * Besides, there are problems when assembling in sourcemod 1.11. * The compiler ignores the data type when assembling. diff --git a/addons/sourcemod/scripting/l4d2_smg_reload_tweak.sp b/addons/sourcemod/scripting/l4d2_smg_reload_tweak.sp index 7e364f8d5..a979ddc1f 100644 --- a/addons/sourcemod/scripting/l4d2_smg_reload_tweak.sp +++ b/addons/sourcemod/scripting/l4d2_smg_reload_tweak.sp @@ -3,7 +3,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define TEAM_SURVIVOR 2 @@ -39,7 +39,7 @@ public void OnWeaponReload(Event hEvent, const char[] eName, bool dontBroadcast) float originalReloadDuration = 0.0, alteredReloadDuration = 0.0; int weapon = GetPlayerWeaponSlot(client, 0); - WeaponId weaponId = IdentifyWeapon(weapon); + int weaponId = IdentifyWeapon(weapon); switch (weaponId) { case WEPID_SMG: { @@ -81,7 +81,7 @@ public Action OnPlayerRunCmd(int client, int &buttons) float originalReloadDuration = 0.0, alteredReloadDuration = 0.0; int weapon = GetPlayerWeaponSlot(client, 0); - WeaponId weaponId = IdentifyWeapon(weapon); + int weaponId = IdentifyWeapon(weapon); switch (weaponId) { case WEPID_SMG: { diff --git a/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval.sp b/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval.sp index 492313298..4dd4e96a6 100644 --- a/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval.sp +++ b/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval.sp @@ -86,38 +86,6 @@ public Action FixDragInterval(Handle hTimer, any userid) return Plugin_Stop; } -/* @A1m`: - * It cannot be found using sourcemod, can only be found in the code: - * - * Function 'CTerrorPlayer::OnGrabbedByTongue' below the middle: - * - * v13 = dword_FDA87C; - * *((_DWORD *)this + 1535) = 0; - * v22 = *(float *)(v13 + 44); - * CountdownTimer::Now((CTerrorPlayer *)((char *)this + 13312)); //we need this line, this is the new offset - * v20 = a1; - * if ( (float)(v20 + v22) != *((float *)this + 3330) ) - * { - * (*(void (__cdecl **)(char *, char *))(*((_DWORD *)this + 3328) + 4))((char *)this + 13312, (char *)this + 13320); - * *((float *)this + 3330) = v20 + v22; - * } - * if ( v22 != *((float *)this + 3329) ) - * { - * (*(void (__cdecl **)(char *, char *))(*((_DWORD *)this + 3328) + 4))((char *)this + 13312, (char *)this + 13316); - * *((float *)this + 3329) = v22; - * } - * CBaseEntity::EmitSound(this, "SmokerZombie.TongueHit", 0.0, 0); - * - * How does it look: - * - * 13352 - 8 (m_timestamp) = 13344 (old offset) - what was previously written here. - * New offset 13312, the plugin will add 8 more and we will get where we need to - * - * CountdownTimer m_tongueDragDamageTimer 13312 - * Member: m_duration (offset 4) (type float) - * Member: m_timestamp (offset 8) (type float) (bits 0) (NoScale) - * -*/ void SetDragDamageInterval(int client) { float fCvarValue = tongue_drag_damage_interval.FloatValue; diff --git a/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval_zone.sp b/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval_zone.sp index f1cb89491..0280101be 100644 --- a/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval_zone.sp +++ b/addons/sourcemod/scripting/l4d2_smoker_drag_damage_interval_zone.sp @@ -123,38 +123,6 @@ public Action FixDragIntervalTimer(Handle hTimer, any userid) return Plugin_Stop; } -/* @A1m`: - * It cannot be found using sourcemod, can only be found in the code: - * - * Function 'CTerrorPlayer::OnGrabbedByTongue' below the middle: - * - * v13 = dword_FDA87C; - * *((_DWORD *)this + 1535) = 0; - * v22 = *(float *)(v13 + 44); - * CountdownTimer::Now((CTerrorPlayer *)((char *)this + 13312)); //we need this line, this is the new offset - * v20 = a1; - * if ( (float)(v20 + v22) != *((float *)this + 3330) ) - * { - * (*(void (__cdecl **)(char *, char *))(*((_DWORD *)this + 3328) + 4))((char *)this + 13312, (char *)this + 13320); - * *((float *)this + 3330) = v20 + v22; - * } - * if ( v22 != *((float *)this + 3329) ) - * { - * (*(void (__cdecl **)(char *, char *))(*((_DWORD *)this + 3328) + 4))((char *)this + 13312, (char *)this + 13316); - * *((float *)this + 3329) = v22; - * } - * CBaseEntity::EmitSound(this, "SmokerZombie.TongueHit", 0.0, 0); - * - * How does it look: - * - * 13352 - 8 (m_timestamp) = 13344 (old offset) - what was previously written here. - * New offset 13312, the plugin will add 8 more and we will get where we need to - * - * CountdownTimer m_tongueDragDamageTimer 13312 - * Member: m_duration (offset 4) (type float) - * Member: m_timestamp (offset 8) (type float) (bits 0) (NoScale) - * -*/ void SetDragDamageInterval(int client, ConVar hConvar) { float fCvarValue = hConvar.FloatValue; diff --git a/addons/sourcemod/scripting/l4d2_sniper_bodyshot.sp b/addons/sourcemod/scripting/l4d2_sniper_bodyshot.sp index fe121702b..035edf37b 100644 --- a/addons/sourcemod/scripting/l4d2_sniper_bodyshot.sp +++ b/addons/sourcemod/scripting/l4d2_sniper_bodyshot.sp @@ -1,142 +1,103 @@ #pragma semicolon 1 +#pragma newdecls required #include #include -#include +#include +#define L4D2UTIL_STOCKS_ONLY 1 +#include -#define HITGROUP_STOMACH 3 +#define DEBUG 0 -new bool:bLateLoad; +public const char g_sSniperWeapon[][ENTITY_MAX_NAME_LENGTH] = +{ + "weapon_sniper_scout", + "weapon_sniper_awp" +}; + +bool g_bLateLoad = false; -public APLRes:AskPluginLoad2( Handle:plugin, bool:late, String:error[], errMax ) +public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int iErrMax) { - bLateLoad = late; + g_bLateLoad = bLate; + return APLRes_Success; } -public Plugin:myinfo = +public Plugin myinfo = { name = "L4D2 Sniper Hunter Bodyshot", - author = "Visor", + author = "Visor, A1m`", description = "Remove sniper weapons' stomach hitgroup damage multiplier against hunters", - version = "1.1", + version = "2.2", url = "https://github.com/Attano/L4D2-Competitive-Framework" }; -public OnPluginStart() +public void OnPluginStart() { - if (bLateLoad) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientConnected(i) && IsClientInGame(i)) - { + if (g_bLateLoad) { + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i)) { OnClientPutInServer(i); } } } } -public OnClientPutInServer(client) +public void OnClientPutInServer(int iClient) { - SDKHook(client, SDKHook_TraceAttack, TraceAttack); + SDKHook(iClient, SDKHook_TraceAttack, TraceAttack); } -public Action:TraceAttack(victim, &attacker, &inflictor, &Float:damage, &damagetype, &ammotype, hitbox, hitgroup) +public Action TraceAttack(int iVictim, int &iAttacker, int &iInflictor, float &fDamage, \ + int &fDamageType, int &iAmmoType, int iHitBox, int iHitGroup) { - if (!IsHunter(victim) || !IsSurvivor(attacker) || IsFakeClient(attacker)) + if (iHitGroup != HITGROUP_STOMACH) { return Plugin_Continue; + } - new weapon = GetClientActiveWeapon(attacker); - if (!IsValidSniper(weapon)) + if (!IsHunter(iVictim) || !IsValidSurvivor(iAttacker) || IsFakeClient(iAttacker)) { return Plugin_Continue; - - // decl String:szHitgroup[32]; - // HitgroupToString(hitgroup, szHitgroup, sizeof(szHitgroup)); - // PrintToChatAll("Victim %N attacker %N hitgroup %s", victim, attacker, szHitgroup); - if (hitgroup == HITGROUP_STOMACH) - { - damage = GetWeaponDamage(weapon) / 1.25; - return Plugin_Changed; } - return Plugin_Continue; -} -// HitgroupToString(hitgroup, String:destination[], maxlength) -// { - // new String:buffer[32]; - // switch (hitgroup) - // { - // case 0: - // { - // buffer = "generic"; - // } - // case 1: - // { - // buffer = "head"; - // } - // case 2: - // { - // buffer = "chest"; - // } - // case 3: - // { - // buffer = "stomach"; - // } - // case 4: - // { - // buffer = "left arm"; - // } - // case 5: - // { - // buffer = "right arm"; - // } - // case 6: - // { - // buffer = "left leg"; - // } - // case 7: - // { - // buffer = "right leg"; - // } - // case 10: - // { - // buffer = "gear"; - // } - // } - // strcopy(destination, maxlength, buffer); -// } - -GetClientActiveWeapon(client) -{ - return GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon"); -} + int iWeapon = GetEntPropEnt(iAttacker, Prop_Send, "m_hActiveWeapon"); + if (iWeapon == -1) { + return Plugin_Continue; + } -GetWeaponDamage(weapon) -{ - decl String:classname[64]; - GetEdictClassname(weapon, classname, sizeof(classname)); - return L4D2_GetIntWeaponAttribute(classname, L4D2IntWeaponAttributes:L4D2IWA_Damage); -} + char sClassName[64]; + GetEdictClassname(iWeapon, sClassName, sizeof(sClassName)); + if (!IsValidSniper(sClassName)) { + return Plugin_Continue; + } -bool:IsValidSniper(weapon) -{ - decl String:classname[64]; - GetEdictClassname(weapon, classname, sizeof(classname)); - return (StrEqual(classname, "weapon_sniper_scout") || StrEqual(classname, "weapon_sniper_awp")); +#if DEBUG + char szHitgroup[32]; + HitgroupToString(iHitGroup, szHitgroup, sizeof(szHitgroup)); + PrintToChatAll("Victim %N, attacker %N, hitgroup %s (%d), weapon: %s, ", iVictim, iAttacker, szHitgroup, iHitGroup, sClassName); +#endif + + fDamage = L4D2_GetIntWeaponAttribute(sClassName, L4D2IWA_Damage) / 1.25; + return Plugin_Changed; } -bool:IsSurvivor(client) +bool IsValidSniper(const char[] sWeaponName) { - return (client > 0 && client <= MaxClients && IsClientInGame(client) && GetClientTeam(client) == 2); + for (int i = 0; i < sizeof(g_sSniperWeapon); i++) { + if (strcmp(sWeaponName, g_sSniperWeapon[i]) == 0) { + return true; + } + } + + return false; } -bool:IsHunter(client) +bool IsHunter(int iClient) { - return (client > 0 - && client <= MaxClients - && IsClientInGame(client) - && GetClientTeam(client) == 3 - && GetEntProp(client, Prop_Send, "m_zombieClass") == 3 - && GetEntProp(client, Prop_Send, "m_isGhost") != 1); -} \ No newline at end of file + return (iClient > 0 + && iClient <= MaxClients + && IsClientInGame(iClient) + && GetClientTeam(iClient) == L4D2Team_Infected + && GetEntProp(iClient, Prop_Send, "m_zombieClass") == L4D2Infected_Hunter + && GetEntProp(iClient, Prop_Send, "m_isGhost") != 1); +} diff --git a/addons/sourcemod/scripting/l4d2_sniper_precache.sp b/addons/sourcemod/scripting/l4d2_sniper_precache.sp index eb089e5ad..5592de036 100644 --- a/addons/sourcemod/scripting/l4d2_sniper_precache.sp +++ b/addons/sourcemod/scripting/l4d2_sniper_precache.sp @@ -1,38 +1,49 @@ #pragma semicolon 1 +#pragma newdecls required; #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include -new const snipers[2] = +static const int snipers[] = { 35, // SNIPER_AWP 36 // SNIPER_SCOUT }; -public Plugin:myinfo = +public Plugin myinfo = { - name = "L4D2 Sniper Precache", - author = "Visor", - version = "2.0", - description = "Unlocks German sniper weapons", - url = "https://github.com/Attano/Equilibrium" + name = "L4D2 Sniper Precache", + author = "Visor, A1m`", + version = "2.2", + description = "Unlocks German sniper weapons", + url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; -public OnMapStart() +public void OnMapStart() { - new WeaponId:wepid; - decl String:buffer[64]; - - for (new i = 0; i < sizeof(snipers); i++) - { - wepid = WeaponId:snipers[i]; - PrecacheModel(WeaponModels[_:wepid]); + char sBuffer[64]; + for (int i = 0; i < sizeof(snipers); i++) { + PrecacheModel(WeaponModels[snipers[i]]); - GetWeaponName(wepid, buffer, sizeof(buffer)); - new index = CreateEntityByName(buffer); - DispatchSpawn(index); - RemoveEdict(index); + GetWeaponName(snipers[i], sBuffer, sizeof(sBuffer)); + SpawnWeaponByName(sBuffer); + } +} + +void SpawnWeaponByName(const char[] sWeaponName) +{ + int iEntity = CreateEntityByName(sWeaponName); + if (iEntity == -1) { + return; } -} \ No newline at end of file + + DispatchSpawn(iEntity); + + #if SOURCEMOD_V_MINOR > 8 + RemoveEntity(iEntity); + #else + AcceptEntityInput(iEntity, "Kill"); + #endif +} diff --git a/addons/sourcemod/scripting/l4d2_spec_stays_spec.sp b/addons/sourcemod/scripting/l4d2_spec_stays_spec.sp index bfbfbc8cd..8aa5e81ac 100644 --- a/addons/sourcemod/scripting/l4d2_spec_stays_spec.sp +++ b/addons/sourcemod/scripting/l4d2_spec_stays_spec.sp @@ -190,7 +190,11 @@ public Action Timer_MoveToSpec(Handle timer, int client) { public Action ReSpec(Handle timer, int client) { - if(IsClientInGame(client) && GetClientTeam(client) == 1) FakeClientCommand(client, "say /spectate"); + if (IsClientInGame(client) && GetClientTeam(client) == 1) { + FakeClientCommand(client, "say /spectate"); + } + + return Plugin_Stop; } /* diff --git a/addons/sourcemod/scripting/l4d2_spitblock.sp b/addons/sourcemod/scripting/l4d2_spitblock.sp index 4f0d32138..10913387f 100644 --- a/addons/sourcemod/scripting/l4d2_spitblock.sp +++ b/addons/sourcemod/scripting/l4d2_spitblock.sp @@ -169,13 +169,13 @@ bool isPointIn2DBox(float x0, float y0, float x1, float y1, float x2, float y2) bool IsInsectSwarm(int iEntity) { - if (iEntity > 0 && IsValidEntity(iEntity)) { - char sClassName[MAX_ENTITY_NAME_SIZE]; - GetEntityClassname(iEntity, sClassName, sizeof(sClassName)); - return (strcmp(sClassName, "insect_swarm") == 0); + if (iEntity <= MaxClients || !IsValidEdict(iEntity)) { + return false; } - return false; + char sClassName[MAX_ENTITY_NAME_SIZE]; + GetEdictClassname(iEntity, sClassName, sizeof(sClassName)); + return (strcmp(sClassName, "insect_swarm") == 0); } bool IsValidClient(int iClient) diff --git a/addons/sourcemod/scripting/l4d2_stats.sp b/addons/sourcemod/scripting/l4d2_stats.sp index a4d3b953d..41bbb0f91 100644 --- a/addons/sourcemod/scripting/l4d2_stats.sp +++ b/addons/sourcemod/scripting/l4d2_stats.sp @@ -76,7 +76,7 @@ public void Event_PlayerSpawn(Event hEvent, const char[] sEventName, bool bDontB } if (GetClientTeam(client) == TEAM_INFECTED) { - L4D2_Infected zombieclass = GetInfectedClass(client); + int zombieclass = GetInfectedClass(client); if (zombieclass == L4D2Infected_Tank) { return; } @@ -164,7 +164,7 @@ public void Event_AbilityUse(Event hEvent, const char[] sEventName, bool bDontBr return; } - L4D2_Infected zombieclass = GetInfectedClass(client); + int zombieclass = GetInfectedClass(client); if (zombieclass == L4D2Infected_Hunter) { g_bIsPouncing[client] = true; @@ -175,7 +175,7 @@ public void Event_AbilityUse(Event hEvent, const char[] sEventName, bool bDontBr public void Event_LungePounce(Event hEvent, const char[] sEventName, bool bDontBroadcast) { int attacker = GetClientOfUserId(hEvent.GetInt("userid")); - L4D2_Infected zombieclass = GetInfectedClass(attacker); + int zombieclass = GetInfectedClass(attacker); if (zombieclass == L4D2Infected_Hunter) { g_bIsPouncing[attacker] = false; @@ -196,6 +196,7 @@ public Action Timer_GroundedCheck(Handle hTimer, any userid) public Action Timer_KillBoomer(Handle hTimer) { BoomerKillTime += 0.1; + return Plugin_Continue; } public void Event_PlayerHurt(Event hEvent, const char[] sEventName, bool bDontBroadcast) @@ -215,7 +216,7 @@ public void Event_PlayerHurt(Event hEvent, const char[] sEventName, bool bDontBr } if (GetClientTeam(attacker) == TEAM_SURVIVOR && GetClientTeam(victim) == TEAM_INFECTED) { - L4D2_Infected zombieclass = GetInfectedClass(victim); + int zombieclass = GetInfectedClass(victim); if (zombieclass == L4D2Infected_Tank) { return; // We don't care about tank damage } @@ -283,7 +284,7 @@ public void Event_PlayerDeath(Event hEvent, const char[] sEventName, bool bDontB } if (GetClientTeam(attacker) == TEAM_SURVIVOR && GetClientTeam(victim) == TEAM_INFECTED) { - L4D2_Infected zombieclass = GetInfectedClass(victim); + int zombieclass = GetInfectedClass(victim); if (zombieclass == L4D2Infected_Tank) { return; // We don't care about tank damage } @@ -511,7 +512,7 @@ public void Event_PlayerShoved(Event hEvent, const char[] sEventName, bool bDont return; } - L4D2_Infected zombieclass = GetInfectedClass(victim); + int zombieclass = GetInfectedClass(victim); if (zombieclass == L4D2Infected_Boomer) { if (g_hBoomerShoveTimer != null) { DestroyTimer(g_hBoomerShoveTimer); @@ -532,6 +533,8 @@ public Action Timer_BoomerShove(Handle hTimer) // PrintToChatAll("[DEBUG] BoomerShove timer expired, credit for boomer shutdown is available to anyone at this point!"); g_hBoomerShoveTimer = null; g_iBoomerShover = 0; + + return Plugin_Stop; } public void Event_PlayerBoomed(Event hEvent, const char[] sEventName, bool bDontBroadcast) diff --git a/addons/sourcemod/scripting/l4d2_tank_announce.sp b/addons/sourcemod/scripting/l4d2_tank_announce.sp index d0361df7b..a7ecf0460 100644 --- a/addons/sourcemod/scripting/l4d2_tank_announce.sp +++ b/addons/sourcemod/scripting/l4d2_tank_announce.sp @@ -5,7 +5,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #undef REQUIRE_PLUGIN #include diff --git a/addons/sourcemod/scripting/l4d2_tank_attack_control.sp b/addons/sourcemod/scripting/l4d2_tank_attack_control.sp index f8784f42f..ddbe32eed 100644 --- a/addons/sourcemod/scripting/l4d2_tank_attack_control.sp +++ b/addons/sourcemod/scripting/l4d2_tank_attack_control.sp @@ -1,3 +1,5 @@ +#pragma semicolon 1 + #include #include #include @@ -39,14 +41,13 @@ public OnPluginStart() g_hBlockJumpRock = CreateConVar("l4d2_block_jump_rock", "0", "Block tanks from jumping and throwing a rock at the same time"); hOverhandOnly = CreateConVar("tank_overhand_only", "0", "Force tank to only throw overhand rocks."); - HookEvent("round_start", EventHook:RoundStartEvent, EventHookMode_PostNoCopy); + HookEvent("round_start", RoundStartEvent, EventHookMode_PostNoCopy); HookEvent("tank_spawn", TankSpawn_Event); } -public RoundStartEvent() +public void RoundStartEvent(Event hEvent, const char[] sEventName, bool bDontBroadcast) { - for (new i = 1; i <= MaxClients; i++) - { + for (int i = 1; i <= MaxClients; i++) { throwQueuedAt[i] = 0.0; } } @@ -56,18 +57,20 @@ public TankSpawn_Event(Handle:event, const String:name[], bool:dontBroadcast) new tank = GetClientOfUserId(GetEventInt(event, "userid")); if (IsFakeClient(tank)) return; - new bool:hidemessage = false; - decl String:buffer[3]; + bool hidemessage = false; + + char buffer[3]; if (GetClientInfo(tank, "rs_hidemessage", buffer, sizeof(buffer))) { hidemessage = bool:StringToInt(buffer); } + if (!hidemessage && (GetConVarBool(hOverhandOnly) == false)) { - CPrintToChat(tank, "{blue}[{default}Tank Rock Selector{blue}]"); - CPrintToChat(tank, "{olive}Reload {default}= {blue}2 Handed Overhand"); - CPrintToChat(tank, "{olive}Use {default}= {blue}Underhand"); - CPrintToChat(tank, "{olive}M2 {default}= {blue}1 Handed Overhand"); + CPrintToChat(tank, "{blue}[{default}Tank Rock Selector{blue}]"); + CPrintToChat(tank, "{olive}Reload {default}= {blue}2 Handed Overhand"); + CPrintToChat(tank, "{olive}Use {default}= {blue}Underhand"); + CPrintToChat(tank, "{olive}M2 {default}= {blue}1 Handed Overhand"); } } @@ -145,4 +148,4 @@ bool:ShouldCancelJump(client) return false; } return (1.5 > GetGameTime() - throwQueuedAt[client]); -} \ No newline at end of file +} diff --git a/addons/sourcemod/scripting/l4d2_tank_attack_control_nextmod.sp b/addons/sourcemod/scripting/l4d2_tank_attack_control_nextmod.sp index f31ce0e0d..78b45b0fa 100644 --- a/addons/sourcemod/scripting/l4d2_tank_attack_control_nextmod.sp +++ b/addons/sourcemod/scripting/l4d2_tank_attack_control_nextmod.sp @@ -220,11 +220,12 @@ public Action ResetJumpRockCooldown(Handle hTimer, any userid) int client = GetClientOfUserId(userid); if (client == 0) { - return; + return Plugin_Stop; } JumpRockReady = true; CPrintToChat(client, "<{red}JumpRock{default}> Jump Rock Is {olive}Ready!"); + return Plugin_Stop; } public Action Timer_Countdown(Handle hTimer) diff --git a/addons/sourcemod/scripting/l4d2_tank_damage_cvars.sp b/addons/sourcemod/scripting/l4d2_tank_damage_cvars.sp index e0ccc554b..9a9e43a42 100644 --- a/addons/sourcemod/scripting/l4d2_tank_damage_cvars.sp +++ b/addons/sourcemod/scripting/l4d2_tank_damage_cvars.sp @@ -1,95 +1,94 @@ #pragma semicolon 1 +#pragma newdecls required #include #include +#define L4D2UTIL_STOCKS_ONLY 1 +#include -new Handle:vs_tank_pound_damage; -new Handle:vs_tank_rock_damage; +#define DEBUG 0 -new bool:lateLoad; +ConVar + g_hCvarVsTankPoundDamage = null, + g_hCvarVsTankRockDamage = null; -public APLRes:AskPluginLoad2(Handle:plugin, bool:late, String:error[], errMax) +bool + g_bLateLoad = false; + +public APLRes AskPluginLoad2(Handle hMyself, bool bLate, char[] sError, int iErrMax) { - lateLoad = late; - return APLRes_Success; + g_bLateLoad = bLate; + return APLRes_Success; } -public Plugin:myinfo = +public Plugin myinfo = { name = "L4D2 Tank Damage Cvars", - author = "Visor", + author = "Visor, A1m`", description = "Toggle Tank attack damage per type", - version = "1.1", - url = "https://github.com/Attano/Equilibrium" + version = "2.1", + url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; -public OnPluginStart() +public void OnPluginStart() { - vs_tank_pound_damage = CreateConVar("vs_tank_pound_damage", "24", "Amount of damage done by a vs tank's melee attack on incapped survivors"); - vs_tank_rock_damage = CreateConVar("vs_tank_rock_damage", "24", "Amount of damage done by a vs tank's rock"); - - if (lateLoad) - { - for (new i = 1; i <= MaxClients; i++) - { - if (IsClientInGame(i)) - { + g_hCvarVsTankPoundDamage = CreateConVar("vs_tank_pound_damage", "24.0", "Amount of damage done by a vs tank's melee attack on incapped survivors (a zero and negative value disables this)."); + g_hCvarVsTankRockDamage = CreateConVar("vs_tank_rock_damage", "24.0", "Amount of damage done by a vs tank's rock (a zero and negative value disables this)."); + + if (g_bLateLoad) { + for (int i = 1; i <= MaxClients; i++) { + if (IsClientInGame(i)) { OnClientPutInServer(i); } } } } -public OnClientPutInServer(client) +public void OnClientPutInServer(int iClient) { - SDKHook(client, SDKHook_OnTakeDamage, OnTakeDamage); + SDKHook(iClient, SDKHook_OnTakeDamage, Hook_OnTakeDamage); } -public OnClientDisconnect(client) +public void OnClientDisconnect(int iClient) { - SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage); + SDKUnhook(iClient, SDKHook_OnTakeDamage, Hook_OnTakeDamage); } -public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damageType, &weapon, Float:damageForce[3], Float:damagePosition[3]) +public Action Hook_OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, float &fDamage, int &iDamagetype) { - if (!IsSurvivor(victim) || !IsTank(attacker)) - { + if (iDamagetype != DMG_CLUB) { return Plugin_Continue; } - - if (IsIncapped(victim) && IsTank(inflictor)) - { - damage = GetConVarFloat(vs_tank_pound_damage); + + if (!IsValidSurvivor(iVictim) || !IsValidTank(iAttacker)) { + return Plugin_Continue; } - else if (IsTankRock(inflictor)) - { - damage = GetConVarFloat(vs_tank_rock_damage); + + if (iInflictor <= MaxClients || !IsValidEdict(iInflictor)) { + return Plugin_Continue; } - return Plugin_Changed; -} -bool:IsIncapped(client) -{ - return bool:GetEntProp(client, Prop_Send, "m_isIncapacitated"); -} + char sClassName[ENTITY_MAX_NAME_LENGTH]; + GetEdictClassname(iInflictor, sClassName, sizeof(sClassName)); -bool:IsSurvivor(client) -{ - return (client > 0 && client <= MaxClients && IsClientInGame(client) && GetClientTeam(client) == 2); -} +#if DEBUG + PrintToChatAll("iVictim: %N, iAttacker: %N, iInflictor, %s (%d), fDamage: %f, iDamagetype: %d", \ + iVictim, iAttacker, sClassName, iInflictor, fDamage, iDamagetype); +#endif -bool:IsTank(client) -{ - return (client > 0 && client <= MaxClients && IsClientInGame(client) && GetClientTeam(client) == 3 && GetEntProp(client, Prop_Send, "m_zombieClass") == 8 && IsPlayerAlive(client)); -} + if (strcmp("weapon_tank_claw", sClassName) == 0) { + if (IsIncapacitated(iVictim) && g_hCvarVsTankPoundDamage.FloatValue > 0) { + fDamage = g_hCvarVsTankPoundDamage.FloatValue; -bool:IsTankRock(entity) -{ - if (entity > 0 && IsValidEntity(entity) && IsValidEdict(entity)) - { - decl String:classname[64]; - GetEdictClassname(entity, classname, sizeof(classname)); - return StrEqual(classname, "tank_rock"); - } - return false; -} \ No newline at end of file + return Plugin_Changed; + } + } else if (strcmp("tank_rock", sClassName) == 0) { + if (g_hCvarVsTankRockDamage.FloatValue > 0) { + fDamage = g_hCvarVsTankRockDamage.FloatValue; + } + + return Plugin_Changed; + } + + return Plugin_Continue; +} diff --git a/addons/sourcemod/scripting/l4d2_tank_props_glow.sp b/addons/sourcemod/scripting/l4d2_tank_props_glow.sp index 7ed56cf15..b52cbf904 100644 --- a/addons/sourcemod/scripting/l4d2_tank_props_glow.sp +++ b/addons/sourcemod/scripting/l4d2_tank_props_glow.sp @@ -281,7 +281,7 @@ public void PD_ev_EntityKilled(Event hEvent, const char[] sEventName, bool bDont } } -public Action TankPropTankKilled(Event hEvent, const char[] sEventName, bool bDontBroadcast) +public void TankPropTankKilled(Event hEvent, const char[] sEventName, bool bDontBroadcast) { if (!g_bTankSpawned) { return; @@ -299,11 +299,15 @@ public Action TankDeadCheck(Handle hTimer) g_bTankSpawned = false; } + + return Plugin_Stop; } public Action TankPropsBeGone(Handle hTimer) { UnhookTankProps(); + + return Plugin_Stop; } public void PropDamaged(int iVictim, int iAttacker, int iInflictor, float fDamage, int iDamageType) diff --git a/addons/sourcemod/scripting/l4d2_tongue_timer.sp b/addons/sourcemod/scripting/l4d2_tongue_timer.sp index 314dc1831..04c295af0 100644 --- a/addons/sourcemod/scripting/l4d2_tongue_timer.sp +++ b/addons/sourcemod/scripting/l4d2_tongue_timer.sp @@ -19,6 +19,8 @@ float fTongueDelaySurvivor; public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { bLateLoad = late; + + return APLRes_Success; } public Plugin myinfo = @@ -100,43 +102,38 @@ public Action OnTakeDamage(int victim, int &attacker, int &inflictor, float &dam // EVENTS // // ---------------------------------------------- - -public Action Event_TongueGrab(Event event, const char[] name, bool dontBroadcast) -{ +public void Event_TongueGrab(Event event, const char[] name, bool dontBroadcast) +{ int victim = GetClientOfUserId(event.GetInt("victim")); - if (IsValidClient(victim) - && GetClientTeam(victim) == 2) + if (IsValidClient(victim) && GetClientTeam(victim) == 2) { bPlayerPulled[victim] = true; } } -public Action Event_TonguePullStopped(Event event, const char[] name, bool dontBroadcast) +public void Event_TonguePullStopped(Event event, const char[] name, bool dontBroadcast) { int victim = GetClientOfUserId(event.GetInt("victim")); int smoker = GetClientOfUserId(event.GetInt("smoker")); - if (IsValidClient(victim) - && IsValidAliveSmoker(smoker) - && GetClientTeam(victim) == 2) + if (IsValidClient(victim) && IsValidAliveSmoker(smoker) && GetClientTeam(victim) == 2) { RequestFrame(OnSmokerSurvivorClear, smoker); } } -public Action Event_TongueRelease(Event event, const char[] name, bool dontBroadcast) +public void Event_TongueRelease(Event event, const char[] name, bool dontBroadcast) { int victim = GetClientOfUserId(event.GetInt("victim")) - if (IsValidClient(victim) - && bPlayerPulled[victim]) + if (IsValidClient(victim) && bPlayerPulled[victim]) { RequestFrame(OnNextFrame, victim); } } -public Action Event_Replace(Event event, const char[] name, bool dontBroadcast) +public void Event_Replace(Event event, const char[] name, bool dontBroadcast) { int bot = GetClientOfUserId(event.GetInt("bot")); int player = GetClientOfUserId(event.GetInt("player")); @@ -166,8 +163,7 @@ public Action Event_Replace(Event event, const char[] name, bool dontBroadcast) // ---------------------------------------------- void OnNextFrame(any victim) { - if (IsValidClient(victim) - && bPlayerPulled[victim]) + if (IsValidClient(victim) && bPlayerPulled[victim]) { bPlayerPulled[victim] = false; } @@ -188,7 +184,6 @@ public void OnSmokerSurvivorClear(any smoker) // If the smoker's pull delay is already longer than what we want it to be, don't bother. duration = time + fTongueDelaySurvivor; - if (duration > timestamp) { SetInfectedAbilityTimer(smoker, duration, fTongueDelaySurvivor); @@ -212,21 +207,27 @@ public void ConvarChanged(ConVar convar, const char[] oldValue, const char[] new // STOCKS // // ---------------------------------------------- -bool IsValidClient(int client) +bool IsValidClient(int client) { - if (client <= 0 - || client > MaxClients - || !IsClientInGame(client) - || !IsPlayerAlive(client)) return false; + if (client <= 0 + || client > MaxClients + || !IsClientInGame(client) + || !IsPlayerAlive(client) + ) { + return false; + } return true; -} +} -bool IsValidAliveSmoker(int client) -{ +bool IsValidAliveSmoker(int client) +{ if (!IsValidClient(client) - || GetClientTeam(client) != 3) return false; + || GetClientTeam(client) != 3 + ) { + return false; + } return GetEntProp(client, Prop_Send, "m_zombieClass") == 1; -} +} int FindSmoker() { @@ -238,4 +239,4 @@ int FindSmoker() } } return 0; -} \ No newline at end of file +} diff --git a/addons/sourcemod/scripting/l4d2_ultra_witch.sp b/addons/sourcemod/scripting/l4d2_ultra_witch.sp index d2745d5c1..6657d2fe9 100644 --- a/addons/sourcemod/scripting/l4d2_ultra_witch.sp +++ b/addons/sourcemod/scripting/l4d2_ultra_witch.sp @@ -119,7 +119,7 @@ public Action OnTakeDamage(int iVictim, int &iAttacker, int &iInflictor, float & fThrowForce[2] = 300.0; ApplyAbsVelocityImpulse(iVictim, fThrowForce); - L4D2Direct_DoAnimationEvent(iVictim, view_as(ANIM_TANK_PUNCH_GETUP)); + L4D2Direct_DoAnimationEvent(iVictim, ANIM_TANK_PUNCH_GETUP); fDamage = fWitchDamage; diff --git a/addons/sourcemod/scripting/l4d2_uncommon_blocker.sp b/addons/sourcemod/scripting/l4d2_uncommon_blocker.sp index a5cb6de62..9c4d092fa 100644 --- a/addons/sourcemod/scripting/l4d2_uncommon_blocker.sp +++ b/addons/sourcemod/scripting/l4d2_uncommon_blocker.sp @@ -102,12 +102,7 @@ public Plugin myinfo = public void OnPluginStart() { - g_hPluginEnabled = CreateConVar( \ - "sm_uncinfblock_enabled", \ - "1", \ - "Enable uncommon blocker plugin?", \ - _, true, 0.0, true, 1.0 \ - ); + g_hPluginEnabled = CreateConVar("sm_uncinfblock_enabled", "1", "Enable uncommon blocker plugin?", _, true, 0.0, true, 1.0 ); // 1 + 2 + 4 + 8 + 16 + 32 + 64 = 127 - Block all // 55 - All except fallen survivor and Jimmy Gibbs @@ -152,7 +147,7 @@ public void OnNextFrame(int iEntity) return; } - int iUncommonInfected = view_as(GetGender(iEntity) - L4D2Gender_Ceda); + int iUncommonInfected = GetGender(iEntity) - L4D2Gender_Ceda; bool bIsUncommonInfected = (iUncommonInfected >= 0 && iUncommonInfected < UNCOMMON_INFECTED_AMOUNT); if (!bIsUncommonInfected) { diff --git a/addons/sourcemod/scripting/l4d2_unsilent_jockey.sp b/addons/sourcemod/scripting/l4d2_unsilent_jockey.sp index f387c9b16..5c646cf4d 100644 --- a/addons/sourcemod/scripting/l4d2_unsilent_jockey.sp +++ b/addons/sourcemod/scripting/l4d2_unsilent_jockey.sp @@ -121,7 +121,7 @@ public void L4D_OnEnterGhostState(int client) ChangeJockeyTimerStatus(client, false); } -public Action PlayerSpawn_Event(Event event, const char[] name, bool dontBroadcast) +public void PlayerSpawn_Event(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); @@ -142,7 +142,7 @@ public Action PlayerSpawn_Event(Event event, const char[] name, bool dontBroadca ChangeJockeyTimerStatus(client, true); } -public Action PlayerDeath_Event(Event event, const char[] name, bool dontBroadcast) +public void PlayerDeath_Event(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); @@ -154,7 +154,7 @@ public Action PlayerDeath_Event(Event event, const char[] name, bool dontBroadca ChangeJockeyTimerStatus(client, false); } -public Action PlayerTeam_Event(Event event, const char[] name, bool dontBroadcast) +public void PlayerTeam_Event(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); @@ -166,7 +166,7 @@ public Action PlayerTeam_Event(Event event, const char[] name, bool dontBroadcas ChangeJockeyTimerStatus(client, false); } -public Action JockeyRideStart_Event(Event event, const char[] name, bool dontBroadcast) +public void JockeyRideStart_Event(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); @@ -174,7 +174,7 @@ public Action JockeyRideStart_Event(Event event, const char[] name, bool dontBro ChangeJockeyTimerStatus(client, false); } -public Action JockeyRideEnd_Event(Event event, const char[] name, bool dontBroadcast) +public void JockeyRideEnd_Event(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); @@ -200,8 +200,10 @@ public void JockeyRideEnd_NextFrame(any userid) public Action delayedJockeySound(Handle timer, any client) { - int rndPick = GetRandomInt(0, MAX_JOCKEYSOUND); - EmitSoundToAll(sJockeySound[rndPick], client, SNDCHAN_VOICE); + int rndPick = GetRandomInt(0, MAX_JOCKEYSOUND); + EmitSoundToAll(sJockeySound[rndPick], client, SNDCHAN_VOICE); + + return Plugin_Stop; } /* -------------------------------------- diff --git a/addons/sourcemod/scripting/l4d2_user_commands.sp b/addons/sourcemod/scripting/l4d2_user_commands.sp index a8a70b0d3..a8d44be33 100644 --- a/addons/sourcemod/scripting/l4d2_user_commands.sp +++ b/addons/sourcemod/scripting/l4d2_user_commands.sp @@ -99,7 +99,7 @@ public void OnPluginStart() for (int i = 1; i <= MaxClients; i++) { - if (IsClientInGame(i)) + if ( IsClientConnected(i) ) { OnClientPutInServer(i); } diff --git a/addons/sourcemod/scripting/l4d2_weaponrules.sp b/addons/sourcemod/scripting/l4d2_weaponrules.sp index 0c051ad38..0302f7d67 100644 --- a/addons/sourcemod/scripting/l4d2_weaponrules.sp +++ b/addons/sourcemod/scripting/l4d2_weaponrules.sp @@ -25,13 +25,13 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define DEBUG 0 int - g_GlobalWeaponRules[view_as(WEPID_SIZE)] = {-1, ...}, + g_GlobalWeaponRules[WEPID_SIZE] = {-1, ...}, // state tracking for roundstart looping g_bRoundStartHit, g_bConfigsExecuted; @@ -64,7 +64,7 @@ public Action ResetWeaponRulesCb(int args) void ResetWeaponRules() { - for (int i = 0; i < view_as(WEPID_SIZE); i++) { + for (int i = 0; i < WEPID_SIZE; i++) { g_GlobalWeaponRules[i] = -1; } } @@ -96,6 +96,8 @@ public Action RoundStartDelay(Handle hTimer) if (g_bConfigsExecuted) { WeaponSearchLoop(); } + + return Plugin_Stop; } public Action AddWeaponRuleCb(int args) @@ -108,20 +110,20 @@ public Action AddWeaponRuleCb(int args) char weaponbuf[64]; GetCmdArg(1, weaponbuf, sizeof(weaponbuf)); - WeaponId match = WeaponNameToId2(weaponbuf); + int match = WeaponNameToId2(weaponbuf); GetCmdArg(2, weaponbuf, sizeof(weaponbuf)); - WeaponId to = WeaponNameToId2(weaponbuf); + int to = WeaponNameToId2(weaponbuf); - AddWeaponRule(match, view_as(to)); + AddWeaponRule(match, to); return Plugin_Handled; } -void AddWeaponRule(WeaponId match, int to) +void AddWeaponRule(int match, int to) { - if (IsValidWeaponId(match) && (to == -1 || IsValidWeaponId(view_as(to)))) { + if (IsValidWeaponId(match) && (to == -1 || IsValidWeaponId(to))) { g_GlobalWeaponRules[match] = to; #if DEBUG PrintToServer("Added weapon rule: %d to %d", match, to); @@ -133,9 +135,9 @@ void WeaponSearchLoop() { int entcnt = GetEntityCount(); for (int ent = 1; ent <= entcnt; ent++) { - WeaponId source = IdentifyWeapon(ent); + int source = IdentifyWeapon(ent); if (source > WEPID_NONE && g_GlobalWeaponRules[source] != -1) { - if (g_GlobalWeaponRules[source] == view_as(WEPID_NONE)) { + if (g_GlobalWeaponRules[source] == WEPID_NONE) { AcceptEntityInput(ent, "kill"); #if DEBUG PrintToServer("Found Weapon %d, killing", source); @@ -144,7 +146,7 @@ void WeaponSearchLoop() #if DEBUG PrintToServer("Found Weapon %d, converting to %d", source, g_GlobalWeaponRules[source]); #endif - ConvertWeaponSpawn(ent, view_as(g_GlobalWeaponRules[source])); + ConvertWeaponSpawn(ent, g_GlobalWeaponRules[source]); } } } @@ -152,10 +154,10 @@ void WeaponSearchLoop() // Tries the given weapon name directly, and upon failure, // tries prepending "weapon_" to the given name -WeaponId WeaponNameToId2(const char[] name) +int WeaponNameToId2(const char[] name) { - static char namebuf[64] = "weapon_"; - WeaponId wepid = WeaponNameToId(name); + char namebuf[64] = "weapon_"; + int wepid = WeaponNameToId(name); if (wepid == WEPID_NONE) { strcopy(namebuf[7], sizeof(namebuf) - 7, name); diff --git a/addons/sourcemod/scripting/l4d2lib/mapinfo.sp b/addons/sourcemod/scripting/l4d2lib/mapinfo.sp index 2e2a544af..d1dbe27c8 100644 --- a/addons/sourcemod/scripting/l4d2lib/mapinfo.sp +++ b/addons/sourcemod/scripting/l4d2lib/mapinfo.sp @@ -358,6 +358,8 @@ public int _native_GetMapStartOrigin(Handle hPlugin, int iNumParams) } SetNativeArray(1, fOrigin, sizeof(fOrigin)); + + return 1; } public int _native_GetMapEndOrigin(Handle hPlugin, int iNumParams) @@ -370,6 +372,8 @@ public int _native_GetMapEndOrigin(Handle hPlugin, int iNumParams) } SetNativeArray(1, fOrigin, sizeof(fOrigin)); + + return 1; } public int _native_GetMapStartDist(Handle hPlugin, int iNumParams) diff --git a/addons/sourcemod/scripting/l4d2lib/tanks.sp b/addons/sourcemod/scripting/l4d2lib/tanks.sp index 7a091ba03..463e08eca 100644 --- a/addons/sourcemod/scripting/l4d2lib/tanks.sp +++ b/addons/sourcemod/scripting/l4d2lib/tanks.sp @@ -98,6 +98,8 @@ public Action TankDeath_Timer(Handle hTimer) Call_Finish(); ResetStatus(); + + return Plugin_Stop; } static void ResetStatus() diff --git a/addons/sourcemod/scripting/l4d_boss_percent.sp b/addons/sourcemod/scripting/l4d_boss_percent.sp index 6500a1215..9bcabce96 100644 --- a/addons/sourcemod/scripting/l4d_boss_percent.sp +++ b/addons/sourcemod/scripting/l4d_boss_percent.sp @@ -47,6 +47,7 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("GetReadyUpFooterIndex", Native_GetReadyUpFooterIndex); // Used for other plugins to get the ready footer index of the boss percents CreateNative("RefreshBossPercentReadyUp", Native_RefreshReadyUp); // Used for other plugins to refresh the boss percents on the ready up CreateNative("IsDarkCarniRemix", Native_IsDarkCarniRemix); // Used for other plugins to check if the current map is Dark Carnival: Remix (It tends to break things when it comes to bosses) + RegPluginLibrary("l4d_boss_percent"); return APLRes_Success; } @@ -136,6 +137,8 @@ void GetCvars() public int Native_UpdateBossPercents(Handle plugin, int numParams){ CreateTimer(0.1, GetBossPercents); UpdateReadyUpFooter(0.2); + + return 1; } // Used for other plugins to check if the current map is Dark Carnival: Remix (It tends to break things when it comes to bosses) @@ -148,6 +151,8 @@ public int Native_IsDarkCarniRemix(Handle plugin, int numParams){ public int Native_SetWitchDisabled(Handle plugin, int numParams){ g_bWitchDisabled = view_as(GetNativeCell(1)); UpdateReadyUpFooter(); + + return 1; } // Other plugins can use this to set the tank as "disabled" on the ready up, and when the !boss command is used @@ -155,6 +160,8 @@ public int Native_SetWitchDisabled(Handle plugin, int numParams){ public int Native_SetTankDisabled(Handle plugin, int numParams){ g_bTankDisabled = view_as(GetNativeCell(1)); UpdateReadyUpFooter(); + + return 1; } // Used for other plugins to get the stored witch percent @@ -555,6 +562,7 @@ public Action GetBossPercents(Handle timer) // Finally build up our string for effiency, yea. ProcessBossString(); + return Plugin_Stop; } /* @@ -666,6 +674,8 @@ public Action Timer_UpdateReadyUpFooter(Handle timer) g_bReadyUpFooterAdded = true; } } + + return Plugin_Stop; } /* ======================================================== @@ -686,6 +696,8 @@ public Action BossCmd(int client, int args) PrintBossPercents(client); RequestFrame(PrintCurrent, GetClientUserId(client)); } + + return Plugin_Handled; } public void PrintCurrent(int userid) { diff --git a/addons/sourcemod/scripting/l4d_boss_vote.sp b/addons/sourcemod/scripting/l4d_boss_vote.sp index 00a1a7e0a..192b71d68 100644 --- a/addons/sourcemod/scripting/l4d_boss_vote.sp +++ b/addons/sourcemod/scripting/l4d_boss_vote.sp @@ -22,12 +22,12 @@ public Plugin myinfo = url = "https://github.com/spoon-l4d2" }; -GlobalForward +Handle g_forwardUpdateBosses; ConVar g_hCvarBossVoting; - + bool bv_bTank, bv_bWitch; @@ -38,7 +38,7 @@ int public void OnPluginStart() { - g_forwardUpdateBosses = new GlobalForward("OnUpdateBosses", ET_Ignore, Param_Cell, Param_Cell); + g_forwardUpdateBosses = CreateGlobalForward("OnUpdateBosses", ET_Ignore, Param_Cell, Param_Cell); g_hCvarBossVoting = CreateConVar("l4d_boss_vote", "1", "Enable boss voting", FCVAR_NOTIFY, true, 0.0, true, 1.0); // Sets if boss voting is enabled or disabled @@ -81,13 +81,19 @@ bool RunVoteChecks(int client) public Action VoteBossCmd(int client, int args) { - if (!GetConVarBool(g_hCvarBossVoting)) return; - if (!RunVoteChecks(client)) return; + if (!GetConVarBool(g_hCvarBossVoting)) { + return Plugin_Handled; + } + + if (!RunVoteChecks(client)) { + return Plugin_Handled; + } + if (args != 2) { CReplyToCommand(client, "{blue}<{green}BossVote{blue}>{default} Usage: !voteboss {olive}<{default}tank{olive}> <{default}witch{olive}>{default}."); CReplyToCommand(client, "{blue}<{green}BossVote{blue}>{default} Use {default}\"{blue}0{default}\" for {olive}No Spawn{default}, \"{blue}-1{default}\" for {olive}Ignorance."); - return; + return Plugin_Handled; } // Get all non-spectating players @@ -115,7 +121,7 @@ public Action VoteBossCmd(int client, int args) if (!IsInteger(bv_sTank) || !IsInteger(bv_sWitch)) { CReplyToCommand(client, "{blue}<{green}BossVote{blue}>{default} Percentages are {olive}invalid{default}."); - return; + return Plugin_Handled; } // Check to make sure static bosses don't get changed @@ -197,7 +203,7 @@ public Action VoteBossCmd(int client, int args) } else // Probably not. { - return; + return Plugin_Handled; } } @@ -208,6 +214,8 @@ public Action VoteBossCmd(int client, int args) SetBuiltinVoteResultCallback(bv_hVote, BossVoteResultHandler); DisplayBuiltinVote(bv_hVote, iPlayers, iNumPlayers, 20); FakeClientCommand(client, "Vote Yes"); + + return Plugin_Handled; } public void BossVoteActionHandler(Handle vote, BuiltinVoteAction action, int param1, int param2) @@ -317,23 +325,26 @@ bool IsInteger(const char[] buffer) public Action ForceTankCommand(int client, int args) { - if (!GetConVarBool(g_hCvarBossVoting)) return; + if (!GetConVarBool(g_hCvarBossVoting)) { + return Plugin_Handled; + } + if (IsDarkCarniRemix()) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Command not available on this map."); - return; + return Plugin_Handled; } if (IsStaticTankMap()) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Tank spawn is static and can not be changed on this map."); - return; + return Plugin_Handled; } if (!IsInReady()) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Command can only be used during ready up."); - return; + return Plugin_Handled; } // Get Requested Tank Percent @@ -342,7 +353,7 @@ public Action ForceTankCommand(int client, int args) // Make sure the cmd argument is a number if (!IsInteger(bv_sTank)) - return; + return Plugin_Handled; // Convert it to in int boy int p_iRequestedPercent = StringToInt(bv_sTank); @@ -350,14 +361,14 @@ public Action ForceTankCommand(int client, int args) if (p_iRequestedPercent < 0) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Percentage is {blue}invalid{default}."); - return; + return Plugin_Handled; } // Check if percent is within limits if (!IsTankPercentValid(p_iRequestedPercent)) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Percentage is {blue}banned{default}."); - return; + return Plugin_Handled; } // Set the boss @@ -376,27 +387,32 @@ public Action ForceTankCommand(int client, int args) Call_PushCell(p_iRequestedPercent); Call_PushCell(-1); Call_Finish(); + + return Plugin_Handled; } public Action ForceWitchCommand(int client, int args) { - if (!GetConVarBool(g_hCvarBossVoting)) return; + if (!GetConVarBool(g_hCvarBossVoting)) { + return Plugin_Handled; + } + if (IsDarkCarniRemix()) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Command not available on this map."); - return; + return Plugin_Handled; } if (IsStaticWitchMap()) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Witch spawn is static and can not be changed on this map."); - return; + return Plugin_Handled; } if (!IsInReady()) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Command can only be used during ready up."); - return; + return Plugin_Handled; } // Get Requested Witch Percent @@ -405,7 +421,7 @@ public Action ForceWitchCommand(int client, int args) // Make sure the cmd argument is a number if (!IsInteger(bv_sWitch)) - return; + return Plugin_Handled; // Convert it to in int boy int p_iRequestedPercent = StringToInt(bv_sWitch); @@ -413,14 +429,14 @@ public Action ForceWitchCommand(int client, int args) if (p_iRequestedPercent < 0) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Percentage is {blue}invalid{default}."); - return; + return Plugin_Handled; } // Check if percent is within limits if (!IsWitchPercentValid(p_iRequestedPercent)) { CPrintToChat(client, "{blue}<{green}BossVote{blue}>{default} Percentage is {olive}banned{default}."); - return; + return Plugin_Handled; } // Set the boss @@ -439,4 +455,6 @@ public Action ForceWitchCommand(int client, int args) Call_PushCell(-1); Call_PushCell(p_iRequestedPercent); Call_Finish(); -} \ No newline at end of file + + return Plugin_Handled; +} diff --git a/addons/sourcemod/scripting/l4d_ci_ffblock.sp b/addons/sourcemod/scripting/l4d_ci_ffblock.sp index f96ff1388..adfa7f8c3 100644 --- a/addons/sourcemod/scripting/l4d_ci_ffblock.sp +++ b/addons/sourcemod/scripting/l4d_ci_ffblock.sp @@ -56,12 +56,12 @@ public Action:OnTakeDamage(victim, &attacker, &inflictor, &Float:damage, &damage damage = float(RoundToCeil(float(GetConVarInt(g_hCvarCommonHealth)) / float(GetConVarInt(g_hCvarDamage)))); return Plugin_Changed; } - return Plugin_Handled; + return Plugin_Handled; } return Plugin_Continue; } -stock bool:IsTank(client) +bool:IsTank(client) { if (GetEntProp(client, Prop_Send, "m_zombieClass") == 8) return true; return false; @@ -71,6 +71,5 @@ bool:IsValidClient(client) { if (client <= 0 || client > MaxClients) return false; if (!IsClientInGame(client)) return false; - if (IsClientSourceTV(client) || IsClientReplay(client)) return false; return true; } diff --git a/addons/sourcemod/scripting/l4d_jockey_ledgehang.sp b/addons/sourcemod/scripting/l4d_jockey_ledgehang.sp index 755976b27..94b99f8a8 100644 --- a/addons/sourcemod/scripting/l4d_jockey_ledgehang.sp +++ b/addons/sourcemod/scripting/l4d_jockey_ledgehang.sp @@ -61,5 +61,5 @@ public void JockeyRideEnd(Event hEvent, const char[] name, bool dontBroadcast) bool IsHangingFromLedge(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge") || GetEntProp(client, Prop_Send, "m_isFallingFromLedge")); + return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge", 1) || GetEntProp(client, Prop_Send, "m_isFallingFromLedge", 1)); } diff --git a/addons/sourcemod/scripting/l4d_skip_intro.sp b/addons/sourcemod/scripting/l4d_skip_intro.sp index 2ebb76c4c..41cf0a093 100644 --- a/addons/sourcemod/scripting/l4d_skip_intro.sp +++ b/addons/sourcemod/scripting/l4d_skip_intro.sp @@ -333,4 +333,6 @@ public Action TimerStart(Handle timer) // DispatchSpawn(entity); } } + + return Plugin_Stop; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/l4d_stuckzombiemeleefix.sp b/addons/sourcemod/scripting/l4d_stuckzombiemeleefix.sp index f8a33c183..27e01ac1d 100644 --- a/addons/sourcemod/scripting/l4d_stuckzombiemeleefix.sp +++ b/addons/sourcemod/scripting/l4d_stuckzombiemeleefix.sp @@ -23,46 +23,47 @@ public OnPluginStart() new bool:MeleeDelay[MAXPLAYERS+1]; -public Action:HookSound_Callback(Clients[64], &NumClients, String:StrSample[PLATFORM_MAX_PATH], &Entity) +public Action HookSound_Callback(int clients[MAXPLAYERS], int &numClients, char sample[PLATFORM_MAX_PATH], int &entity, int &channel, \ + float &volume, int &level, int &pitch, int &flags, char soundEntry[PLATFORM_MAX_PATH], int &seed) { //to work only on melee sounds, its 'swish' or 'weaponswing' - if (StrContains(StrSample, "Swish", false) == -1) return Plugin_Continue; + if (StrContains(sample, "Swish", false) == -1) return Plugin_Continue; //so the client has the melee sound playing. OMG HES MELEEING! - - if (Entity > MaxClients) return Plugin_Continue; // bugfix for some people on L4D2 - + + if (entity > MaxClients) return Plugin_Continue; // bugfix for some people on L4D2 + //add in a 1 second delay so this doesnt fire every frame - if (MeleeDelay[Entity]) return Plugin_Continue; //note 'Entity' means 'client' here - MeleeDelay[Entity] = true; - CreateTimer(1.0, ResetMeleeDelay, Entity); - + if (MeleeDelay[entity]) return Plugin_Continue; //note 'Entity' means 'client' here + MeleeDelay[entity] = true; + CreateTimer(1.0, ResetMeleeDelay, entity); + #if DEBUG PrintToChatAll("Melee detected via soundhook."); #endif - - new entid = GetClientAimTarget(Entity, false); + + new entid = GetClientAimTarget(entity, false); if (entid <= 0) return Plugin_Continue; - + decl String:entclass[96]; GetEntityNetClass(entid, entclass, sizeof(entclass)); if (!StrEqual(entclass, "Infected")) return Plugin_Continue; - + decl Float:clientpos[3], Float:entpos[3]; GetEntityAbsOrigin(entid, entpos); - GetClientEyePosition(Entity, clientpos); + GetClientEyePosition(entity, clientpos); if (GetVectorDistance(clientpos, entpos) < 50) return Plugin_Continue; //else you could 'jedi melee' Zombies from a distance - + #if DEBUG PrintToChatAll("Youre meleeing and looking at Zombie id #%i", entid); #endif - + //now to make this Zombie fire a event to be caught by the actual 'fix' - + new Handle:newEvent = CreateEvent("entity_shoved", true); - SetEventInt(newEvent, "attacker", Entity); //the client being called Entity is a bit unfortunate + SetEventInt(newEvent, "attacker", entity); //the client being called Entity is a bit unfortunate SetEventInt(newEvent, "entityid", entid); FireEvent(newEvent, true); - + return Plugin_Continue; } diff --git a/addons/sourcemod/scripting/l4d_tank_control_eq.sp b/addons/sourcemod/scripting/l4d_tank_control_eq.sp index 16844ec3a..81845f948 100644 --- a/addons/sourcemod/scripting/l4d_tank_control_eq.sp +++ b/addons/sourcemod/scripting/l4d_tank_control_eq.sp @@ -23,6 +23,8 @@ bool casterSystemAvailable; public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) { CreateNative("GetTankSelection", Native_GetTankSelection); + + return APLRes_Success; } public int Native_GetTankSelection(Handle plugin, int numParams) { return getInfectedPlayerBySteamId(queuedTankSteamId); } @@ -127,15 +129,17 @@ public void RoundStart_Event(Event hEvent, const char[] eName, bool dontBroadcas public Action newGame(Handle timer) { - int teamAScore = L4D2Direct_GetVSCampaignScore(0); - int teamBScore = L4D2Direct_GetVSCampaignScore(1); - - // If it's a new game, reset the tank pool - if (teamAScore == 0 && teamBScore == 0) - { - h_whosHadTank.Clear(); - queuedTankSteamId = ""; - } + int teamAScore = L4D2Direct_GetVSCampaignScore(0); + int teamBScore = L4D2Direct_GetVSCampaignScore(1); + + // If it's a new game, reset the tank pool + if (teamAScore == 0 && teamBScore == 0) + { + h_whosHadTank.Clear(); + queuedTankSteamId = ""; + } + + return Plugin_Stop; } /** @@ -433,7 +437,7 @@ public void outputTankToAll(any data) } } -stock int PrintToInfected(const char[] Message, any ... ) +stock void PrintToInfected(const char[] Message, any ... ) { char sPrint[256]; VFormat(sPrint, sizeof(sPrint), Message, 2); diff --git a/addons/sourcemod/scripting/l4d_tank_damage_announce.sp b/addons/sourcemod/scripting/l4d_tank_damage_announce.sp index a05824a5b..4eee5f62a 100644 --- a/addons/sourcemod/scripting/l4d_tank_damage_announce.sp +++ b/addons/sourcemod/scripting/l4d_tank_damage_announce.sp @@ -14,8 +14,8 @@ new const ZOMBIECLASS_TANK = 8; // Zombi new bool: g_bEnabled = true; new bool: g_bAnnounceTankDamage = false; // Whether or not tank damage should be announced new bool: g_bIsTankInPlay = false; // Whether or not the tank is active -new bool: bPrintedHealth = false; // Is Remaining Health showed? -new g_iWasTank[MAXPLAYERS + 1] = 0; // Was Player Tank before he died. +new bool: bPrintedHealth = false; // Is Remaining Health showed? +new g_iWasTank[MAXPLAYERS + 1] = {0, ...}; // Was Player Tank before he died. new g_iWasTankAI = 0; new g_iOffset_Incapacitated = 0; // Used to check if tank is dying new g_iTankClient = 0; // Which client is currently playing as tank diff --git a/addons/sourcemod/scripting/l4d_tank_rush.sp b/addons/sourcemod/scripting/l4d_tank_rush.sp index 3f0eaa4af..843b96351 100644 --- a/addons/sourcemod/scripting/l4d_tank_rush.sp +++ b/addons/sourcemod/scripting/l4d_tank_rush.sp @@ -4,7 +4,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include bool @@ -73,6 +73,8 @@ public Action L4D2_OnEndVersusModeRound(bool countSurvivors) if (cvar_unfreezeSaferoom.IntValue == 1 && IsTankActuallyInPlay() && GetUprightSurvivors() > 0) { UnFreezePoints(true, 2); } + + return Plugin_Continue; } void PluginDisable() @@ -129,6 +131,8 @@ public Action CheckForTanksDelay(Handle timer) if (!IsTankActuallyInPlay()) { UnFreezePoints(true); } + + return Plugin_Stop; } void FreezePoints(bool show_message = false) diff --git a/addons/sourcemod/scripting/l4d_tankpunchstuckfix.sp b/addons/sourcemod/scripting/l4d_tankpunchstuckfix.sp index 1316818e8..2f9ce0f0b 100644 --- a/addons/sourcemod/scripting/l4d_tankpunchstuckfix.sp +++ b/addons/sourcemod/scripting/l4d_tankpunchstuckfix.sp @@ -114,7 +114,7 @@ public void OnMapEnd() fClearArrays(); } -public Action Event_Reset(Event hEvent, const char[] name, bool dontBroadcast) +public void Event_Reset(Event hEvent, const char[] name, bool dontBroadcast) { fClearArrays(); } diff --git a/addons/sourcemod/scripting/l4d_weapon_limits.sp b/addons/sourcemod/scripting/l4d_weapon_limits.sp index 5c112a567..98dec6103 100644 --- a/addons/sourcemod/scripting/l4d_weapon_limits.sp +++ b/addons/sourcemod/scripting/l4d_weapon_limits.sp @@ -4,7 +4,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include //#include #include @@ -21,14 +21,14 @@ enum struct LimitArrayEntry { int LAE_iLimit; int LAE_iGiveAmmo; - int LAE_WeaponArray[view_as(WEPID_SIZE) / 32 + 1]; + int LAE_WeaponArray[WEPID_SIZE / 32 + 1]; } #else enum LimitArrayEntry { LAE_iLimit, LAE_iGiveAmmo, - LAE_WeaponArray[view_as(WEPID_SIZE) / 32 + 1] + LAE_WeaponArray[WEPID_SIZE / 32 + 1] }; #endif @@ -144,7 +144,7 @@ public Action AddLimit_Cmd(int args) for (int i = 3; i <= args; ++i) { GetCmdArg(i, sTempBuff, sizeof(sTempBuff)); - wepid = view_as(WeaponNameToId(sTempBuff)); + wepid = WeaponNameToId(sTempBuff); newEntry.LAE_WeaponArray[wepid / 32] |= (1 << (wepid % 32)); } @@ -160,7 +160,7 @@ public Action AddLimit_Cmd(int args) for (int i = 3; i <= args; ++i) { GetCmdArg(i, sTempBuff, sizeof(sTempBuff)); - wepid = view_as(WeaponNameToId(sTempBuff)); + wepid = WeaponNameToId(sTempBuff); newEntry[LAE_WeaponArray][wepid / 32] |= (1 << (wepid % 32)); } @@ -177,6 +177,8 @@ public Action LockLimits_Cmd(int args) bIsLocked = true; PrintToServer("Weapon limits locked !"); } + + return Plugin_Handled; } public Action ClearLimits_Cmd(int args) @@ -186,6 +188,8 @@ public Action ClearLimits_Cmd(int args) PrintToChatAll("[L4D Weapon Limits] Weapon limits cleared!"); ClearLimits(); } + + return Plugin_Handled; } void ClearLimits() @@ -205,10 +209,10 @@ public Action WeaponCanUse(int client, int weapon) return Plugin_Continue; } - int wepid = view_as(IdentifyWeapon(weapon)); - int wep_slot = GetSlotFromWeaponId(view_as(wepid)); + int wepid = IdentifyWeapon(weapon); + int wep_slot = GetSlotFromWeaponId(wepid); int player_weapon = GetPlayerWeaponSlot(client, wep_slot); - int player_wepid = view_as(IdentifyWeapon(player_weapon)); + int player_wepid = IdentifyWeapon(player_weapon); #if SOURCEMOD_V_MINOR > 9 LimitArrayEntry arrayEntry; @@ -223,7 +227,7 @@ public Action WeaponCanUse(int client, int weapon) if (arrayEntry.LAE_WeaponArray[wepid / 32] & (1 << (wepid % 32)) && GetWeaponCount(arrayEntry.LAE_WeaponArray) >= arrayEntry.LAE_iLimit) { if (!player_wepid || wepid == player_wepid || !(arrayEntry.LAE_WeaponArray[player_wepid / 32] & (1 << (player_wepid % 32)))) { // Swap melee, np - if (player_wepid == view_as(WEPID_MELEE) && wepid == view_as(WEPID_MELEE)) { + if (player_wepid == WEPID_MELEE && wepid == WEPID_MELEE) { return Plugin_Continue; } @@ -241,7 +245,7 @@ public Action WeaponCanUse(int client, int weapon) if (arrayEntry[LAE_WeaponArray][wepid / 32] & (1 << (wepid % 32)) && GetWeaponCount(arrayEntry[LAE_WeaponArray]) >= arrayEntry[LAE_iLimit]) { if (!player_wepid || wepid == player_wepid || !(arrayEntry[LAE_WeaponArray][player_wepid / 32] & (1 << (player_wepid % 32)))) { // Swap melee, np - if (player_wepid == view_as(WEPID_MELEE) && wepid == view_as(WEPID_MELEE)) { + if (player_wepid == WEPID_MELEE && wepid == WEPID_MELEE) { return Plugin_Continue; } @@ -306,13 +310,13 @@ public void OnPlayerReplacedBot(Event event, const char[] name, bool dontBroadca stock int GetWeaponCount(const int[] mask) { - bool queryMelee = view_as(mask[view_as(WEPID_MELEE) / 32] & (1 << (view_as(WEPID_MELEE) % 32))); + bool queryMelee = view_as(mask[WEPID_MELEE / 32] & (1 << (WEPID_MELEE % 32))); int count, wepid; for (int i = 1; i <= MaxClients; i++) { if (IsClientInGame(i) && GetClientTeam(i) == TEAM_SURVIVOR && IsPlayerAlive(i)) { for (int j = 0; j < MAX_PLAYER_WEAPON_SLOTS; ++j) { - wepid = view_as(IdentifyWeapon(GetPlayerWeaponSlot(i, j))); + wepid = IdentifyWeapon(GetPlayerWeaponSlot(i, j)); if (mask[wepid / 32] & (1 << (wepid % 32)) || (j == 1 && queryMelee && bIsIncappedWithMelee[i])) { count++; } diff --git a/addons/sourcemod/scripting/left4dhooks.sp b/addons/sourcemod/scripting/left4dhooks.sp index 2298d01b1..2fb6c7cfe 100644 --- a/addons/sourcemod/scripting/left4dhooks.sp +++ b/addons/sourcemod/scripting/left4dhooks.sp @@ -18,7 +18,7 @@ -#define PLUGIN_VERSION "1.61" +#define PLUGIN_VERSION "1.69" #define DEBUG 0 // #define DEBUG 1 // Prints addresses + detour info (only use for debugging, slows server down) @@ -42,6 +42,116 @@ ======================================================================================== Change Log: +1.69a (04-Nov-2021) + - Added missing forwards "L4D_OnPouncedOnSurvivor" and "L4D2_OnStartCarryingVictim" to the include file. Thanks to "ProjectSky" for reporting. + +1.69 (03-Nov-2021) + - Added forward "L4D_OnPouncedOnSurvivor" to notify when a Survivor is being pounced on by a Hunter. + - Added forward "L4D2_OnStartCarryingVictim" to L4D2 to notify when a Survivor is being grabbed by a Charger. + - Fixed some natives disabling the plugin if their signatures broke. Only their functionality will break. + + - GameData files, include file and plugins updated. + +1.68 (02-Nov-2021) + - Added forward "L4D_OnGrabWithTongue" to L4D2 to notify when someone is about to be grabbed by a Smoker Tongue. Requested by "Alexmy". + - Added forward "L4D2_OnJockeyRide" to notify when someone is about to be ridden by a Jockey. Requested by "Alexmy". + - Cleaned and consolidated the code: standardized gamedata names, function names and variable names. + - Compatibility support for SourceMod 1.11. Fixed various warnings. + + - GameData files, include file and plugins updated. + +1.67 (25-Oct-2021) + - Fixed the create projectile natives from failing still when passing 0 entity index. Thanks to "BHaType" for reporting. + - Fixed L4D1 Linux forward "TryOfferingTankBot" sometimes throwing errors. Thanks to "HarryPotter" for reporting. + - Fixed L4D1 setting "L4D2FWA_PenetrationNumLayers" - float values will be rounded to ceiling. Thanks to "epzminion" for finding and "Psyk0tik" for reporting. + - Fixed target filters "@isb" and "@isp" being flipped. + +1.66 (21-Oct-2021) + - Fixed L4D1 Linux not finding the "g_pWeaponInfoDatabase" signature. Thanks to "Ja-Forces" for reporting. + - L4D1 GameData updated. + +1.65 (20-Oct-2021) + - Changed forward "L4D2_CGasCan_EventKilled" params to show the inflictor and attacker. + - Thanks to "ProjectSky" for reminding me. + + - Plugins and include file updated. + +1.64 (20-Oct-2021) + - Added 1 new forward to L4D1 and L4D2: + - "L4D_CBreakableProp_Break" - When a physics prop is broken. + + - Added 3 new forwards to L4D2: + - "L4D2_CGasCan_EventKilled" - When a GasCan is destroyed. + - "L4D2_CGasCan_ActionComplete" - When a Survivor has finished pouring gas. + - "L4D2_CInsectSwarm_CanHarm" - When Spitter Acid is checking if a player or entity can be damaged. + + - Added 1 new native to L4D1 and L4D2: + - "L4D_GetWeaponID" - to get the Weapon ID by classname + + - Added and unlocked all the weapon attribute modification natives to L4D1: + - Thanks to "Psyk0tik" for the suggestion and information about offsets. + - "L4D2_IsValidWeapon" + - "L4D2_GetFloatWeaponAttribute" and "L4D2_SetFloatWeaponAttribute" + - "L4D2_GetIntWeaponAttribute" and "L4D2_SetIntWeaponAttribute" + - "L4D2IntWeaponAttributes" enums - ("L4D2IWA_Bullets", "L4D2IWA_Damage", "L4D2IWA_ClipSize") + - "L4D2FloatWeaponAttributes" enums - ("L4D2FWA_MaxPlayerSpeed", "L4D2FWA_SpreadPerShot", "L4D2FWA_MaxSpread", "L4D2FWA_Range", etc) + + - Added new target filters: + "@deads" - Dead Survivors (all, bots) + "@deadsi" - Dead Special Infected (all, bots) + "@deadsp" - Dead Survivors players (no bots) + "@deadsip" - Dead Special Infected players (no bots) + "@deadsb" - Dead Survivors bots (no players) + "@deadsib" - Dead Special Infected bots (no players) + "@sp" - Survivors players (no bots) + "@sip" - Special Infected players (no bots) + "@isb" - Incapped Survivor Only Bots + "@isp" - Incapped Survivor Only Players + + - Changed target filter names: + "@incappedsurvivorbot" to "@rincappedsurvivorbot" + "@isb" to "@risb" + "@survivorbot" to "@rsurvivorbot" + "@sb" to "@rsb" + "@infectedbot" to "@rinfectedbot" + "@ib" to "@rib" + "@tankbot" to "@rtankbot" + "@tb" to "@rtb" + + - Added "FINALE_*" enums to the include file for use with the "L4D2_ChangeFinaleStage" and "L4D2_GetCurrentFinaleStage" natives and "L4D2_OnChangeFinaleStage" forward. + - Thanks to "Dragokas" for suggesting. + + - GameData files, include file and plugins updated. + +1.63 (15-Oct-2021) + - Changed all projectile natives to allow passing 0 (world) instead of a client index. Thanks to "BHaType" for reporting. + - Changed forward "L4D_OnGameModeChange" from "Action" type to "Void". Thanks to "Psyk0tik" for reporting. + - Fixed commands "sm_l4dd_detours" and "sm_l4dhooks_detours" not showing all forwards when they have pre and post hooks. + + - Added 11 new forwards to L4D1 and L4D2. Thanks to "Psyk0tik" for the suggestions, signatures and detour functions. + - "L4D_TankClaw_DoSwing_Pre" - When a tank is swinging to punch. + - "L4D_TankClaw_DoSwing_Post" - When a tank is swinging to punch. + - "L4D_TankClaw_GroundPound_Pre" - When an tank punches the ground. + - "L4D_TankClaw_GroundPound_Post" - When an tank punches the ground. + - "L4D_TankClaw_OnPlayerHit_Pre" - When a tank swings and punches a player. + - "L4D_TankClaw_OnPlayerHit_Post" - When a tank swings and punches a player. + - "L4D_TankRock_OnDetonate" - When a tank rock hits something. + - "L4D_TankRock_OnRelease" - When a tank rock is thrown. + - "L4D_PlayerExtinguish" - When a player is about to be extinguished. + - "L4D_PipeBombProjectile_Pre" - When a PipeBomb projectile is being created. + - "L4D_PipeBombProjectile_Post" - After a PipeBomb projectile is created. + + - Added 1 new forward to L4D2. Thanks to "Lux" for the suggestion, signature and detour functions. + - "L4D2_MeleeGetDamageForVictim" - When calculating melee damage to inflict on something. + + - GameData files, include file and plugins updated. + +1.62 (08-Oct-2021) + - L4D1 Linux: Update thanks to "Forgetest" for writing. + - L4D1 Linux: Fixed issues with the forwards "L4D_OnShovedBySurvivor" and "L4D2_OnStagger". Thanks "HarryPotter" for reporting. + + - L4D1 GameData file and plugin updated. + 1.61 (05-Oct-2021) - Added natives "L4D_GetTempHealth" and "L4D_SetTempHealth" to handle Survivors temporary health buffer. - Added natives "L4D_PlayMusic" to play a specified music string to a client. Thanks to "DeathChaos25" and "Shadowysn" for "Dynamic Soundtrack Sets" plugin. @@ -70,7 +180,7 @@ 1.60 (29-Sep-2021) - Added native "L4D2_GrenadeLauncherPrj" to create an activated Grenade Launcher projectile which detonates on impact. L4D2 only. - - Fixed L4D1 Linux "MolotovProjectile_Create" signature. Thanks to "Ja-Forces" for reporting. + - Fixed L4D1 Linux "CMolotovProjectile::Create" signature. Thanks to "Ja-Forces" for reporting. 1.59 (29-Sep-2021) - HotFix: Fix Linux not loading the last 2 natives. @@ -156,7 +266,7 @@ 1.45 (04-Jul-2021) - Fixed bad description for "L4D_SetHumanSpec" and "L4D_TakeOverBot" in the Include file. - - L4D1: Fixed forward "L4D_OnVomitedUpon" crashing. GameData file updated. Thanks to "Crasher_3637" for reporting. + - L4D1: Fixed forward "L4D_OnVomitedUpon" crashing. GameData file updated. Thanks to "Psyk0tik" for reporting. 1.44 (01-Jul-2021) - Fixed forward "L4D_OnMaterializeFromGhost" not firing. Thanks to "ProjectSky" for reporting. @@ -217,7 +327,7 @@ 1.39 (16-Jun-2021) - Changed command "sm_l4dd_detours" results displayed to be read easier. - - L4D2: Fixed signatures breaking from "2.2.1.3" game update. Thanks to "Crasher_3637" for fixing. + - L4D2: Fixed signatures breaking from "2.2.1.3" game update. Thanks to "Psyk0tik" for fixing. - L4D2: Fixed "VanillaModeOffset" in Linux breaking from "2.2.1.3" game update. Thanks to "Accelerator74" for fixing. - GameData .txt file updated. @@ -245,7 +355,7 @@ 1.34 (23-Mar-2021) - Added native "L4D_HasPlayerControlledZombies" to return if players can control infected. Thanks to "Spirit_12" for requesting. - - Thanks to "Crasher_3637" for the L4D1 signature. + - Thanks to "Psyk0tik" for the L4D1 signature. - Fixed Linux detection accidentally being broken from version 1.17 update. - Updated: L4D1 GameData file. @@ -396,7 +506,7 @@ 1.13 (05-May-2020) - Added better error log message when gamedata file is missing. - Fixed "L4D2_OnEntityShoved" not detecting the last client. Thanks to "Addie" for reporting. - - Made all natives optional from the include file. Thanks to "Crasher_3637" for requesting. + - Made all natives optional from the include file. Thanks to "Psyk0tik" for requesting. - Optional natives can be set by plugins with "#undef REQUIRE_PLUGIN" before "#include " and "#define REQUIRE_PLUGIN" after. - Updated: Plugin and Include file. @@ -605,6 +715,8 @@ float g_fProf; #define NATIVE_UNSUPPORTED1 "\n==========\nThis Native is only supported in L4D1.\nPlease fix the code to avoid calling this native from L4D2.\n==========" #define NATIVE_UNSUPPORTED2 "\n==========\nThis Native is only supported in L4D2.\nPlease fix the code to avoid calling this native from L4D1.\n==========" + + // Tank animations #define L4D2_ACT_HULK_THROW 761 #define L4D2_ACT_TANK_OVERHEAD_THROW 762 @@ -634,9 +746,14 @@ float g_fProf; #define L4D1_SEQ_THROW_FROM_HIP 48 #define L4D1_SEQ_THROW_2HAND_OVER 49 + + // Dissolver #define SPRITE_GLOW "sprites/blueglow1.vmt" + + +// Precache models for spawning static const char g_sModels1[][] = { "models/infected/witch.mdl", @@ -657,13 +774,15 @@ static const char g_sModels2[][] = // Dynamic Detours: -#define MAX_FWD_LEN 32 // Maximum string length of forward names, used for ArrayList. +#define MAX_FWD_LEN 64 // Maximum string length of forward and signature names, used for ArrayList. // ToDo: When using extra-api.ext (or hopefully one day native SM forwards), g_aDetoursHooked will store the number of plugins using each forward // so we can disable when the value is 0 and not have to check all plugins just to determine if still required. ArrayList g_aDetoursHooked; // Identifies if the detour hook is enabled or disabled ArrayList g_aDetourHandles; // Stores detour handles to enable/disable as required +ArrayList g_aGameDataSigs; // Stores Signature names ArrayList g_aForwardNames; // Stores Forward names +ArrayList g_aUseLastIndex; // Use last index ArrayList g_aForwardIndex; // Stores Detour indexes ArrayList g_aForceDetours; // Determines if a detour should be forced on without any forward using it int g_iCurrentIndex; // Index for each detour while created @@ -674,10 +793,10 @@ Handle g_hThisPlugin; // Ignore checking this plugin // Animation Hook int g_iAnimationDetourIndex; -ArrayList g_iHookedClients; -ArrayList g_hActivityList; +ArrayList g_iAnimationHookedClients; +ArrayList g_hAnimationActivityList; PrivateForward g_hAnimationCallbackPre; -PrivateForward g_hAnimationCallback; +PrivateForward g_hAnimationCallbackPost; @@ -690,215 +809,231 @@ ArrayList g_aMeleePtrs; // Stores melee pointers // FORWARDS -GlobalForward g_hForward_GameModeChange; -GlobalForward g_hForward_SpawnSpecial; -GlobalForward g_hForward_SpawnTank; -GlobalForward g_hForward_SpawnWitch; -GlobalForward g_hForward_SpawnWitchBride; -GlobalForward g_hForward_ClearTeamScores; -GlobalForward g_hForward_SetCampaignScores; -GlobalForward g_hForward_RecalculateVersusScore; -GlobalForward g_hForward_OnFirstSurvivorLeftSafeArea; -GlobalForward g_hForward_GetScriptValueInt; -GlobalForward g_hForward_GetScriptValueFloat; -GlobalForward g_hForward_GetScriptValueString; -GlobalForward g_hForward_IsTeamFull; -GlobalForward g_hForward_EnterGhostState; -GlobalForward g_hForward_EnterGhostStatePre; -GlobalForward g_hForward_TryOfferingTankBot; -GlobalForward g_hForward_MobRushStart; -GlobalForward g_hForward_SpawnITMob; -GlobalForward g_hForward_SpawnMob; -GlobalForward g_hForward_ShovedBySurvivor; -GlobalForward g_hForward_GetCrouchTopSpeed; -GlobalForward g_hForward_GetRunTopSpeed; -GlobalForward g_hForward_GetWalkTopSpeed; -GlobalForward g_hForward_HasConfigurableDifficulty; -GlobalForward g_hForward_GetSurvivorSet; -GlobalForward g_hForward_FastGetSurvivorSet; -GlobalForward g_hForward_GetMissionVSBossSpawning; -GlobalForward g_hForward_CThrowActivate; -GlobalForward g_hForward_StartMeleeSwing; -GlobalForward g_hForward_SendInRescueVehicle; -GlobalForward g_hForward_ChangeFinaleStage; -GlobalForward g_hForward_EndVersusModeRound; -GlobalForward g_hForward_EndVersusModeRoundPost; -GlobalForward g_hForward_SelectTankAttackPre; -GlobalForward g_hForward_SelectTankAttack; -GlobalForward g_hForward_LedgeGrabbed; -GlobalForward g_hForward_OnRevived; -GlobalForward g_hForward_OnReplaceTank; -GlobalForward g_hForward_OnUseHealingItems; -GlobalForward g_hForward_OnFindScavengeItem; -GlobalForward g_hForward_OnChooseVictim; -GlobalForward g_hForward_OnMaterializeFromGhostPre; -GlobalForward g_hForward_OnMaterializeFromGhost; -GlobalForward g_hForward_OnVomitedUpon; -GlobalForward g_hForward_OnHitByVomitJar; -GlobalForward g_hForward_InfernoSpread; -GlobalForward g_hForward_CTerrorWeapon_OnHit; -GlobalForward g_hForward_OnPlayerStagger; -GlobalForward g_hForward_OnShovedByPounceLanding; -GlobalForward g_hForward_PlayerFling; -GlobalForward g_hForward_FatalFalling; -GlobalForward g_hForward_Falling; -GlobalForward g_hForward_EnterStasis; -GlobalForward g_hForward_LeaveStasis; -GlobalForward g_hForward_AddonsDisabler; -// GlobalForward g_hForward_GetRandomPZSpawnPos; -// GlobalForward g_hForward_InfectedShoved; -// GlobalForward g_hForward_OnWaterMove; +GlobalForward g_hFWD_GameModeChange; +GlobalForward g_hFWD_ZombieManager_SpawnSpecial; +GlobalForward g_hFWD_ZombieManager_SpawnTank; +GlobalForward g_hFWD_ZombieManager_SpawnWitch; +GlobalForward g_hFWD_ZombieManager_SpawnWitchBride; +GlobalForward g_hFWD_CTerrorGameRules_ClearTeamScores; +GlobalForward g_hFWD_CTerrorGameRules_SetCampaignScores; +GlobalForward g_hFWD_CTerrorPlayer_RecalculateVersusScore; +GlobalForward g_hFWD_CDirector_OnFirstSurvivorLeftSafeArea; +GlobalForward g_hFWD_CDirector_GetScriptValueInt; +GlobalForward g_hFWD_CDirector_GetScriptValueFloat; +GlobalForward g_hFWD_CDirector_GetScriptValueString; +GlobalForward g_hFWD_CDirector_IsTeamFull; +GlobalForward g_hFWD_CTerrorPlayer_EnterGhostState; +GlobalForward g_hFWD_CTerrorPlayer_EnterGhostStatePre; +GlobalForward g_hFWD_CTankClaw_DoSwing_Pre; +GlobalForward g_hFWD_CTankClaw_DoSwing_Post; +GlobalForward g_hFWD_CTankClaw_GroundPound_Pre; +GlobalForward g_hFWD_CTankClaw_GroundPound_Post; +GlobalForward g_hFWD_CTankClaw_OnPlayerHit_Pre; +GlobalForward g_hFWD_CTankClaw_OnPlayerHit_Post; +GlobalForward g_hFWD_CTankRock_Detonate; +GlobalForward g_hFWD_CTankRock_OnRelease; +GlobalForward g_hFWD_CDirector_TryOfferingTankBot; +GlobalForward g_hFWD_CDirector_MobRushStart; +GlobalForward g_hFWD_ZombieManager_SpawnITMob; +GlobalForward g_hFWD_ZombieManager_SpawnMob; +GlobalForward g_hFWD_CTerrorPlayer_OnShovedBySurvivor; +GlobalForward g_hFWD_CTerrorPlayer_GetCrouchTopSpeed; +GlobalForward g_hFWD_CTerrorPlayer_GetRunTopSpeed; +GlobalForward g_hFWD_CTerrorPlayer_GetWalkTopSpeed; +GlobalForward g_hFWD_CTerrorGameRules_HasConfigurableDifficultySetting; +GlobalForward g_hFWD_CTerrorGameRules_GetSurvivorSet; +GlobalForward g_hFWD_CTerrorGameRules_FastGetSurvivorSet; +GlobalForward g_hFWD_GetMissionVSBossSpawning; +GlobalForward g_hFWD_CThrow_ActivateAbililty; +GlobalForward g_hFWD_StartMeleeSwing; +GlobalForward g_hFWD_GetDamageForVictim; +GlobalForward g_hFWD_CDirectorScriptedEventManager_SendInRescueVehicle; +GlobalForward g_hFWD_CDirectorScriptedEventManager_ChangeFinaleStage; +GlobalForward g_hFWD_CDirectorVersusMode_EndVersusModeRound_Pre; +GlobalForward g_hFWD_CDirectorVersusMode_EndVersusModeRound_Post; +GlobalForward g_hFWD_CBaseAnimating_SelectWeightedSequence_Pre; +GlobalForward g_hFWD_CBaseAnimating_SelectWeightedSequence_Post; +GlobalForward g_hFWD_CTerrorPlayer_OnLedgeGrabbed; +GlobalForward g_hFWD_CTerrorPlayer_OnRevived_Post; +GlobalForward g_hFWD_ZombieManager_ReplaceTank; +GlobalForward g_hFWD_SurvivorBot_UseHealingItems; +GlobalForward g_hFWD_SurvivorBot_FindScavengeItem_Post; +GlobalForward g_hFWD_BossZombiePlayerBot_ChooseVictim_Post; +GlobalForward g_hFWD_CTerrorPlayer_MaterializeFromGhost_Pre; +GlobalForward g_hFWD_CTerrorPlayer_MaterializeFromGhost_Post; +GlobalForward g_hFWD_CTerrorPlayer_OnVomitedUpon; +GlobalForward g_hFWD_CTerrorPlayer_OnHitByVomitJar; +GlobalForward g_hFWD_CBreakableProp_Break_Post; +GlobalForward g_hFWD_CGasCanEvent_Killed; +GlobalForward g_hFWD_CGasCan_OnActionComplete; +GlobalForward g_hFWD_CTerrorPlayer_OnPouncedOnSurvivor; +GlobalForward g_hFWD_CTerrorPlayer_GrabVictimWithTongue; +GlobalForward g_hFWD_CTerrorPlayer_OnLeptOnSurvivor; +GlobalForward g_hFWD_CTerrorPlayer_OnStartCarryingVictim; +GlobalForward g_hFWD_CInsectSwarm_CanHarm; +GlobalForward g_hFWD_CPipeBombProjectile_Create_Pre; +GlobalForward g_hFWD_CPipeBombProjectile_Create_Post; +GlobalForward g_hFWD_CTerrorPlayer_Extinguish; +GlobalForward g_hFWD_CInferno_Spread; +GlobalForward g_hFWD_CTerrorWeapon_OnHit; +GlobalForward g_hFWD_CTerrorPlayer_OnStaggered; +GlobalForward g_hFWD_CTerrorPlayer_OnShovedByPounceLanding; +GlobalForward g_hFWD_CTerrorPlayer_Fling; +GlobalForward g_hFWD_CDeathFallCamera_Enable; +GlobalForward g_hFWD_CTerrorPlayer_OnFalling_Post; +GlobalForward g_hFWD_Tank_EnterStasis_Post; +GlobalForward g_hFWD_Tank_LeaveStasis_Post; +GlobalForward g_hFWD_AddonsDisabler; +// GlobalForward g_hFWD_GetRandomPZSpawnPos; +// GlobalForward g_hFWD_InfectedShoved; +// GlobalForward g_hFWD_OnWaterMove; // NATIVES - SDKCall // Silvers Natives -Handle g_hSDK_Call_HasConfigurableDifficultySetting; -Handle g_hSDK_Call_IsGenericCooperativeMode; -Handle g_hSDK_Call_IsRealismMode; -Handle g_hSDK_Call_NavAreaTravelDistance; -Handle g_hSDK_Call_GetLastKnownArea; -Handle g_hSDK_Call_MusicPlay; -Handle g_hSDK_Call_MusicStop; -Handle g_hSDK_Call_Deafen; -Handle g_hSDK_Call_Dissolve; -Handle g_hSDK_Call_OnITExpired; -Handle g_hSDK_Call_AngularVelocity; -Handle g_hSDK_Call_IsReachable; -Handle g_hSDK_Call_HasPlayerControlledZombies; -Handle g_hSDK_Call_PipeBombPrj; -Handle g_hSDK_Call_MolotovPrj; -Handle g_hSDK_Call_VomitJarPrj; -Handle g_hSDK_Call_GrenadeLauncher; -Handle g_hSDK_Call_SpitterPrj; -Handle g_hSDK_Call_OnAdrenalineUsed; -Handle g_hSDK_Call_RoundRespawn; -Handle g_hSDK_Call_SetHumanSpec; -Handle g_hSDK_Call_TakeOverBot; -Handle g_hSDK_Call_CanBecomeGhost; -Handle g_hSDK_Call_AreWanderersAllowed; -Handle g_hSDK_Call_IsFinaleEscapeInProgress; -Handle g_hSDK_Call_ForceNextStage; -Handle g_hSDK_Call_IsTankInPlay; -Handle g_hSDK_Call_GetFurthestSurvivorFlow; -Handle g_hSDK_Call_GetScriptValueInt; -// Handle g_hSDK_Call_GetScriptValueFloat; -// Handle g_hSDK_Call_GetScriptValueString; -Handle g_hSDK_Call_GetRandomPZSpawnPosition; -Handle g_hSDK_Call_GetNearestNavArea; -Handle g_hSDK_Call_FindRandomSpot; -Handle g_hSDK_Call_HasAnySurvivorLeftSafeArea; -Handle g_hSDK_Call_IsAnySurvivorInCheckpoint; -Handle g_hSDK_Call_IsAnySurvivorInStartArea; -Handle g_hSDK_Call_GetMaxChapters; -Handle g_hSDK_Call_GetGameMode; -Handle g_hSDK_Call_KV_GetString; +Handle g_hSDK_CTerrorGameRules_HasConfigurableDifficultySetting; +Handle g_hSDK_CTerrorGameRules_IsGenericCooperativeMode; +Handle g_hSDK_CTerrorGameRules_IsRealismMode; +Handle g_hSDK_NavAreaTravelDistance; +Handle g_hSDK_CTerrorPlayer_GetLastKnownArea; +Handle g_hSDK_Music_Play; +Handle g_hSDK_Music_StopPlaying; +Handle g_hSDK_CTerrorPlayer_Deafen; +Handle g_hSDK_CEntityDissolve_Create; +Handle g_hSDK_CTerrorPlayer_OnITExpired; +Handle g_hSDK_CBaseEntity_ApplyLocalAngularVelocityImpulse; +Handle g_hSDK_SurvivorBot_IsReachable; +Handle g_hSDK_CTerrorGameRules_HasPlayerControlledZombies; +Handle g_hSDK_CPipeBombProjectile_Create; +Handle g_hSDK_CMolotovProjectile_Create; +Handle g_hSDK_VomitJarProjectile_Create; +Handle g_hSDK_CGrenadeLauncher_Projectile_Create; +Handle g_hSDK_CSpitterProjectile_Create; +Handle g_hSDK_CTerrorPlayer_OnAdrenalineUsed; +Handle g_hSDK_CTerrorPlayer_RoundRespawn; +Handle g_hSDK_SurvivorBot_SetHumanSpectator; +Handle g_hSDK_CTerrorPlayer_TakeOverBot; +Handle g_hSDK_CTerrorPlayer_CanBecomeGhost; +Handle g_hSDK_CDirector_AreWanderersAllowed; +Handle g_hSDK_CDirector_IsFinaleEscapeInProgress; +Handle g_hSDK_CDirector_ForceNextStage; +Handle g_hSDK_CDirector_IsTankInPlay; +Handle g_hSDK_CDirector_GetFurthestSurvivorFlow; +Handle g_hSDK_CDirector_GetScriptValueInt; +// Handle g_hSDK_CDirector_GetScriptValueFloat; +// Handle g_hSDK_CDirector_GetScriptValueString; +Handle g_hSDK_ZombieManager_GetRandomPZSpawnPosition; +Handle g_hSDK_CNavMesh_GetNearestNavArea; +Handle g_hSDK_TerrorNavArea_FindRandomSpot; +Handle g_hSDK_CDirector_HasAnySurvivorLeftSafeArea; +Handle g_hSDK_CDirector_IsAnySurvivorInExitCheckpoint; +Handle g_hSDK_CDirector_IsAnySurvivorInStartArea; +Handle g_hSDK_CTerrorGameRules_GetNumChaptersForMissionAndMode; +Handle g_hSDK_CDirector_GetGameModeBase; +Handle g_hSDK_KeyValues_GetString; // left4downtown.inc -Handle g_hSDK_Call_GetTeamScore; -Handle g_hSDK_Call_RestartScenarioFromVote; -Handle g_hSDK_Call_IsFirstMapInScenario; -Handle g_hSDK_Call_IsMissionFinalMap; -Handle g_hSDK_Call_ResetMobTimer; -Handle g_hSDK_Call_NotifyNetworkStateChanged; -Handle g_hSDK_Call_StaggerPlayer; -Handle g_hSDK_Call_ReplaceTank; -Handle g_hSDK_Call_SendInRescueVehicle; -Handle g_hSDK_Call_ChangeFinaleStage; -Handle g_hSDK_Call_SpawnSpecial; -Handle g_hSDK_Call_SpawnHunter; -Handle g_hSDK_Call_SpawnBoomer; -Handle g_hSDK_Call_SpawnSmoker; -Handle g_hSDK_Call_SpawnTank; -Handle g_hSDK_Call_SpawnWitch; -Handle g_hSDK_Call_SpawnWitchBride; -Handle g_hSDK_Call_GetWeaponInfo; -Handle g_hSDK_Call_GetMeleeInfo; -Handle g_hSDK_Call_GetMissionInfo; -Handle g_hSDK_Call_TryOfferingTankBot; -Handle g_hSDK_Call_GetNavArea; -Handle g_hSDK_Call_GetFlowDistance; -Handle g_hSDK_Call_DoAnimationEvent; -Handle g_hSDK_Call_RecomputeTeamScores; -Handle g_hSDK_Call_LobbyUnreserve; -// Handle g_hSDK_Call_GetCampaignScores; -// Handle g_hSDK_Call_LobbyIsReserved; +Handle g_hSDK_CTerrorGameRules_GetTeamScore; +Handle g_hSDK_CDirector_RestartScenarioFromVote; +Handle g_hSDK_CDirector_IsFirstMapInScenario; +Handle g_hSDK_CTerrorGameRules_IsMissionFinalMap; +Handle g_hSDK_CDirector_ResetMobTimer; +Handle g_hSDK_CGameRulesProxy_NotifyNetworkStateChanged; +Handle g_hSDK_CTerrorPlayer_OnStaggered; +Handle g_hSDK_ZombieManager_ReplaceTank; +Handle g_hSDK_CDirectorScriptedEventManager_SendInRescueVehicle; +Handle g_hSDK_CDirectorScriptedEventManager_ChangeFinaleStage; +Handle g_hSDK_ZombieManager_SpawnSpecial; +Handle g_hSDK_ZombieManager_SpawnHunter; +Handle g_hSDK_ZombieManager_SpawnBoomer; +Handle g_hSDK_ZombieManager_SpawnSmoker; +Handle g_hSDK_ZombieManager_SpawnTank; +Handle g_hSDK_ZombieManager_SpawnWitch; +Handle g_hSDK_ZombieManager_SpawnWitchBride; +Handle g_hSDK_GetWeaponInfo; +Handle g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo; +Handle g_hSDK_CTerrorGameRules_GetMissionInfo; +Handle g_hSDK_CDirector_TryOfferingTankBot; +Handle g_hSDK_CNavMesh_GetNavArea; +Handle g_hSDK_CTerrorPlayer_GetFlowDistance; +Handle g_hSDK_CTerrorPlayer_DoAnimationEvent; +Handle g_hSDK_CTerrorGameRules_RecomputeTeamScores; +Handle g_hSDK_CBaseServer_SetReservationCookie; +// Handle g_hSDK_GetCampaignScores; +// Handle g_hSDK_LobbyIsReserved; // l4d2addresses.txt -Handle g_hSDK_Call_CTerrorPlayer_OnVomitedUpon; -Handle g_hSDK_Call_CTerrorPlayer_OnHitByVomitJar; -Handle g_hSDK_Call_Infected_OnHitByVomitJar; -Handle g_hSDK_Call_CTerrorPlayer_Fling; -Handle g_hSDK_Call_CancelStagger; -Handle g_hSDK_Call_CreateRescuableSurvivors; -Handle g_hSDK_Call_OnRevived; -Handle g_hSDK_Call_GetVersusCompletionPlayer; -Handle g_hSDK_Call_GetHighestFlowSurvivor; -Handle g_hSDK_Call_GetInfectedFlowDistance; -Handle g_hSDK_Call_TakeOverZombieBot; -Handle g_hSDK_Call_ReplaceWithBot; -Handle g_hSDK_Call_CullZombie; -Handle g_hSDK_Call_SetClass; -Handle g_hSDK_Call_CreateAbility; -Handle g_hSDK_Call_MaterializeFromGhost; -Handle g_hSDK_Call_BecomeGhost; -Handle g_hSDK_Call_State_Transition; -Handle g_hSDK_Call_SwapTeams; -Handle g_hSDK_Call_AreTeamsFlipped; -Handle g_hSDK_Call_StartRematchVote; -Handle g_hSDK_Call_FullRestart; -Handle g_hSDK_Call_HideVersusScoreboard; -Handle g_hSDK_Call_HideScavengeScoreboard; -Handle g_hSDK_Call_HideScoreboard; -Handle g_hSDK_Call_RegisterForbiddenTarget; -Handle g_hSDK_Call_UnRegisterForbiddenTarget; - - - -// Offsets +Handle g_hSDK_CTerrorPlayer_OnVomitedUpon; +Handle g_hSDK_CTerrorPlayer_OnHitByVomitJar; +Handle g_hSDK_Infected_OnHitByVomitJar; +Handle g_hSDK_CTerrorPlayer_Fling; +Handle g_hSDK_CTerrorPlayer_CancelStagger; +Handle g_hSDK_CDirector_CreateRescuableSurvivors; +Handle g_hSDK_CTerrorPlayer_OnRevived; +Handle g_hSDK_CTerrorGameRules_GetVersusCompletion; +Handle g_hSDK_CDirectorTacticalServices_GetHighestFlowSurvivor; +Handle g_hSDK_Infected_GetFlowDistance; +Handle g_hSDK_CTerrorPlayer_TakeOverZombieBot; +Handle g_hSDK_CTerrorPlayer_ReplaceWithBot; +Handle g_hSDK_CTerrorPlayer_CullZombie; +Handle g_hSDK_CTerrorPlayer_SetClass; +Handle g_hSDK_CBaseAbility_CreateForPlayer; +Handle g_hSDK_CTerrorPlayer_MaterializeFromGhost; +Handle g_hSDK_CTerrorPlayer_BecomeGhost; +Handle g_hSDK_CCSPlayer_State_Transition; +Handle g_hSDK_CDirector_SwapTeams; +Handle g_hSDK_CDirector_AreTeamsFlipped; +Handle g_hSDK_CDirector_StartRematchVote; +Handle g_hSDK_CDirector_FullRestart; +Handle g_hSDK_CDirectorVersusMode_HideScoreboardNonVirtual; +Handle g_hSDK_CDirectorScavengeMode_HideScoreboardNonVirtual; +Handle g_hSDK_CDirector_HideScoreboard; +Handle g_hSDK_CDirector_RegisterForbiddenTarget; +Handle g_hSDK_CDirector_UnregisterForbiddenTarget; + + + +// Offsets - Addons Eclipse +int g_iOff_AddonEclipse1; +int g_iOff_AddonEclipse2; +int g_iOff_VanillaModeOffset; +Address g_pVanillaModeAddress; + +// Various offsets +int g_iOff_VersusStartTimer; +int g_iOff_m_rescueCheckTimer; +int g_iOff_SpawnTimer; +int g_iOff_MobSpawnTimer; +int g_iOff_VersusMaxCompletionScore; +int g_iOff_OnBeginRoundSetupTime; +int g_iOff_m_iTankCount; +int g_iOff_m_iWitchCount; +int g_iOff_m_iCampaignScores; +int g_iOff_m_fTankSpawnFlowPercent; +int g_iOff_m_fWitchSpawnFlowPercent; +int g_iOff_m_iTankPassedCount; +int g_iOff_m_bTankThisRound; +int g_iOff_m_bWitchThisRound; +int g_iOff_OvertimeGraceTimer; +int g_iOff_InvulnerabilityTimer; +int g_iOff_m_iTankTickets; +int g_iOff_m_iSurvivorHealthBonus; +int g_iOff_m_bFirstSurvivorLeftStartArea; +int g_iOff_m_iShovePenalty; +int g_iOff_m_fNextShoveTime; +int g_iOff_m_preIncapacitatedHealth; +int g_iOff_m_preIncapacitatedHealthBuffer; +int g_iOff_m_maxFlames; +int g_iOff_m_flow; +int g_iOff_m_PendingMobCount; +int g_iOff_m_fMapMaxFlowDistance; +int g_iOff_m_chapter; +// int g_iOff_m_iClrRender; // NULL PTR - METHOD (kept for demonstration) // int ClearTeamScore_A; // int ClearTeamScore_B; -int g_iAddonEclipse1; -int g_iAddonEclipse2; - -int VersusStartTimer; -int m_rescueCheckTimer; -int SpawnTimer; -int MobSpawnTimer; -int VersusMaxCompletionScore; -int OnBeginRoundSetupTime; -int ScriptedEventManagerPtr; -int VersusModePtr; -int ScavengeModePtr; -int VanillaModeOffset; -Address VanillaModeAddress; // Address TeamScoresAddress; -// Various offsets -int m_iTankCount; -int m_iWitchCount; -int m_iCampaignScores; -int m_fTankSpawnFlowPercent; -int m_fWitchSpawnFlowPercent; -int m_iTankPassedCount; -int m_bTankThisRound; -int m_bWitchThisRound; -int OvertimeGraceTimer; -int InvulnerabilityTimer; -int m_iTankTickets; -int m_iSurvivorHealthBonus; -int m_bFirstSurvivorLeftStartArea; -int m_iShovePenalty; -int m_fNextShoveTime; -int m_preIncapacitatedHealth; -int m_preIncapacitatedHealthBuffer; -int m_maxFlames; -int m_flow; -int m_PendingMobCount; -int m_fMapMaxFlowDistance; -int m_chapter; -// int m_iClrRender; // NULL PTR - METHOD (kept for demonstration) - // l4d2timers.inc int L4D2CountdownTimer_Offsets[9]; int L4D2IntervalTimer_Offsets[6]; @@ -913,6 +1048,9 @@ int L4D2FloatMeleeWeapon_Offsets[3]; // Pointers +int g_pScriptedEventManager; +int g_pVersusMode; +int g_pScavengeMode; Address g_pServer; Address g_pDirector; Address g_pGameRules; @@ -927,17 +1065,17 @@ Address g_pWeaponInfoDatabase; int g_iCurrentMode; int g_iMaxChapters; int g_iClassTank; -bool g_bCheckpoint[MAXPLAYERS+1]; -bool g_bRoundEnded; -bool g_bMapStarted; -bool g_bLeft4Dead2; bool g_bLinuxOS; -ConVar g_hCvarVScriptBuffer; -ConVar g_hCvarAddonsEclipse; -ConVar g_hCvarRescueDeadTime; -ConVar g_hDecayDecay; -ConVar g_hPillsHealth; -ConVar g_hMPGameMode; +bool g_bLeft4Dead2; +bool g_bMapStarted; +bool g_bRoundEnded; +bool g_bCheckpoint[MAXPLAYERS+1]; +ConVar g_hCvar_VScriptBuffer; +ConVar g_hCvar_AddonsEclipse; +ConVar g_hCvar_RescueDeadTime; +ConVar g_hCvar_PillsDecay; +ConVar g_hCvar_PillsHealth; +ConVar g_hCvar_MPGameMode; #if DEBUG bool g_bLateLoad; @@ -993,76 +1131,96 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max // ==================================================================================================== // FORWARDS // List should match the CreateDetour list of forwards. - g_hForward_GameModeChange = new GlobalForward("L4D_OnGameModeChange", ET_Event, Param_Cell); - g_hForward_SpawnSpecial = new GlobalForward("L4D_OnSpawnSpecial", ET_Event, Param_CellByRef, Param_Array, Param_Array); - g_hForward_SpawnTank = new GlobalForward("L4D_OnSpawnTank", ET_Event, Param_Array, Param_Array); - g_hForward_SpawnWitch = new GlobalForward("L4D_OnSpawnWitch", ET_Event, Param_Array, Param_Array); - g_hForward_MobRushStart = new GlobalForward("L4D_OnMobRushStart", ET_Event); - g_hForward_SpawnITMob = new GlobalForward("L4D_OnSpawnITMob", ET_Event, Param_CellByRef); - g_hForward_SpawnMob = new GlobalForward("L4D_OnSpawnMob", ET_Event, Param_CellByRef); - g_hForward_EnterGhostState = new GlobalForward("L4D_OnEnterGhostState", ET_Event, Param_Cell); - g_hForward_EnterGhostStatePre = new GlobalForward("L4D_OnEnterGhostStatePre", ET_Event, Param_Cell); - g_hForward_IsTeamFull = new GlobalForward("L4D_OnIsTeamFull", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_ClearTeamScores = new GlobalForward("L4D_OnClearTeamScores", ET_Event, Param_Cell); - g_hForward_SetCampaignScores = new GlobalForward("L4D_OnSetCampaignScores", ET_Event, Param_CellByRef, Param_CellByRef); + g_hFWD_GameModeChange = new GlobalForward("L4D_OnGameModeChange", ET_Event, Param_Cell); + g_hFWD_ZombieManager_SpawnSpecial = new GlobalForward("L4D_OnSpawnSpecial", ET_Event, Param_CellByRef, Param_Array, Param_Array); + g_hFWD_ZombieManager_SpawnTank = new GlobalForward("L4D_OnSpawnTank", ET_Event, Param_Array, Param_Array); + g_hFWD_ZombieManager_SpawnWitch = new GlobalForward("L4D_OnSpawnWitch", ET_Event, Param_Array, Param_Array); + g_hFWD_CDirector_MobRushStart = new GlobalForward("L4D_OnMobRushStart", ET_Event); + g_hFWD_ZombieManager_SpawnITMob = new GlobalForward("L4D_OnSpawnITMob", ET_Event, Param_CellByRef); + g_hFWD_ZombieManager_SpawnMob = new GlobalForward("L4D_OnSpawnMob", ET_Event, Param_CellByRef); + g_hFWD_CTerrorPlayer_EnterGhostState = new GlobalForward("L4D_OnEnterGhostState", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_EnterGhostStatePre = new GlobalForward("L4D_OnEnterGhostStatePre", ET_Event, Param_Cell); + g_hFWD_CDirector_IsTeamFull = new GlobalForward("L4D_OnIsTeamFull", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_CTerrorGameRules_ClearTeamScores = new GlobalForward("L4D_OnClearTeamScores", ET_Event, Param_Cell); + g_hFWD_CTerrorGameRules_SetCampaignScores = new GlobalForward("L4D_OnSetCampaignScores", ET_Event, Param_CellByRef, Param_CellByRef); if( !g_bLeft4Dead2 ) - g_hForward_RecalculateVersusScore = new GlobalForward("L4D_OnRecalculateVersusScore", ET_Event, Param_Cell); - g_hForward_OnFirstSurvivorLeftSafeArea = new GlobalForward("L4D_OnFirstSurvivorLeftSafeArea", ET_Event, Param_Cell); - g_hForward_GetCrouchTopSpeed = new GlobalForward("L4D_OnGetCrouchTopSpeed", ET_Event, Param_Cell, Param_FloatByRef); - g_hForward_GetRunTopSpeed = new GlobalForward("L4D_OnGetRunTopSpeed", ET_Event, Param_Cell, Param_FloatByRef); - g_hForward_GetWalkTopSpeed = new GlobalForward("L4D_OnGetWalkTopSpeed", ET_Event, Param_Cell, Param_FloatByRef); - g_hForward_GetMissionVSBossSpawning = new GlobalForward("L4D_OnGetMissionVSBossSpawning", ET_Event, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef); - g_hForward_OnReplaceTank = new GlobalForward("L4D_OnReplaceTank", ET_Event, Param_Cell, Param_Cell); - g_hForward_TryOfferingTankBot = new GlobalForward("L4D_OnTryOfferingTankBot", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_CThrowActivate = new GlobalForward("L4D_OnCThrowActivate", ET_Event, Param_Cell); - g_hForward_SelectTankAttackPre = new GlobalForward("L4D2_OnSelectTankAttackPre", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_SelectTankAttack = new GlobalForward("L4D2_OnSelectTankAttack", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_SendInRescueVehicle = new GlobalForward("L4D2_OnSendInRescueVehicle", ET_Event); - g_hForward_EndVersusModeRound = new GlobalForward("L4D2_OnEndVersusModeRound", ET_Event, Param_Cell); - g_hForward_EndVersusModeRoundPost = new GlobalForward("L4D2_OnEndVersusModeRound_Post", ET_Event); - g_hForward_LedgeGrabbed = new GlobalForward("L4D_OnLedgeGrabbed", ET_Event, Param_Cell); - g_hForward_OnRevived = new GlobalForward("L4D2_OnRevived", ET_Event, Param_Cell); - g_hForward_OnPlayerStagger = new GlobalForward("L4D2_OnStagger", ET_Event, Param_Cell, Param_Cell); - g_hForward_ShovedBySurvivor = new GlobalForward("L4D_OnShovedBySurvivor", ET_Event, Param_Cell, Param_Cell, Param_Array); - g_hForward_CTerrorWeapon_OnHit = new GlobalForward("L4D2_OnEntityShoved", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Array, Param_Cell); - g_hForward_OnShovedByPounceLanding = new GlobalForward("L4D2_OnPounceOrLeapStumble", ET_Event, Param_Cell, Param_Cell); - g_hForward_PlayerFling = new GlobalForward("L4D2_OnPlayerFling", ET_Event, Param_Cell, Param_Cell, Param_Array); - g_hForward_FatalFalling = new GlobalForward("L4D_OnFatalFalling", ET_Event, Param_Cell, Param_Cell); - g_hForward_Falling = new GlobalForward("L4D_OnFalling", ET_Event, Param_Cell); - g_hForward_EnterStasis = new GlobalForward("L4D_OnEnterStasis", ET_Event, Param_Cell); - g_hForward_LeaveStasis = new GlobalForward("L4D_OnLeaveStasis", ET_Event, Param_Cell); - g_hForward_InfernoSpread = new GlobalForward("L4D2_OnSpitSpread", ET_Event, Param_Cell, Param_Cell, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef); - g_hForward_OnUseHealingItems = new GlobalForward("L4D2_OnUseHealingItems", ET_Event, Param_Cell); - g_hForward_OnFindScavengeItem = new GlobalForward("L4D2_OnFindScavengeItem", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_OnChooseVictim = new GlobalForward("L4D2_OnChooseVictim", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_OnMaterializeFromGhostPre = new GlobalForward("L4D_OnMaterializeFromGhostPre", ET_Event, Param_Cell); - g_hForward_OnMaterializeFromGhost = new GlobalForward("L4D_OnMaterializeFromGhost", ET_Event, Param_Cell); - g_hForward_OnVomitedUpon = new GlobalForward("L4D_OnVomitedUpon", ET_Event, Param_Cell, Param_CellByRef, Param_CellByRef); - // g_hForward_InfectedShoved = new GlobalForward("L4D_OnInfectedShoved", ET_Event, Param_Cell, Param_Cell); - // g_hForward_OnWaterMove = new GlobalForward("L4D2_OnWaterMove", ET_Event, Param_Cell); - // g_hForward_GetRandomPZSpawnPos = new GlobalForward("L4D_OnGetRandomPZSpawnPosition", ET_Event, Param_CellByRef, Param_CellByRef, Param_CellByRef, Param_Array); + g_hFWD_CTerrorPlayer_RecalculateVersusScore = new GlobalForward("L4D_OnRecalculateVersusScore", ET_Event, Param_Cell); + g_hFWD_CDirector_OnFirstSurvivorLeftSafeArea = new GlobalForward("L4D_OnFirstSurvivorLeftSafeArea", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_GetCrouchTopSpeed = new GlobalForward("L4D_OnGetCrouchTopSpeed", ET_Event, Param_Cell, Param_FloatByRef); + g_hFWD_CTerrorPlayer_GetRunTopSpeed = new GlobalForward("L4D_OnGetRunTopSpeed", ET_Event, Param_Cell, Param_FloatByRef); + g_hFWD_CTerrorPlayer_GetWalkTopSpeed = new GlobalForward("L4D_OnGetWalkTopSpeed", ET_Event, Param_Cell, Param_FloatByRef); + g_hFWD_GetMissionVSBossSpawning = new GlobalForward("L4D_OnGetMissionVSBossSpawning", ET_Event, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef); + g_hFWD_ZombieManager_ReplaceTank = new GlobalForward("L4D_OnReplaceTank", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTankClaw_DoSwing_Pre = new GlobalForward("L4D_TankClaw_DoSwing_Pre", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTankClaw_DoSwing_Post = new GlobalForward("L4D_TankClaw_DoSwing_Post", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTankClaw_GroundPound_Pre = new GlobalForward("L4D_TankClaw_GroundPound_Pre", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTankClaw_GroundPound_Post = new GlobalForward("L4D_TankClaw_GroundPound_Post", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTankClaw_OnPlayerHit_Pre = new GlobalForward("L4D_TankClaw_OnPlayerHit_Pre", ET_Event, Param_Cell, Param_Cell, Param_Cell); + g_hFWD_CTankClaw_OnPlayerHit_Post = new GlobalForward("L4D_TankClaw_OnPlayerHit_Post", ET_Event, Param_Cell, Param_Cell, Param_Cell); + g_hFWD_CTankRock_Detonate = new GlobalForward("L4D_TankRock_OnDetonate", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTankRock_OnRelease = new GlobalForward("L4D_TankRock_OnRelease", ET_Event, Param_Cell, Param_Cell, Param_Array, Param_Array, Param_Array, Param_Array); + g_hFWD_CDirector_TryOfferingTankBot = new GlobalForward("L4D_OnTryOfferingTankBot", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_CThrow_ActivateAbililty = new GlobalForward("L4D_OnCThrowActivate", ET_Event, Param_Cell); + g_hFWD_CBaseAnimating_SelectWeightedSequence_Pre = new GlobalForward("L4D2_OnSelectTankAttackPre", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_CBaseAnimating_SelectWeightedSequence_Post = new GlobalForward("L4D2_OnSelectTankAttack", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_CDirectorScriptedEventManager_SendInRescueVehicle = new GlobalForward("L4D2_OnSendInRescueVehicle", ET_Event); + g_hFWD_CDirectorVersusMode_EndVersusModeRound_Pre = new GlobalForward("L4D2_OnEndVersusModeRound", ET_Event, Param_Cell); + g_hFWD_CDirectorVersusMode_EndVersusModeRound_Post = new GlobalForward("L4D2_OnEndVersusModeRound_Post", ET_Event); + g_hFWD_CTerrorPlayer_OnLedgeGrabbed = new GlobalForward("L4D_OnLedgeGrabbed", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_OnRevived_Post = new GlobalForward("L4D2_OnRevived", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_OnStaggered = new GlobalForward("L4D2_OnStagger", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTerrorPlayer_OnShovedBySurvivor = new GlobalForward("L4D_OnShovedBySurvivor", ET_Event, Param_Cell, Param_Cell, Param_Array); + g_hFWD_CTerrorWeapon_OnHit = new GlobalForward("L4D2_OnEntityShoved", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_Array, Param_Cell); + g_hFWD_CTerrorPlayer_OnShovedByPounceLanding = new GlobalForward("L4D2_OnPounceOrLeapStumble", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTerrorPlayer_Fling = new GlobalForward("L4D2_OnPlayerFling", ET_Event, Param_Cell, Param_Cell, Param_Array); + g_hFWD_CDeathFallCamera_Enable = new GlobalForward("L4D_OnFatalFalling", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTerrorPlayer_OnFalling_Post = new GlobalForward("L4D_OnFalling", ET_Event, Param_Cell); + g_hFWD_Tank_EnterStasis_Post = new GlobalForward("L4D_OnEnterStasis", ET_Event, Param_Cell); + g_hFWD_Tank_LeaveStasis_Post = new GlobalForward("L4D_OnLeaveStasis", ET_Event, Param_Cell); + g_hFWD_CInferno_Spread = new GlobalForward("L4D2_OnSpitSpread", ET_Event, Param_Cell, Param_Cell, Param_FloatByRef, Param_FloatByRef, Param_FloatByRef); + g_hFWD_SurvivorBot_UseHealingItems = new GlobalForward("L4D2_OnUseHealingItems", ET_Event, Param_Cell); + g_hFWD_SurvivorBot_FindScavengeItem_Post = new GlobalForward("L4D2_OnFindScavengeItem", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_BossZombiePlayerBot_ChooseVictim_Post = new GlobalForward("L4D2_OnChooseVictim", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_CTerrorPlayer_MaterializeFromGhost_Pre = new GlobalForward("L4D_OnMaterializeFromGhostPre", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_MaterializeFromGhost_Post = new GlobalForward("L4D_OnMaterializeFromGhost", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_OnVomitedUpon = new GlobalForward("L4D_OnVomitedUpon", ET_Event, Param_Cell, Param_CellByRef, Param_CellByRef); + g_hFWD_CPipeBombProjectile_Create_Pre = new GlobalForward("L4D_PipeBombProjectile_Pre", ET_Event, Param_Cell, Param_Array, Param_Array, Param_Array, Param_Array); + g_hFWD_CPipeBombProjectile_Create_Post = new GlobalForward("L4D_PipeBombProjectile_Post", ET_Event, Param_Cell, Param_Cell, Param_Array, Param_Array, Param_Array, Param_Array); + g_hFWD_CTerrorPlayer_Extinguish = new GlobalForward("L4D_PlayerExtinguish", ET_Event, Param_Cell); + g_hFWD_CTerrorPlayer_OnPouncedOnSurvivor = new GlobalForward("L4D_OnPouncedOnSurvivor", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTerrorPlayer_GrabVictimWithTongue = new GlobalForward("L4D_OnGrabWithTongue", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CBreakableProp_Break_Post = new GlobalForward("L4D_CBreakableProp_Break", ET_Event, Param_Cell, Param_Cell); + // g_hFWD_GetRandomPZSpawnPos = new GlobalForward("L4D_OnGetRandomPZSpawnPosition", ET_Event, Param_CellByRef, Param_CellByRef, Param_CellByRef, Param_Array); + // g_hFWD_InfectedShoved = new GlobalForward("L4D_OnInfectedShoved", ET_Event, Param_Cell, Param_Cell); + // g_hFWD_OnWaterMove = new GlobalForward("L4D2_OnWaterMove", ET_Event, Param_Cell); if( g_bLeft4Dead2 ) { - g_hForward_OnHitByVomitJar = new GlobalForward("L4D2_OnHitByVomitJar", ET_Event, Param_Cell, Param_CellByRef); - g_hForward_SpawnWitchBride = new GlobalForward("L4D2_OnSpawnWitchBride", ET_Event, Param_Array, Param_Array); - g_hForward_GetScriptValueInt = new GlobalForward("L4D_OnGetScriptValueInt", ET_Event, Param_String, Param_CellByRef); - g_hForward_GetScriptValueFloat = new GlobalForward("L4D_OnGetScriptValueFloat", ET_Event, Param_String, Param_FloatByRef); - g_hForward_GetScriptValueString = new GlobalForward("L4D_OnGetScriptValueString", ET_Event, Param_String, Param_String, Param_String); - g_hForward_HasConfigurableDifficulty = new GlobalForward("L4D_OnHasConfigurableDifficulty", ET_Event, Param_CellByRef); - g_hForward_GetSurvivorSet = new GlobalForward("L4D_OnGetSurvivorSet", ET_Event, Param_CellByRef); - g_hForward_FastGetSurvivorSet = new GlobalForward("L4D_OnFastGetSurvivorSet", ET_Event, Param_CellByRef); - g_hForward_StartMeleeSwing = new GlobalForward("L4D_OnStartMeleeSwing", ET_Event, Param_Cell, Param_Cell); - g_hForward_ChangeFinaleStage = new GlobalForward("L4D2_OnChangeFinaleStage", ET_Event, Param_CellByRef, Param_String); - g_hForward_AddonsDisabler = new GlobalForward("L4D2_OnClientDisableAddons", ET_Event, Param_String); + g_hFWD_CTerrorPlayer_OnLeptOnSurvivor = new GlobalForward("L4D2_OnJockeyRide", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CTerrorPlayer_OnStartCarryingVictim = new GlobalForward("L4D2_OnStartCarryingVictim", ET_Event, Param_Cell, Param_Cell); + g_hFWD_CGasCanEvent_Killed = new GlobalForward("L4D2_CGasCan_EventKilled", ET_Event, Param_Cell, Param_Cell, Param_Cell); + g_hFWD_CGasCan_OnActionComplete = new GlobalForward("L4D2_CGasCan_ActionComplete", ET_Event, Param_Cell, Param_Cell, Param_Cell); + g_hFWD_CInsectSwarm_CanHarm = new GlobalForward("L4D2_CInsectSwarm_CanHarm", ET_Event, Param_Cell, Param_Cell, Param_Cell); + g_hFWD_CTerrorPlayer_OnHitByVomitJar = new GlobalForward("L4D2_OnHitByVomitJar", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_ZombieManager_SpawnWitchBride = new GlobalForward("L4D2_OnSpawnWitchBride", ET_Event, Param_Array, Param_Array); + g_hFWD_CDirector_GetScriptValueInt = new GlobalForward("L4D_OnGetScriptValueInt", ET_Event, Param_String, Param_CellByRef); + g_hFWD_CDirector_GetScriptValueFloat = new GlobalForward("L4D_OnGetScriptValueFloat", ET_Event, Param_String, Param_FloatByRef); + g_hFWD_CDirector_GetScriptValueString = new GlobalForward("L4D_OnGetScriptValueString", ET_Event, Param_String, Param_String, Param_String); + g_hFWD_CTerrorGameRules_HasConfigurableDifficultySetting = new GlobalForward("L4D_OnHasConfigurableDifficulty", ET_Event, Param_CellByRef); + g_hFWD_CTerrorGameRules_GetSurvivorSet = new GlobalForward("L4D_OnGetSurvivorSet", ET_Event, Param_CellByRef); + g_hFWD_CTerrorGameRules_FastGetSurvivorSet = new GlobalForward("L4D_OnFastGetSurvivorSet", ET_Event, Param_CellByRef); + g_hFWD_StartMeleeSwing = new GlobalForward("L4D_OnStartMeleeSwing", ET_Event, Param_Cell, Param_Cell); + g_hFWD_GetDamageForVictim = new GlobalForward("L4D2_MeleeGetDamageForVictim", ET_Event, Param_Cell, Param_Cell, Param_Cell, Param_FloatByRef); + g_hFWD_CDirectorScriptedEventManager_ChangeFinaleStage = new GlobalForward("L4D2_OnChangeFinaleStage", ET_Event, Param_CellByRef, Param_String); + g_hFWD_AddonsDisabler = new GlobalForward("L4D2_OnClientDisableAddons", ET_Event, Param_String); } // ==================================================================================================== // NATIVES - // L4D1 = 18 [left4downtown] + 47 [l4d_direct] + 15 [l4d2addresses] + 36 [silvers - mine!] + 4 [anim] = 113 - // L4D2 = 53 [left4downtown] + 61 [l4d_direct] + 26 [l4d2addresses] + 69 [silvers - mine!] + 4 [anim] = 202 + // L4D1 = 24 [left4downtown] + 47 [l4d_direct] + 15 [l4d2addresses] + 37 [silvers - mine!] + 4 [anim] = 119 + // L4D2 = 53 [left4downtown] + 61 [l4d_direct] + 26 [l4d2addresses] + 70 [silvers - mine!] + 4 [anim] = 203 // ==================================================================================================== // ANIMATION HOOK CreateNative("AnimHookEnable", Native_AnimHookEnable); @@ -1076,53 +1234,52 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max // Silvers Natives // ========================= CreateNative("L4D_GetGameModeType", Native_GetGameMode); - CreateNative("L4D2_IsGenericCooperativeMode", Native_IsGenericCooperativeMode); + CreateNative("L4D2_IsGenericCooperativeMode", Native_CTerrorGameRules_IsGenericCooperativeMode); CreateNative("L4D_IsCoopMode", Native_IsCoopMode); CreateNative("L4D2_IsRealismMode", Native_IsRealismMode); CreateNative("L4D_IsSurvivalMode", Native_IsSurvivalMode); CreateNative("L4D2_IsScavengeMode", Native_IsScavengeMode); CreateNative("L4D_IsVersusMode", Native_IsVersusMode); - CreateNative("L4D2_HasConfigurableDifficultySetting", Native_HasConfigurableDifficultySetting); + CreateNative("L4D2_HasConfigurableDifficultySetting", Native_CTerrorGameRules_HasConfigurableDifficultySetting); CreateNative("L4D_GetTempHealth", Native_GetTempHealth); CreateNative("L4D_SetTempHealth", Native_SetTempHealth); CreateNative("L4D_PlayMusic", Native_PlayMusic); CreateNative("L4D_StopMusic", Native_StopMusic); - CreateNative("L4D_Deafen", Native_Deafen); - CreateNative("L4D_Dissolve", Native_Dissolve); - CreateNative("L4D_OnITExpired", Native_OnITExpired); - CreateNative("L4D_AngularVelocity", Native_AngularVelocity); - CreateNative("L4D_GetRandomPZSpawnPosition", Native_GetRandomPZSpawnPosition); - CreateNative("L4D_FindRandomSpot", Native_FindRandomSpot); - CreateNative("L4D_GetNearestNavArea", Native_GetNearestNavArea); - CreateNative("L4D_GetLastKnownArea", Native_GetLastKnownarea); - CreateNative("L4D_HasAnySurvivorLeftSafeArea", Native_HasAnySurvivorLeftSafeArea); - CreateNative("L4D_IsAnySurvivorInStartArea", Native_IsAnySurvivorInStartArea); - CreateNative("L4D_IsAnySurvivorInCheckpoint", Native_IsAnySurvivorInCheckpoint); + CreateNative("L4D_Deafen", Native_CTerrorPlayer_Deafen); + CreateNative("L4D_Dissolve", Native_CEntityDissolve_Create); + CreateNative("L4D_OnITExpired", Native_CTerrorPlayer_OnITExpired); + CreateNative("L4D_AngularVelocity", Native_CBaseEntity_ApplyLocalAngularVelocityImpulse); + CreateNative("L4D_GetRandomPZSpawnPosition", Native_ZombieManager_GetRandomPZSpawnPosition); + CreateNative("L4D_FindRandomSpot", Native_TerrorNavArea_FindRandomSpot); + CreateNative("L4D_GetNearestNavArea", Native_CNavMesh_GetNearestNavArea); + CreateNative("L4D_GetLastKnownArea", Native_CTerrorPlayer_GetLastKnownArea); + CreateNative("L4D_HasAnySurvivorLeftSafeArea", Native_CDirector_HasAnySurvivorLeftSafeArea); + CreateNative("L4D_IsAnySurvivorInStartArea", Native_CDirector_IsAnySurvivorInStartArea); + CreateNative("L4D_IsAnySurvivorInCheckpoint", Native_CDirector_IsAnySurvivorInExitCheckpoint); CreateNative("L4D_IsInFirstCheckpoint", Native_IsInFirstCheckpoint); CreateNative("L4D_IsInLastCheckpoint", Native_IsInLastCheckpoint); - CreateNative("L4D_HasPlayerControlledZombies", Native_HasPlayerControlledZombies); - CreateNative("L4D_PipeBombPrj", Native_PipeBombPrj); - CreateNative("L4D_MolotovPrj", Native_MolotovPrj); - CreateNative("L4D2_VomitJarPrj", Native_VomitJarPrj); - CreateNative("L4D2_GrenadeLauncherPrj", Native_GrenadeLauncher); - - CreateNative("L4D_SetHumanSpec", Native_SetHumanSpec); - CreateNative("L4D_TakeOverBot", Native_TakeOverBot); - CreateNative("L4D_CanBecomeGhost", Native_CanBecomeGhost); - CreateNative("L4D_IsFinaleEscapeInProgress", Native_IsFinaleEscapeInProgress); + CreateNative("L4D_HasPlayerControlledZombies", Native_CTerrorGameRules_HasPlayerControlledZombies); + CreateNative("L4D_PipeBombPrj", Native_CPipeBombProjectile_Create); + CreateNative("L4D_MolotovPrj", Native_CMolotovProjectile_Create); + CreateNative("L4D2_VomitJarPrj", Native_VomitJarProjectile_Create); + CreateNative("L4D2_GrenadeLauncherPrj", Native_CGrenadeLauncher_Projectile_Create); + CreateNative("L4D_SetHumanSpec", Native_SurvivorBot_SetHumanSpectator); + CreateNative("L4D_TakeOverBot", Native_CTerrorPlayer_TakeOverBot); + CreateNative("L4D_CanBecomeGhost", Native_CTerrorPlayer_CanBecomeGhost); + CreateNative("L4D_IsFinaleEscapeInProgress", Native_CDirector_IsFinaleEscapeInProgress); // L4D2 only: - CreateNative("L4D2_AreWanderersAllowed", Native_AreWanderersAllowed); + CreateNative("L4D2_AreWanderersAllowed", Native_CDirector_AreWanderersAllowed); CreateNative("L4D2_ExecVScriptCode", Native_ExecVScriptCode); CreateNative("L4D2_GetVScriptOutput", Native_GetVScriptOutput); - CreateNative("L4D2_SpitterPrj", Native_SpitterPrj); - CreateNative("L4D2_UseAdrenaline", Native_OnAdrenalineUsed); + CreateNative("L4D2_SpitterPrj", Native_CSpitterProjectile_Create); + CreateNative("L4D2_UseAdrenaline", Native_CTerrorPlayer_OnAdrenalineUsed); CreateNative("L4D2_GetCurrentFinaleStage", Native_GetCurrentFinaleStage); - CreateNative("L4D2_ForceNextStage", Native_ForceNextStage); - CreateNative("L4D2_IsTankInPlay", Native_IsTankInPlay); - CreateNative("L4D2_IsReachable", Native_IsReachable); - CreateNative("L4D2_GetFurthestSurvivorFlow", Native_GetFurthestSurvivorFlow); - CreateNative("L4D2_GetScriptValueInt", Native_GetScriptValueInt); + CreateNative("L4D2_ForceNextStage", Native_CDirector_ForceNextStage); + CreateNative("L4D2_IsTankInPlay", Native_CDirector_IsTankInPlay); + CreateNative("L4D2_IsReachable", Native_SurvivorBot_IsReachable); + CreateNative("L4D2_GetFurthestSurvivorFlow", Native_CDirector_GetFurthestSurvivorFlow); + CreateNative("L4D2_GetScriptValueInt", Native_CDirector_GetScriptValueInt); CreateNative("L4D2_NavAreaTravelDistance", Native_NavAreaTravelDistance); CreateNative("L4D2_VScriptWrapper_GetMapNumber", Native_VS_GetMapNumber); @@ -1136,8 +1293,8 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("L4D2_VScriptWrapper_GetSenseFlags", Native_VS_GetSenseFlags); CreateNative("L4D2_VScriptWrapper_NavAreaBuildPath", Native_VS_NavAreaBuildPath); CreateNative("L4D2_VScriptWrapper_NavAreaTravelDistance", Native_VS_NavAreaTravelDistance); - // CreateNative("L4D2_GetScriptValueFloat", Native_GetScriptValueFloat); // Only returns default value provided. - // CreateNative("L4D2_GetScriptValueString", Native_GetScriptValueString); // Not implemented, probably broken too, request if really required. + // CreateNative("L4D2_GetScriptValueFloat", Native_CDirector_GetScriptValueFloat); // Only returns default value provided. + // CreateNative("L4D2_GetScriptValueString", Native_CDirector_GetScriptValueString); // Not implemented, probably broken too, request if really required. @@ -1146,35 +1303,36 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max // ========================= // CreateNative("L4D_GetCampaignScores", Native_GetCampaignScores); // CreateNative("L4D_LobbyIsReserved", Native_LobbyIsReserved); - CreateNative("L4D_LobbyUnreserve", Native_LobbyUnreserve); - CreateNative("L4D_RestartScenarioFromVote", Native_RestartScenarioFromVote); - CreateNative("L4D_IsFirstMapInScenario", Native_IsFirstMapInScenario); - CreateNative("L4D_IsMissionFinalMap", Native_IsMissionFinalMap); - CreateNative("L4D_NotifyNetworkStateChanged", Native_NotifyNetworkStateChanged); - CreateNative("L4D_StaggerPlayer", Native_StaggerPlayer); - CreateNative("L4D2_SendInRescueVehicle", Native_SendInRescueVehicle); - CreateNative("L4D_ReplaceTank", Native_ReplaceTank); - CreateNative("L4D2_SpawnTank", Native_SpawnTank); - CreateNative("L4D2_SpawnSpecial", Native_SpawnSpecial); - CreateNative("L4D2_SpawnWitch", Native_SpawnWitch); + CreateNative("L4D_LobbyUnreserve", Native_CBaseServer_SetReservationCookie); + CreateNative("L4D_RestartScenarioFromVote", Native_CDirector_RestartScenarioFromVote); + CreateNative("L4D_IsFirstMapInScenario", Native_CDirector_IsFirstMapInScenario); + CreateNative("L4D_IsMissionFinalMap", Native_CTerrorGameRules_IsMissionFinalMap); + CreateNative("L4D_NotifyNetworkStateChanged", Native_CGameRulesProxy_NotifyNetworkStateChanged); + CreateNative("L4D_StaggerPlayer", Native_CTerrorPlayer_OnStaggered); + CreateNative("L4D2_SendInRescueVehicle", Native_CDirectorScriptedEventManager_SendInRescueVehicle); + CreateNative("L4D_ReplaceTank", Native_ZombieManager_ReplaceTank); + CreateNative("L4D2_SpawnTank", Native_ZombieManager_SpawnTank); + CreateNative("L4D2_SpawnSpecial", Native_ZombieManager_SpawnSpecial); + CreateNative("L4D2_SpawnWitch", Native_ZombieManager_SpawnWitch); CreateNative("L4D2_GetTankCount", Native_GetTankCount); CreateNative("L4D2_GetWitchCount", Native_GetWitchCount); CreateNative("L4D_GetCurrentChapter", Native_GetCurrentChapter); - CreateNative("L4D_GetMaxChapters", Native_GetMaxChapters); + CreateNative("L4D_GetMaxChapters", Native_CTerrorGameRules_GetNumChaptersForMissionAndMode); CreateNative("L4D_GetVersusMaxCompletionScore", Native_GetVersusMaxCompletionScore); CreateNative("L4D_SetVersusMaxCompletionScore", Native_SetVersusMaxCompletionScore); // L4D2 only: CreateNative("L4D_ScavengeBeginRoundSetupTime", Native_ScavengeBeginRoundSetupTime); - CreateNative("L4D_ResetMobTimer", Native_ResetMobTimer); + CreateNative("L4D_ResetMobTimer", Native_CDirector_ResetMobTimer); CreateNative("L4D_GetPlayerSpawnTime", Native_GetPlayerSpawnTime); - CreateNative("L4D_GetTeamScore", Native_GetTeamScore); + CreateNative("L4D_GetTeamScore", Native_CTerrorGameRules_GetTeamScore); CreateNative("L4D_GetMobSpawnTimerRemaining", Native_GetMobSpawnTimerRemaining); CreateNative("L4D_GetMobSpawnTimerDuration", Native_GetMobSpawnTimerDuration); - CreateNative("L4D2_ChangeFinaleStage", Native_ChangeFinaleStage); - CreateNative("L4D2_SpawnWitchBride", Native_SpawnWitchBride); + CreateNative("L4D2_ChangeFinaleStage", Native_CDirectorScriptedEventManager_ChangeFinaleStage); + CreateNative("L4D2_SpawnWitchBride", Native_ZombieManager_SpawnWitchBride); // l4d2weapons.inc + CreateNative("L4D_GetWeaponID", Native_GetWeaponID); CreateNative("L4D2_IsValidWeapon", Native_IsValidWeapon); CreateNative("L4D2_GetIntWeaponAttribute", Native_GetIntWeaponAttribute); CreateNative("L4D2_GetFloatWeaponAttribute", Native_GetFloatWeaponAttribute); @@ -1291,34 +1449,34 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max // l4d2addresses.txt // ========================= CreateNative("L4D_CTerrorPlayer_OnVomitedUpon", Native_CTerrorPlayer_OnVomitedUpon); - CreateNative("L4D_CancelStagger", Native_CancelStagger); - CreateNative("L4D_RespawnPlayer", Native_RespawnPlayer); - CreateNative("L4D_CreateRescuableSurvivors", Native_CreateRescuableSurvivors); - CreateNative("L4D_ReviveSurvivor", Native_OnRevived); - CreateNative("L4D_GetHighestFlowSurvivor", Native_GetHighestFlowSurvivor); - CreateNative("L4D_GetInfectedFlowDistance", Native_GetInfectedFlowDistance); - CreateNative("L4D_TakeOverZombieBot", Native_TakeOverZombieBot); - CreateNative("L4D_ReplaceWithBot", Native_ReplaceWithBot); - CreateNative("L4D_CullZombie", Native_CullZombie); - CreateNative("L4D_SetClass", Native_SetClass); - CreateNative("L4D_MaterializeFromGhost", Native_MaterializeFromGhost); - CreateNative("L4D_BecomeGhost", Native_BecomeGhost); - CreateNative("L4D_State_Transition", Native_State_Transition); - CreateNative("L4D_RegisterForbiddenTarget", Native_RegisterForbiddenTarget); - CreateNative("L4D_UnRegisterForbiddenTarget", Native_UnRegisterForbiddenTarget); + CreateNative("L4D_CancelStagger", Native_CTerrorPlayer_CancelStagger); + CreateNative("L4D_RespawnPlayer", Native_CTerrorPlayer_RespawnPlayer); + CreateNative("L4D_CreateRescuableSurvivors", Native_CDirector_CreateRescuableSurvivors); + CreateNative("L4D_ReviveSurvivor", Native_CTerrorPlayer_OnRevived); + CreateNative("L4D_GetHighestFlowSurvivor", Native_CDirectorTacticalServices_GetHighestFlowSurvivor); + CreateNative("L4D_GetInfectedFlowDistance", Native_Infected_GetInfectedFlowDistance); + CreateNative("L4D_TakeOverZombieBot", Native_CTerrorPlayer_TakeOverZombieBot); + CreateNative("L4D_ReplaceWithBot", Native_CTerrorPlayer_ReplaceWithBot); + CreateNative("L4D_CullZombie", Native_CTerrorPlayer_CullZombie); + CreateNative("L4D_SetClass", Native_CTerrorPlayer_SetClass); + CreateNative("L4D_MaterializeFromGhost", Native_CTerrorPlayer_MaterializeFromGhost); + CreateNative("L4D_BecomeGhost", Native_CTerrorPlayer_BecomeGhost); + CreateNative("L4D_State_Transition", Native_CCSPlayer_State_Transition); + CreateNative("L4D_RegisterForbiddenTarget", Native_CDirector_RegisterForbiddenTarget); + CreateNative("L4D_UnRegisterForbiddenTarget", Native_CDirector_UnregisterForbiddenTarget); // L4D2 only: CreateNative("L4D2_CTerrorPlayer_OnHitByVomitJar", Native_CTerrorPlayer_OnHitByVomitJar); CreateNative("L4D2_Infected_OnHitByVomitJar", Native_Infected_OnHitByVomitJar); CreateNative("L4D2_CTerrorPlayer_Fling", Native_CTerrorPlayer_Fling); - CreateNative("L4D2_GetVersusCompletionPlayer", Native_GetVersusCompletionPlayer); - CreateNative("L4D2_SwapTeams", Native_SwapTeams); - CreateNative("L4D2_AreTeamsFlipped", Native_AreTeamsFlipped); - CreateNative("L4D2_StartRematchVote", Native_StartRematchVote); - CreateNative("L4D2_FullRestart", Native_FullRestart); - CreateNative("L4D2_HideVersusScoreboard", Native_HideVersusScoreboard); - CreateNative("L4D2_HideScavengeScoreboard", Native_HideScavengeScoreboard); - CreateNative("L4D2_HideScoreboard", Native_HideScoreboard); + CreateNative("L4D2_GetVersusCompletionPlayer", Native_CTerrorGameRules_GetVersusCompletion); + CreateNative("L4D2_SwapTeams", Native_CDirector_SwapTeams); + CreateNative("L4D2_AreTeamsFlipped", Native_CDirector_AreTeamsFlipped); + CreateNative("L4D2_StartRematchVote", Native_CDirector_StartRematchVote); + CreateNative("L4D2_FullRestart", Native_CDirector_FullRestart); + CreateNative("L4D2_HideVersusScoreboard", Native_CDirectorVersusMode_HideScoreboardNonVirtual); + CreateNative("L4D2_HideScavengeScoreboard", Native_CDirectorScavengeMode_HideScoreboardNonVirtual); + CreateNative("L4D2_HideScoreboard", Native_CDirector_HideScoreboard); return APLRes_Success; } @@ -1333,19 +1491,19 @@ public void OnPluginStart() // Animation Hook - g_hActivityList = new ArrayList(ByteCountToCells(64)); + g_hAnimationActivityList = new ArrayList(ByteCountToCells(64)); ParseActivityConfig(); - g_iHookedClients = new ArrayList(); + g_iAnimationHookedClients = new ArrayList(); g_hAnimationCallbackPre = new PrivateForward(ET_Event, Param_Cell, Param_CellByRef); - g_hAnimationCallback = new PrivateForward(ET_Event, Param_Cell, Param_CellByRef); + g_hAnimationCallbackPost = new PrivateForward(ET_Event, Param_Cell, Param_CellByRef); // NULL PTR - METHOD (kept for demonstration) // Null pointer - by Dragokas /* - m_iClrRender = FindSendPropInfo("CBaseEntity", "m_clrRender"); - if( m_iClrRender == -1 ) + g_iOff_m_iClrRender = FindSendPropInfo("CBaseEntity", "m_clrRender"); + if( g_iOff_m_iClrRender == -1 ) { SetFailState("Error: m_clrRender not found."); } @@ -1359,18 +1517,25 @@ public void OnPluginStart() if( !g_bLeft4Dead2 ) { - // UNUSED, UNKNOWN OFFSETS FOR WEAPON DATA - // g_aWeaponIDs.SetValue("weapon_none", 0); - // g_aWeaponIDs.SetValue("weapon_pistol", 1); - // g_aWeaponIDs.SetValue("weapon_smg", 2); - // g_aWeaponIDs.SetValue("weapon_pumpshotgun", 3); - // g_aWeaponIDs.SetValue("weapon_autoshotgun", 4); - // g_aWeaponIDs.SetValue("weapon_rifle", 5); - // g_aWeaponIDs.SetValue("weapon_hunting_rifle", 6); - // g_aWeaponIDs.SetValue("weapon_first_aid_kit", 8); - // g_aWeaponIDs.SetValue("weapon_molotov", 9); - // g_aWeaponIDs.SetValue("weapon_pipe_bomb", 10); - // g_aWeaponIDs.SetValue("weapon_pain_pills", 12); + g_aWeaponIDs.SetValue("weapon_none", 0); + g_aWeaponIDs.SetValue("weapon_pistol", 1); + g_aWeaponIDs.SetValue("weapon_smg", 2); + g_aWeaponIDs.SetValue("weapon_pumpshotgun", 3); + g_aWeaponIDs.SetValue("weapon_autoshotgun", 4); + g_aWeaponIDs.SetValue("weapon_rifle", 5); + g_aWeaponIDs.SetValue("weapon_hunting_rifle", 6); + g_aWeaponIDs.SetValue("weapon_first_aid_kit", 8); + g_aWeaponIDs.SetValue("weapon_molotov", 9); + g_aWeaponIDs.SetValue("weapon_pipe_bomb", 10); + g_aWeaponIDs.SetValue("weapon_pain_pills", 12); + g_aWeaponIDs.SetValue("weapon_gascan", 14); + g_aWeaponIDs.SetValue("weapon_propanetank", 15); + g_aWeaponIDs.SetValue("weapon_oxygentank", 16); + g_aWeaponIDs.SetValue("weapon_tank_claw", 17); + g_aWeaponIDs.SetValue("weapon_hunter_claw", 18); + g_aWeaponIDs.SetValue("weapon_boomer_claw", 19); + g_aWeaponIDs.SetValue("weapon_smoker_claw", 20); + g_aWeaponIDs.SetValue("weapon_ammo_spawn", 29); } else { g_aWeaponIDs.SetValue("weapon_none", 0); g_aWeaponIDs.SetValue("weapon_pistol", 1); @@ -1417,6 +1582,7 @@ public void OnPluginStart() g_aWeaponIDs.SetValue("weapon_smoker_claw", 42); g_aWeaponIDs.SetValue("weapon_spitter_claw", 43); g_aWeaponIDs.SetValue("weapon_jockey_claw", 44); + g_aWeaponIDs.SetValue("weapon_ammo_spawn", 54); g_aMeleePtrs = new ArrayList(2); g_aMeleeIDs = new StringMap(); @@ -1461,14 +1627,25 @@ public void OnPluginStart() AddMultiTargetFilter("@ri", FilterRandomC, "Random Infected", false); AddMultiTargetFilter("@randomtank", FilterRandomD, "Random Tank", false); AddMultiTargetFilter("@rt", FilterRandomD, "Random Tank", false); - AddMultiTargetFilter("@incappedsurvivorbot", FilterRandomE, "Random Incapped Survivor Bot", false); - AddMultiTargetFilter("@isb", FilterRandomE, "Random Incapped Survivor Bot", false); - AddMultiTargetFilter("@survivorbot", FilterRandomF, "Random Survivor Bot", false); - AddMultiTargetFilter("@sb", FilterRandomF, "Random Survivor Bot", false); - AddMultiTargetFilter("@infectedbot", FilterRandomG, "Random Infected Bot", false); - AddMultiTargetFilter("@ib", FilterRandomG, "Random Infected Bot", false); - AddMultiTargetFilter("@tankbot", FilterRandomH, "Random Tank Bot", false); - AddMultiTargetFilter("@tb", FilterRandomH, "Random Tank Bot", false); + AddMultiTargetFilter("@rincappedsurvivorbot", FilterRandomE, "Random Incapped Survivor Bot", false); + AddMultiTargetFilter("@risb", FilterRandomE, "Random Incapped Survivor Bot", false); + AddMultiTargetFilter("@rsurvivorbot", FilterRandomF, "Random Survivor Bot", false); + AddMultiTargetFilter("@rsb", FilterRandomF, "Random Survivor Bot", false); + AddMultiTargetFilter("@rinfectedbot", FilterRandomG, "Random Infected Bot", false); + AddMultiTargetFilter("@rib", FilterRandomG, "Random Infected Bot", false); + AddMultiTargetFilter("@rtankbot", FilterRandomH, "Random Tank Bot", false); + AddMultiTargetFilter("@rtb", FilterRandomH, "Random Tank Bot", false); + + AddMultiTargetFilter("@deads", FilterDeadA, "Dead Survivors (all, bots)", false); + AddMultiTargetFilter("@deadsi", FilterDeadB, "Dead Special Infected (all, bots)", false); + AddMultiTargetFilter("@deadsp", FilterDeadC, "Dead Survivors players (no bots)", false); + AddMultiTargetFilter("@deadsip", FilterDeadD, "Dead Special Infected players (no bots)", false); + AddMultiTargetFilter("@deadsb", FilterDeadE, "Dead Survivors bots (no players)", false); + AddMultiTargetFilter("@deadsib", FilterDeadF, "Dead Special Infected bots (no players)", false); + AddMultiTargetFilter("@sp", FilterPlayA, "Survivors players (no bots)", false); + AddMultiTargetFilter("@sip", FilterPlayB, "Special Infected players (no bots)", false); + AddMultiTargetFilter("@isb", FilterIncapA, "Incapped Survivor Only Bots", false); + AddMultiTargetFilter("@isp", FilterIncapB, "Incapped Survivor Only Players", false); AddMultiTargetFilter("@nick", FilterNick, "Nick", false); AddMultiTargetFilter("@rochelle", FilterRochelle, "Rochelle", false); @@ -1511,17 +1688,18 @@ public void OnPluginStart() if( g_bLeft4Dead2 ) { - g_hCvarVScriptBuffer = CreateConVar("l4d2_vscript_return", "", "Buffer used to return VScript values. Do not use.", FCVAR_DONTRECORD); - g_hCvarAddonsEclipse = CreateConVar("l4d2_addons_eclipse", "-1", "Addons Manager (-1: use addonconfig; 0: disable addons; 1: enable addons.)", FCVAR_NOTIFY); - g_hCvarAddonsEclipse.AddChangeHook(ConVarChanged_Cvars); + g_hCvar_VScriptBuffer = CreateConVar("l4d2_vscript_return", "", "Buffer used to return VScript values. Do not use.", FCVAR_DONTRECORD); + g_hCvar_AddonsEclipse = CreateConVar("l4d2_addons_eclipse", "-1", "Addons Manager (-1: use addonconfig; 0: disable addons; 1: enable addons.)", FCVAR_NOTIFY); + AutoExecConfig(true, "left4dhooks"); + g_hCvar_AddonsEclipse.AddChangeHook(ConVarChanged_Cvars); - g_hPillsHealth = FindConVar("pain_pills_health_value"); + g_hCvar_PillsHealth = FindConVar("pain_pills_health_value"); } - g_hDecayDecay = FindConVar("pain_pills_decay_rate"); - g_hCvarRescueDeadTime = FindConVar("rescue_min_dead_time"); - g_hMPGameMode = FindConVar("mp_gamemode"); - g_hMPGameMode.AddChangeHook(ConVarChanged_Mode); + g_hCvar_PillsDecay = FindConVar("pain_pills_decay_rate"); + g_hCvar_RescueDeadTime = FindConVar("rescue_min_dead_time"); + g_hCvar_MPGameMode = FindConVar("mp_gamemode"); + g_hCvar_MPGameMode.AddChangeHook(ConVarChanged_Mode); @@ -1570,7 +1748,7 @@ public void OnMapEnd() g_iMaxChapters = 0; // Reset hooks - g_iHookedClients.Clear(); + g_iAnimationHookedClients.Clear(); // Remove all hooked functions from private forward Handle hIter = GetPluginIterator(); @@ -1581,7 +1759,7 @@ public void OnMapEnd() { hPlug = ReadPlugin(hIter); g_hAnimationCallbackPre.RemoveAllFunctions(hPlug); - g_hAnimationCallback.RemoveAllFunctions(hPlug); + g_hAnimationCallbackPost.RemoveAllFunctions(hPlug); } delete hIter; @@ -1602,14 +1780,15 @@ public int Native_AnimHookEnable(Handle plugin, int numParams) if( g_aDetoursHooked.Get(g_iAnimationDetourIndex) == 0 ) { Handle hDetour = g_aDetourHandles.Get(g_iAnimationDetourIndex); - DHookEnableDetour(hDetour, false, SelectTankAttackPre); - DHookEnableDetour(hDetour, true, SelectTankAttack); + DHookEnableDetour(hDetour, false, DTR_CBaseAnimating_SelectWeightedSequence_Pre); + DHookEnableDetour(hDetour, true, DTR_CBaseAnimating_SelectWeightedSequence_Post); } // Add callback if( GetNativeFunction(2) != INVALID_FUNCTION ) g_hAnimationCallbackPre.AddFunction(plugin, GetNativeFunction(2)); - if( GetNativeFunction(3) != INVALID_FUNCTION ) g_hAnimationCallback.AddFunction(plugin, GetNativeFunction(3)); - g_iHookedClients.Push(GetClientUserId(client)); + if( GetNativeFunction(3) != INVALID_FUNCTION ) g_hAnimationCallbackPost.AddFunction(plugin, GetNativeFunction(3)); + g_iAnimationHookedClients.Push(GetClientUserId(client)); + return true; } @@ -1617,7 +1796,7 @@ public int Native_AnimHookDisable(Handle plugin, int numParams) { // Remove callback if( GetNativeFunction(2) != INVALID_FUNCTION ) g_hAnimationCallbackPre.RemoveFunction(plugin, GetNativeFunction(2)); - if( GetNativeFunction(3) != INVALID_FUNCTION ) g_hAnimationCallback.RemoveFunction(plugin, GetNativeFunction(3)); + if( GetNativeFunction(3) != INVALID_FUNCTION ) g_hAnimationCallbackPost.RemoveFunction(plugin, GetNativeFunction(3)); // Validate client int client = GetNativeCell(1); @@ -1625,12 +1804,13 @@ public int Native_AnimHookDisable(Handle plugin, int numParams) client = GetClientUserId(client); // Remove client from checking array - int index = g_iHookedClients.FindValue(client); + int index = g_iAnimationHookedClients.FindValue(client); if( index != -1 ) { - g_iHookedClients.Erase(index); + g_iAnimationHookedClients.Erase(index); return true; } + return false; } @@ -1640,7 +1820,7 @@ public int Native_AnimGetActivity(Handle plugin, int numParams) int maxlength = GetNativeCell(3); char[] activity = new char[maxlength]; - if( g_hActivityList.GetString(sequence, activity, maxlength) ) + if( g_hAnimationActivityList.GetString(sequence, activity, maxlength) ) { SetNativeString(2, activity, maxlength); return true; @@ -1657,7 +1837,7 @@ public int Native_AnimGetFromActivity(Handle plugin, int numParams) char[] activity = new char[maxlength]; GetNativeString(1, activity, maxlength); - int sequence = g_hActivityList.FindString(activity); + int sequence = g_hAnimationActivityList.FindString(activity); return sequence; } @@ -1697,7 +1877,7 @@ public SMCResult ColorConfig_NewSection(Handle parser, const char[] section, boo public SMCResult ColorConfig_KeyValue(Handle parser, const char[] key, const char[] value, bool key_quotes, bool value_quotes) { - g_hActivityList.PushString(key); + g_hAnimationActivityList.PushString(key); return SMCParse_Continue; } @@ -1735,17 +1915,17 @@ void GetGameMode() if( g_bLeft4Dead2 ) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_GetGameMode, "GetGameMode"); + ValidateNatives(g_hSDK_CDirector_GetGameModeBase, "CDirector::GetGameModeBase"); - //PrintToServer("#### CALL g_hSDK_Call_GetGameMode"); - SDKCall(g_hSDK_Call_GetGameMode, g_pDirector, sMode, sizeof(sMode)); + //PrintToServer("#### CALL g_hSDK_CDirector_GetGameModeBase"); + SDKCall(g_hSDK_CDirector_GetGameModeBase, g_pDirector, sMode, sizeof(sMode)); if( strcmp(sMode, "coop") == 0 ) g_iCurrentMode = GAMEMODE_COOP; else if( strcmp(sMode, "survival") == 0 ) g_iCurrentMode = GAMEMODE_SURVIVAL; else if( strcmp(sMode, "versus") == 0 ) g_iCurrentMode = GAMEMODE_VERSUS; else if( strcmp(sMode, "scavenge") == 0 ) g_iCurrentMode = GAMEMODE_SCAVENGE; } else { - g_hMPGameMode.GetString(sMode, sizeof(sMode)); + g_hCvar_MPGameMode.GetString(sMode, sizeof(sMode)); if( strcmp(sMode, "coop") == 0 ) g_iCurrentMode = GAMEMODE_COOP; else if( strcmp(sMode, "survival") == 0 ) g_iCurrentMode = GAMEMODE_SURVIVAL; @@ -1759,7 +1939,7 @@ void GetGameMode() { mode = g_iCurrentMode; - Call_StartForward(g_hForward_GameModeChange); + Call_StartForward(g_hFWD_GameModeChange); Call_PushCell(mode); Call_Finish(); } @@ -1770,13 +1950,13 @@ public int Native_GetGameMode(Handle plugin, int numParams) return g_iCurrentMode; } -public int Native_IsGenericCooperativeMode(Handle plugin, int numParams) +public int Native_CTerrorGameRules_IsGenericCooperativeMode(Handle plugin, int numParams) { ValidateAddress(g_pGameRules, "g_pGameRules"); - ValidateNatives(g_hSDK_Call_IsGenericCooperativeMode, "IsGenericCooperativeMode"); + ValidateNatives(g_hSDK_CTerrorGameRules_IsGenericCooperativeMode, "CTerrorGameRules::IsGenericCooperativeMode"); - //PrintToServer("#### CALL g_hSDK_Call_IsGenericCooperativeMode"); - return SDKCall(g_hSDK_Call_IsGenericCooperativeMode, g_pGameRules); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_IsGenericCooperativeMode"); + return SDKCall(g_hSDK_CTerrorGameRules_IsGenericCooperativeMode, g_pGameRules); } public int Native_IsCoopMode(Handle plugin, int numParams) @@ -1787,10 +1967,10 @@ public int Native_IsCoopMode(Handle plugin, int numParams) public int Native_IsRealismMode(Handle plugin, int numParams) { ValidateAddress(g_pGameRules, "g_pGameRules"); - ValidateNatives(g_hSDK_Call_IsRealismMode, "IsRealismMode"); + ValidateNatives(g_hSDK_CTerrorGameRules_IsRealismMode, "CTerrorGameRules::IsRealismMode"); - //PrintToServer("#### CALL g_hSDK_Call_IsRealismMode"); - return SDKCall(g_hSDK_Call_IsRealismMode, g_pGameRules); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_IsRealismMode"); + return SDKCall(g_hSDK_CTerrorGameRules_IsRealismMode, g_pGameRules); } public int Native_IsSurvivalMode(Handle plugin, int numParams) @@ -1839,7 +2019,11 @@ public bool FilterIncapped(const char[] pattern, Handle clients) return true; } + + +// ========================= // Specific survivors +// ========================= void MatchSurvivor(Handle clients, int survivorCharacter) { int type; @@ -1938,7 +2122,11 @@ public bool FilterLouis(const char[] pattern, Handle clients) return true; } + + +// ========================= // Filter all Infected +// ========================= public bool FilterInfected(const char[] pattern, Handle clients) { for( int i = 1; i <= MaxClients; i++ ) @@ -1957,167 +2145,192 @@ public bool FilterInfected(const char[] pattern, Handle clients) } -// Filter - Random Incapped Survivors -public bool FilterRandomA(const char[] pattern, Handle clients) + +// ========================= +// Filter - Random Clients +// ========================= +void MatchRandomClient(Handle clients, int index) { ArrayList aList = new ArrayList(); for( int i = 1; i <= MaxClients; i++ ) { - if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && GetEntProp(i, Prop_Send, "m_isIncapacitated", 1) ) + switch( index ) { - aList.Push(i); + case 1: if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && GetEntProp(i, Prop_Send, "m_isIncapacitated", 1) ) aList.Push(i); // Random Incapped Survivors + case 2: if( IsClientInGame(i) && GetClientTeam(i) == 2 ) aList.Push(i); // Random Survivors + case 3: if( IsClientInGame(i) && GetClientTeam(i) == 3 ) aList.Push(i); // Random Infected + case 4: if( IsClientInGame(i) && GetClientTeam(i) == 3 && IsPlayerAlive(i) && GetEntProp(i, Prop_Send, "m_zombieClass") == g_iClassTank ) aList.Push(i); // Random Tank + case 5: if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && IsFakeClient(i) && GetEntProp(i, Prop_Send, "m_isIncapacitated", 1) ) aList.Push(i); // Random Incapped Survivor Bot + case 6: if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && IsFakeClient(i) ) aList.Push(i); // Random Survivor Bot + case 7: if( IsClientInGame(i) && GetClientTeam(i) == 3 && IsPlayerAlive(i) && IsFakeClient(i) ) aList.Push(i); // Random Infected Bot + case 8: if( IsClientInGame(i) && GetClientTeam(i) == 3 && IsPlayerAlive(i) && IsFakeClient(i) && GetEntProp(i, Prop_Send, "m_zombieClass") == g_iClassTank ) aList.Push(i); // Random Tank Bot } } PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); delete aList; +} +public bool FilterRandomA(const char[] pattern, Handle clients) +{ + MatchRandomClient(clients, 1); return true; } -// Filter - Random Survivors public bool FilterRandomB(const char[] pattern, Handle clients) { - ArrayList aList = new ArrayList(); - - for( int i = 1; i <= MaxClients; i++ ) - { - if( IsClientInGame(i) && GetClientTeam(i) == 2 ) - { - aList.Push(i); - } - } - - PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); - - delete aList; - + MatchRandomClient(clients, 2); return true; } -// Filter - Random Infected public bool FilterRandomC(const char[] pattern, Handle clients) { - ArrayList aList = new ArrayList(); - - for( int i = 1; i <= MaxClients; i++ ) - { - if( IsClientInGame(i) && GetClientTeam(i) == 3 ) - { - aList.Push(i); - } - } - - PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); - - delete aList; - + MatchRandomClient(clients, 3); return true; } -// Filter - Random Tank public bool FilterRandomD(const char[] pattern, Handle clients) { - ArrayList aList = new ArrayList(); + MatchRandomClient(clients, 4); + return true; +} - for( int i = 1; i <= MaxClients; i++ ) - { - if( IsClientInGame(i) && GetClientTeam(i) == 3 && IsPlayerAlive(i) && GetEntProp(i, Prop_Send, "m_zombieClass") == g_iClassTank ) - { - aList.Push(i); - } - } +public bool FilterRandomE(const char[] pattern, Handle clients) +{ + MatchRandomClient(clients, 5); + return true; +} - PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); +public bool FilterRandomF(const char[] pattern, Handle clients) +{ + MatchRandomClient(clients, 6); + return true; +} - delete aList; +public bool FilterRandomG(const char[] pattern, Handle clients) +{ + MatchRandomClient(clients, 7); + return true; +} +public bool FilterRandomH(const char[] pattern, Handle clients) +{ + MatchRandomClient(clients, 8); return true; } -// Filter - Random Incapped Survivor Bot -public bool FilterRandomE(const char[] pattern, Handle clients) + + +// ========================= +// Various matches +// ========================= +void MatchVariousClients(Handle clients, int index) { ArrayList aList = new ArrayList(); for( int i = 1; i <= MaxClients; i++ ) { - if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && IsFakeClient(i) && GetEntProp(i, Prop_Send, "m_isIncapacitated", 1) ) + if( IsClientInGame(i) ) { - aList.Push(i); + switch( index ) + { + case 1: if( !IsPlayerAlive(i) && GetClientTeam(i) == 2 ) aList.Push(i); // "Dead Survivors (all, bots)" + case 2: if( !IsPlayerAlive(i) && GetClientTeam(i) == 3 ) aList.Push(i); // "Dead Special Infected (all, bots)" + case 3: if( !IsPlayerAlive(i) && GetClientTeam(i) == 2 && !IsFakeClient(i) ) aList.Push(i); // "Dead Survivors players (no bots)" + case 4: if( !IsPlayerAlive(i) && GetClientTeam(i) == 3 && !IsFakeClient(i) ) aList.Push(i); // "Dead Special Infected players (no bots)" + case 5: if( !IsPlayerAlive(i) && GetClientTeam(i) == 2 && IsFakeClient(i) ) aList.Push(i); // "Dead Survivors bots (no players)" + case 6: if( !IsPlayerAlive(i) && GetClientTeam(i) == 3 && IsFakeClient(i) ) aList.Push(i); // "Dead Special Infected bots (no players)" + case 7: if( GetClientTeam(i) == 2 && !IsFakeClient(i) ) aList.Push(i); // "Survivors players (no bots)" + case 8: if( GetClientTeam(i) == 3 && !IsFakeClient(i) ) aList.Push(i); // "Special Infected players (no bots)" + case 9: if( GetClientTeam(i) == 2 && IsFakeClient(i) && GetEntProp(i, Prop_Send, "m_isIncapacitated", 1) ) aList.Push(i); // "Incapped Survivor Only Bots" + case 10: if( GetClientTeam(i) == 2 && !IsFakeClient(i) && GetEntProp(i, Prop_Send, "m_isIncapacitated", 1) ) aList.Push(i); // "Incapped Survivor Only Players" + } } } PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); delete aList; +} +public bool FilterDeadA(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 1); return true; } -// Filter - Random Survivor Bot -public bool FilterRandomF(const char[] pattern, Handle clients) +public bool FilterDeadB(const char[] pattern, Handle clients) { - ArrayList aList = new ArrayList(); - - for( int i = 1; i <= MaxClients; i++ ) - { - if( IsClientInGame(i) && GetClientTeam(i) == 2 && IsPlayerAlive(i) && IsFakeClient(i) ) - { - aList.Push(i); - } - } - - PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); + MatchVariousClients(clients, 2); + return true; +} - delete aList; +public bool FilterDeadC(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 3); + return true; +} +public bool FilterDeadD(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 4); return true; } -// Filter - Random Infected Bot -public bool FilterRandomG(const char[] pattern, Handle clients) +public bool FilterDeadE(const char[] pattern, Handle clients) { - ArrayList aList = new ArrayList(); + MatchVariousClients(clients, 5); + return true; +} - for( int i = 1; i <= MaxClients; i++ ) - { - if( IsClientInGame(i) && GetClientTeam(i) == 3 && IsPlayerAlive(i) && IsFakeClient(i) ) - { - aList.Push(i); - } - } +public bool FilterDeadF(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 6); + return true; +} - PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); +public bool FilterPlayA(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 7); + return true; +} - delete aList; +public bool FilterPlayB(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 8); + return true; +} +public bool FilterIncapA(const char[] pattern, Handle clients) +{ + MatchVariousClients(clients, 9); return true; } -// Filter - Random Tank Bot -public bool FilterRandomH(const char[] pattern, Handle clients) +public bool FilterIncapB(const char[] pattern, Handle clients) { - ArrayList aList = new ArrayList(); + MatchVariousClients(clients, 10); + return true; +} + + +// ========================= +// Specific Infected +// ========================= +void MatchZombie(Handle clients, int zombieClass) +{ for( int i = 1; i <= MaxClients; i++ ) { - if( IsClientInGame(i) && GetClientTeam(i) == 3 && IsPlayerAlive(i) && IsFakeClient(i) && GetEntProp(i, Prop_Send, "m_zombieClass") == g_iClassTank ) + if( IsClientInGame(i) && GetClientTeam(i) == 3 && GetEntProp(i, Prop_Send, "m_zombieClass") == zombieClass ) { - aList.Push(i); + PushArrayCell(clients, i); } } - - PushArrayCell(clients, aList.Get(GetRandomInt(0, aList.Length - 1))); - - delete aList; - - return true; } -// Specific Infected public bool FilterSmoker(const char[] pattern, Handle clients) { MatchZombie(clients, 1); @@ -2160,17 +2373,6 @@ public bool FilterTanks(const char[] pattern, Handle clients) return true; } -void MatchZombie(Handle clients, int zombieClass) -{ - for( int i = 1; i <= MaxClients; i++ ) - { - if( IsClientInGame(i) && GetClientTeam(i) == 3 && GetEntProp(i, Prop_Send, "m_zombieClass") == zombieClass ) - { - PushArrayCell(clients, i); - } - } -} - // ==================================================================================================== @@ -2199,14 +2401,25 @@ public void OnPluginEnd() RemoveMultiTargetFilter("@ri", FilterRandomC); RemoveMultiTargetFilter("@randomtank", FilterRandomD); RemoveMultiTargetFilter("@rt", FilterRandomD); - RemoveMultiTargetFilter("@incappedsurvivorbot", FilterRandomE); - RemoveMultiTargetFilter("@isb", FilterRandomE); - RemoveMultiTargetFilter("@survivorbot", FilterRandomF); - RemoveMultiTargetFilter("@sb", FilterRandomF); - RemoveMultiTargetFilter("@infectedbot", FilterRandomG); - RemoveMultiTargetFilter("@ib", FilterRandomG); - RemoveMultiTargetFilter("@tankbot", FilterRandomH); - RemoveMultiTargetFilter("@tb", FilterRandomH); + RemoveMultiTargetFilter("@rincappedsurvivorbot", FilterRandomE); + RemoveMultiTargetFilter("@risb", FilterRandomE); + RemoveMultiTargetFilter("@rsurvivorbot", FilterRandomF); + RemoveMultiTargetFilter("@rsb", FilterRandomF); + RemoveMultiTargetFilter("@rinfectedbot", FilterRandomG); + RemoveMultiTargetFilter("@rib", FilterRandomG); + RemoveMultiTargetFilter("@rtankbot", FilterRandomH); + RemoveMultiTargetFilter("@rtb", FilterRandomH); + + RemoveMultiTargetFilter("@deads", FilterDeadA); + RemoveMultiTargetFilter("@deadsi", FilterDeadB); + RemoveMultiTargetFilter("@deadsp", FilterDeadC); + RemoveMultiTargetFilter("@deadsip", FilterDeadD); + RemoveMultiTargetFilter("@deadsb", FilterDeadE); + RemoveMultiTargetFilter("@deadsib", FilterDeadF); + RemoveMultiTargetFilter("@sp", FilterPlayA); + RemoveMultiTargetFilter("@sip", FilterPlayB); + RemoveMultiTargetFilter("@isb", FilterIncapA); + RemoveMultiTargetFilter("@isp", FilterIncapB); RemoveMultiTargetFilter("@nick", FilterNick); RemoveMultiTargetFilter("@rochelle", FilterRochelle); @@ -2244,7 +2457,7 @@ bool g_bAddonsPatched; public void ConVarChanged_Cvars(Handle convar, const char[] oldValue, const char[] newValue) { - if( g_hCvarAddonsEclipse.IntValue > -1 ) + if( g_hCvar_AddonsEclipse.IntValue > -1 ) AddonsDisabler_Patch(); else AddonsDisabler_Unpatch(); @@ -2256,15 +2469,15 @@ void AddonsDisabler_Patch() if( !g_bAddonsPatched ) { g_bAddonsPatched = true; - AddonsDisabler_Restore[0] = LoadFromAddress(VanillaModeAddress + view_as
    (VanillaModeOffset), NumberType_Int8); - AddonsDisabler_Restore[1] = LoadFromAddress(VanillaModeAddress + view_as
    (VanillaModeOffset + 1), NumberType_Int8); - AddonsDisabler_Restore[2] = LoadFromAddress(VanillaModeAddress + view_as
    (VanillaModeOffset + 2), NumberType_Int8); + AddonsDisabler_Restore[0] = LoadFromAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset), NumberType_Int8); + AddonsDisabler_Restore[1] = LoadFromAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset + 1), NumberType_Int8); + AddonsDisabler_Restore[2] = LoadFromAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset + 2), NumberType_Int8); } //PrintToServer("Addons restore: %02x%02x%02x", AddonsDisabler_Restore[0], AddonsDisabler_Restore[1], AddonsDisabler_Restore[2]); - StoreToAddress(VanillaModeAddress + view_as
    (VanillaModeOffset), 0x0F, NumberType_Int8); - StoreToAddress(VanillaModeAddress + view_as
    (VanillaModeOffset + 1), 0x1F, NumberType_Int8); - StoreToAddress(VanillaModeAddress + view_as
    (VanillaModeOffset + 2), 0x00, NumberType_Int8); + StoreToAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset), 0x0F, NumberType_Int8); + StoreToAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset + 1), 0x1F, NumberType_Int8); + StoreToAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset + 2), 0x00, NumberType_Int8); } void AddonsDisabler_Unpatch() @@ -2272,9 +2485,9 @@ void AddonsDisabler_Unpatch() if( g_bAddonsPatched ) { g_bAddonsPatched = false; - StoreToAddress(VanillaModeAddress + view_as
    (VanillaModeOffset), AddonsDisabler_Restore[0], NumberType_Int8); - StoreToAddress(VanillaModeAddress + view_as
    (VanillaModeOffset + 1), AddonsDisabler_Restore[1], NumberType_Int8); - StoreToAddress(VanillaModeAddress + view_as
    (VanillaModeOffset + 2), AddonsDisabler_Restore[2], NumberType_Int8); + StoreToAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset), AddonsDisabler_Restore[0], NumberType_Int8); + StoreToAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset + 1), AddonsDisabler_Restore[1], NumberType_Int8); + StoreToAddress(g_pVanillaModeAddress + view_as
    (g_iOff_VanillaModeOffset + 2), AddonsDisabler_Restore[2], NumberType_Int8); } } @@ -2283,23 +2496,23 @@ void AddonsDisabler_Unpatch() // ==================================================================================================== // ADDONS DISABLER DETOUR // ==================================================================================================== -public MRESReturn AddonsDisabler(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_AddonsDisabler(int pThis, Handle hReturn, Handle hParams) { // Details on finding offsets can be found here: https://github.com/ProdigySim/left4dhooks/pull/1 // Big thanks to "ProdigySim" for updating for The Last Stand update. #if DEBUG - PrintToServer("##### DTR AddonsDisabler"); + PrintToServer("##### DTR_AddonsDisabler"); #endif - int cvar = g_hCvarAddonsEclipse.IntValue; + int cvar = g_hCvar_AddonsEclipse.IntValue; if( cvar != -1 ) { int ptr = DHookGetParam(hParams, 1); // This is `m_nPlayerSlot` on the `SVC_ServerInfo`. // It represents the client index of the connecting user. - int playerSlot = LoadFromAddress(view_as
    (ptr + g_iAddonEclipse1), NumberType_Int8); + int playerSlot = LoadFromAddress(view_as
    (ptr + g_iOff_AddonEclipse1), NumberType_Int8); // The playerslot is an index into `CBaseServer::m_Clients`, and SourceMod's client entity indexes are just `m_Clients` index plus 1. int client = playerSlot + 1; @@ -2318,13 +2531,13 @@ public MRESReturn AddonsDisabler(int pThis, Handle hReturn, Handle hParams) #endif Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_AddonsDisabler); + Call_StartForward(g_hFWD_AddonsDisabler); Call_PushString(netID); Call_Finish(aResult); // 1 to tell the client it should use "vanilla mode"--no addons. 0 to enable addons. - int bVanillaMode = aResult == Plugin_Handled ? 0 : view_as(!cvar); - StoreToAddress(view_as
    (ptr + g_iAddonEclipse2), bVanillaMode, NumberType_Int8); + int bVanillaMode = aResult == Plugin_Handled ? 0 : view_as(!cvar); + StoreToAddress(view_as
    (ptr + g_iOff_AddonEclipse2), bVanillaMode, NumberType_Int8); #if DEBUG PrintToServer("#### AddonCheck vanillaMode for %d [%s] (%N): %d", client, netID, client, bVanillaMode); @@ -2351,7 +2564,8 @@ public void AP_OnPluginUpdate(int pre) public Action CmdLobby(int client, int args) { - Native_LobbyUnreserve(null, 0); + Native_CBaseServer_SetReservationCookie(null, 0); + return Plugin_Handled; } public Action CmdDetours(int client, int args) @@ -2375,8 +2589,10 @@ void SetupDetours(GameData hGameData = null) { g_aDetoursHooked = new ArrayList(); g_aDetourHandles = new ArrayList(); + g_aUseLastIndex = new ArrayList(); g_aForwardIndex = new ArrayList(); g_aForceDetours = new ArrayList(); + g_aGameDataSigs = new ArrayList(ByteCountToCells(MAX_FWD_LEN)); g_aForwardNames = new ArrayList(ByteCountToCells(MAX_FWD_LEN)); } @@ -2385,87 +2601,119 @@ void SetupDetours(GameData hGameData = null) // Forwards listed here must match forward list in plugin start. - // GameData DHookCallback PRE DHookCallback POST Signature Name Forward Name useLast index forceOn detour - CreateDetour(hGameData, SpawnTank, INVALID_FUNCTION, "SpawnTank", "L4D_OnSpawnTank"); + // GameData DHookCallback PRE DHookCallback POST Signature Name Forward Name useLast index forceOn detour + CreateDetour(hGameData, DTR_ZombieManager_SpawnTank, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnTank", "L4D_OnSpawnTank"); + if( !g_bLeft4Dead2 && g_bLinuxOS ) - CreateDetour(hGameData, SpawnWitchArea, INVALID_FUNCTION, "SpawnWitchArea", "L4D_OnSpawnWitch"); - // CreateDetour(hGameData, SpawnWitchAreaPre, SpawnWitchArea, "SpawnWitchArea", "L4D_OnSpawnWitch"); - CreateDetour(hGameData, SpawnWitch, INVALID_FUNCTION, "SpawnWitch", "L4D_OnSpawnWitch"); - CreateDetour(hGameData, MobRushStart, INVALID_FUNCTION, "OnMobRushStart", "L4D_OnMobRushStart"); - CreateDetour(hGameData, SpawnITMob, INVALID_FUNCTION, "SpawnITMob", "L4D_OnSpawnITMob"); - CreateDetour(hGameData, SpawnMob, INVALID_FUNCTION, "SpawnMob", "L4D_OnSpawnMob"); - CreateDetour(hGameData, EnterGhostStatePre, EnterGhostState, "OnEnterGhostState", "L4D_OnEnterGhostState"); - CreateDetour(hGameData, EnterGhostStatePre, EnterGhostState, "OnEnterGhostState", "L4D_OnEnterGhostStatePre", true); // Different forwards, same detour as above - same index. - CreateDetour(hGameData, IsTeamFullPre, INVALID_FUNCTION, "IsTeamFull", "L4D_OnIsTeamFull"); - CreateDetour(hGameData, ClearTeamScores, INVALID_FUNCTION, "ClearTeamScores", "L4D_OnClearTeamScores"); - CreateDetour(hGameData, SetCampaignScores, INVALID_FUNCTION, "SetCampaignScores", "L4D_OnSetCampaignScores"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnWitch_Area, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnWitch_Area", "L4D_OnSpawnWitch"); + // CreateDetour(hGameData, DTR_ZombieManager_SpawnWitch_AreaPre, DTR_ZombieManager_SpawnWitch_Area, "L4DD::ZombieManager::SpawnWitch_Area", "L4D_OnSpawnWitch"); + + CreateDetour(hGameData, DTR_ZombieManager_SpawnWitch, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnWitch", "L4D_OnSpawnWitch"); + CreateDetour(hGameData, DTR_CDirector_MobRushStart, INVALID_FUNCTION, "L4DD::CDirector::OnMobRushStart", "L4D_OnMobRushStart"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnITMob, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnITMob", "L4D_OnSpawnITMob"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnMob, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnMob", "L4D_OnSpawnMob"); + CreateDetour(hGameData, DTR_CTerrorPlayer_EnterGhostState_Pre, DTR_CTerrorPlayer_EnterGhostState_Post, "L4DD::CTerrorPlayer::OnEnterGhostState", "L4D_OnEnterGhostState"); + CreateDetour(hGameData, DTR_CTerrorPlayer_EnterGhostState_Pre, DTR_CTerrorPlayer_EnterGhostState_Post, "L4DD::CTerrorPlayer::OnEnterGhostState", "L4D_OnEnterGhostStatePre", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CDirector_IsTeamFull, INVALID_FUNCTION, "L4DD::CDirector::IsTeamFull", "L4D_OnIsTeamFull"); + CreateDetour(hGameData, DTR_CTerrorGameRules_ClearTeamScores, INVALID_FUNCTION, "L4DD::CTerrorGameRules::ClearTeamScores", "L4D_OnClearTeamScores"); + CreateDetour(hGameData, DTR_CTerrorGameRules_SetCampaignScores, INVALID_FUNCTION, "L4DD::CTerrorGameRules::SetCampaignScores", "L4D_OnSetCampaignScores"); + if( !g_bLeft4Dead2 ) - CreateDetour(hGameData, RecalculateVersusScore, INVALID_FUNCTION, "RecalculateVersusScore", "L4D_OnRecalculateVersusScore"); - CreateDetour(hGameData, OnFirstSurvivorLeftSafeArea, INVALID_FUNCTION, "OnFirstSurvivorLeftSafeArea", "L4D_OnFirstSurvivorLeftSafeArea"); - CreateDetour(hGameData, GetCrouchTopSpeedPre, GetCrouchTopSpeed, "GetCrouchTopSpeed", "L4D_OnGetCrouchTopSpeed"); - CreateDetour(hGameData, GetRunTopSpeedPre, GetRunTopSpeed, "GetRunTopSpeed", "L4D_OnGetRunTopSpeed"); - CreateDetour(hGameData, GetWalkTopSpeedPre, GetWalkTopSpeed, "GetWalkTopSpeed", "L4D_OnGetWalkTopSpeed"); - CreateDetour(hGameData, GetMissionVSBoss, INVALID_FUNCTION, "GetMissionVersusBossSpawning", "L4D_OnGetMissionVSBossSpawning"); - CreateDetour(hGameData, OnReplaceTank, INVALID_FUNCTION, "ReplaceTank", "L4D_OnReplaceTank"); - if( !g_bLeft4Dead2 && g_bLinuxOS ) - CreateDetour(hGameData, TryOfferingTankBot, INVALID_FUNCTION, "TryOfferingTankBot_Clone", "L4D_OnTryOfferingTankBot"); - else - CreateDetour(hGameData, TryOfferingTankBot, INVALID_FUNCTION, "TryOfferingTankBot", "L4D_OnTryOfferingTankBot"); - CreateDetour(hGameData, CThrowActivate, INVALID_FUNCTION, "CThrowActivate", "L4D_OnCThrowActivate"); + CreateDetour(hGameData, DTR_CTerrorPlayer_RecalculateVersusScore, INVALID_FUNCTION, "L4DD::CTerrorPlayer::RecalculateVersusScore", "L4D_OnRecalculateVersusScore"); + + CreateDetour(hGameData, DTR_CDirector_OnFirstSurvivorLeftSafeArea, INVALID_FUNCTION, "L4DD::CDirector::OnFirstSurvivorLeftSafeArea", "L4D_OnFirstSurvivorLeftSafeArea"); + CreateDetour(hGameData, DTR_CTerrorPlayer_GetCrouchTopSpeed_Pre, DTR_CTerrorPlayer_GetCrouchTopSpeed_Post, "L4DD::CTerrorPlayer::GetCrouchTopSpeed", "L4D_OnGetCrouchTopSpeed"); + CreateDetour(hGameData, DTR_CTerrorPlayer_GetRunTopSpeed_Pre, DTR_CTerrorPlayer_GetRunTopSpeed_Post, "L4DD::CTerrorPlayer::GetRunTopSpeed", "L4D_OnGetRunTopSpeed"); + CreateDetour(hGameData, DTR_CTerrorPlayer_GetWalkTopSpeed_Pre, DTR_CTerrorPlayer_GetWalkTopSpeed_Post, "L4DD::CTerrorPlayer::GetWalkTopSpeed", "L4D_OnGetWalkTopSpeed"); + CreateDetour(hGameData, DTR_CDirectorVersusMode_GetMissionVersusBossSpawning, INVALID_FUNCTION, "L4DD::CDirectorVersusMode::GetMissionVersusBossSpawning", "L4D_OnGetMissionVSBossSpawning"); + CreateDetour(hGameData, DTR_ZombieManager_ReplaceTank, INVALID_FUNCTION, "L4DD::ZombieManager::ReplaceTank", "L4D_OnReplaceTank"); + CreateDetour(hGameData, DTR_CTankClaw_DoSwing_Pre, DTR_CTankClaw_DoSwing_Post, "L4DD::CTankClaw::DoSwing", "L4D_TankClaw_DoSwing_Pre"); + CreateDetour(hGameData, DTR_CTankClaw_DoSwing_Pre, DTR_CTankClaw_DoSwing_Post, "L4DD::CTankClaw::DoSwing", "L4D_TankClaw_DoSwing_Post", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CTankClaw_GroundPound_Pre, DTR_CTankClaw_GroundPound_Post, "L4DD::CTankClaw::GroundPound", "L4D_TankClaw_GroundPound_Pre"); + CreateDetour(hGameData, DTR_CTankClaw_GroundPound_Pre, DTR_CTankClaw_GroundPound_Post, "L4DD::CTankClaw::GroundPound", "L4D_TankClaw_GroundPound_Post", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CTankClaw_OnPlayerHit_Pre, DTR_CTankClaw_OnPlayerHit_Post, "L4DD::CTankClaw::OnPlayerHit", "L4D_TankClaw_OnPlayerHit_Pre"); + CreateDetour(hGameData, DTR_CTankClaw_OnPlayerHit_Pre, DTR_CTankClaw_OnPlayerHit_Post, "L4DD::CTankClaw::OnPlayerHit", "L4D_TankClaw_OnPlayerHit_Post", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CTankRock_Detonate, INVALID_FUNCTION, "L4DD::CTankRock::Detonate", "L4D_TankRock_OnDetonate"); + CreateDetour(hGameData, DTR_CTankRock_OnRelease, INVALID_FUNCTION, "L4DD::CTankRock::OnRelease", "L4D_TankRock_OnRelease"); + CreateDetour(hGameData, DTR_CThrow_ActivateAbililty, INVALID_FUNCTION, "L4DD::CThrow::ActivateAbililty", "L4D_OnCThrowActivate"); g_iAnimationDetourIndex = g_iCurrentIndex; // Animation Hook - detour index to enable when required. - CreateDetour(hGameData, SelectTankAttackPre, SelectTankAttack, "SelectTankAttack", "L4D2_OnSelectTankAttack"); // Animation Hook - CreateDetour(hGameData, SelectTankAttackPre, SelectTankAttack, "SelectTankAttack", "L4D2_OnSelectTankAttackPre", true); // Animation Hook - if( !g_bLinuxOS ) // Blocked on Linux in L4D1/L4D2 to prevent crashes. Waiting for DHooks update to support object returns. - CreateDetour(hGameData, SendInRescueVehicle, INVALID_FUNCTION, "SendInRescueVehicle", "L4D2_OnSendInRescueVehicle"); - CreateDetour(hGameData, EndVersusModeRoundPre, EndVersusModeRound, "EndVersusModeRound", "L4D2_OnEndVersusModeRound"); - CreateDetour(hGameData, EndVersusModeRoundPre, EndVersusModeRound, "EndVersusModeRound", "L4D2_OnEndVersusModeRound_Post", true); // Different forwards, same detour as above - same index. - CreateDetour(hGameData, LedgeGrabbed, INVALID_FUNCTION, "OnLedgeGrabbed", "L4D_OnLedgeGrabbed"); - CreateDetour(hGameData, OnRevivedPre, OnRevived, "OnRevived", "L4D2_OnRevived"); - CreateDetour(hGameData, OnPlayerStagger, INVALID_FUNCTION, "OnStaggered", "L4D2_OnStagger"); - CreateDetour(hGameData, ShovedBySurvivor, INVALID_FUNCTION, "OnShovedBySurvivor", "L4D_OnShovedBySurvivor"); - CreateDetour(hGameData, CTerrorWeapon_OnHit, INVALID_FUNCTION, "OnHit", "L4D2_OnEntityShoved"); - CreateDetour(hGameData, OnShovedByPounceLanding, INVALID_FUNCTION, "OnShovedByPounceLanding", "L4D2_OnPounceOrLeapStumble"); - CreateDetour(hGameData, OnFatalFalling, INVALID_FUNCTION, "CDeathFallCamera::Enable", "L4D_OnFatalFalling"); - CreateDetour(hGameData, OnFallingPre, OnFalling, "CTerrorPlayer::OnFalling", "L4D_OnFalling"); - CreateDetour(hGameData, OnEnterStasisPre, OnEnterStasis, "Tank::EnterStasis", "L4D_OnEnterStasis"); - CreateDetour(hGameData, OnLeaveStasisPre, OnLeaveStasis, "Tank::LeaveStasis", "L4D_OnLeaveStasis"); - CreateDetour(hGameData, InfernoSpread, INVALID_FUNCTION, "Spread", "L4D2_OnSpitSpread"); + CreateDetour(hGameData, DTR_CBaseAnimating_SelectWeightedSequence_Pre, DTR_CBaseAnimating_SelectWeightedSequence_Post, "L4DD::CBaseAnimating::SelectWeightedSequence", "L4D2_OnSelectTankAttack"); // Animation Hook + CreateDetour(hGameData, DTR_CBaseAnimating_SelectWeightedSequence_Pre, DTR_CBaseAnimating_SelectWeightedSequence_Post, "L4DD::CBaseAnimating::SelectWeightedSequence", "L4D2_OnSelectTankAttackPre", true); // Animation Hook + CreateDetour(hGameData, DTR_CDirectorVersusMode_EndVersusModeRound_Pre, DTR_CDirectorVersusMode_EndVersusModeRound_Post, "L4DD::CDirectorVersusMode::EndVersusModeRound", "L4D2_OnEndVersusModeRound"); + CreateDetour(hGameData, DTR_CDirectorVersusMode_EndVersusModeRound_Pre, DTR_CDirectorVersusMode_EndVersusModeRound_Post, "L4DD::CDirectorVersusMode::EndVersusModeRound", "L4D2_OnEndVersusModeRound_Post", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CTerrorPlayer_OnLedgeGrabbed, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnLedgeGrabbed", "L4D_OnLedgeGrabbed"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnRevived_Pre, DTR_CTerrorPlayer_OnRevived_Post, "L4DD::CTerrorPlayer::OnRevived", "L4D2_OnRevived"); + if( !g_bLinuxOS ) // Blocked on Linux in L4D1/L4D2 to prevent crashes. Waiting for DHooks update to support object returns. - CreateDetour(hGameData, OnUseHealingItems, INVALID_FUNCTION, "UseHealingItems", "L4D2_OnUseHealingItems"); - CreateDetour(hGameData, OnFindScavengeItemPre, OnFindScavengeItem, "FindScavengeItem", "L4D2_OnFindScavengeItem"); - CreateDetour(hGameData, OnChooseVictimPre, OnChooseVictim, "ChooseVictim", "L4D2_OnChooseVictim"); - CreateDetour(hGameData, OnMaterializeFromGhostPre, OnMaterialize, "OnMaterializeFromGhost", "L4D_OnMaterializeFromGhostPre"); - CreateDetour(hGameData, OnMaterializeFromGhostPre, OnMaterialize, "OnMaterializeFromGhost", "L4D_OnMaterializeFromGhost", true); - CreateDetour(hGameData, OnVomitedUpon, INVALID_FUNCTION, "OnVomitedUpon", "L4D_OnVomitedUpon"); + { + CreateDetour(hGameData, DTR_SurvivorBot_UseHealingItems, INVALID_FUNCTION, "L4DD::SurvivorBot::UseHealingItems", "L4D2_OnUseHealingItems"); + CreateDetour(hGameData, DTR_CDirectorScriptedEventManager_SendInRescueVehicle, INVALID_FUNCTION, "L4DD::CDirectorScriptedEventManager::SendInRescueVehicle", "L4D2_OnSendInRescueVehicle"); + } + + CreateDetour(hGameData, DTR_CDirector_TryOfferingTankBot, INVALID_FUNCTION, "L4DD::CDirector::TryOfferingTankBot", "L4D_OnTryOfferingTankBot"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnShovedBySurvivor, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnShovedBySurvivor", "L4D_OnShovedBySurvivor"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnStaggered, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnStaggered", "L4D2_OnStagger"); + + if( !g_bLeft4Dead2 && g_bLinuxOS ) + { + CreateDetour(hGameData, DTR_CDirector_TryOfferingTankBot_Clone, INVALID_FUNCTION, "L4DD::CDirector::TryOfferingTankBot_Clone", "L4D_OnTryOfferingTankBot"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnShovedBySurvivor_Clone, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnShovedBySurvivor_Clone", "L4D_OnShovedBySurvivor"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnStaggered_Clone, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnStaggered_Clone", "L4D2_OnStagger"); + } + + CreateDetour(hGameData, DTR_CTerrorWeapon_OnHit, INVALID_FUNCTION, "L4DD::CTerrorWeapon::OnHit", "L4D2_OnEntityShoved"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnShovedByPounceLanding, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnShovedByPounceLanding", "L4D2_OnPounceOrLeapStumble"); + CreateDetour(hGameData, DTR_CDeathFallCamera_Enable, INVALID_FUNCTION, "L4DD::CDeathFallCamera::Enable", "L4D_OnFatalFalling"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnFalling_Pre, DTR_CTerrorPlayer_OnFalling_Post, "L4DD::CTerrorPlayer::OnFalling", "L4D_OnFalling"); + CreateDetour(hGameData, DTR_Tank_EnterStasis_Pre, DTR_Tank_EnterStasis_Post, "L4DD::Tank::EnterStasis", "L4D_OnEnterStasis"); + CreateDetour(hGameData, DTR_Tank_LeaveStasis_Pre, DTR_Tank_LeaveStasis_Post, "L4DD::Tank::LeaveStasis", "L4D_OnLeaveStasis"); + CreateDetour(hGameData, DTR_CInferno_Spread, INVALID_FUNCTION, "L4DD::CInferno::Spread", "L4D2_OnSpitSpread"); + CreateDetour(hGameData, DTR_SurvivorBot_FindScavengeItem_Pre, DTR_SurvivorBot_FindScavengeItem_Post, "L4DD::SurvivorBot::FindScavengeItem", "L4D2_OnFindScavengeItem"); + CreateDetour(hGameData, DTR_BossZombiePlayerBot_ChooseVictim_Pre, DTR_BossZombiePlayerBot_ChooseVictim_Post, "L4DD::BossZombiePlayerBot::ChooseVictim", "L4D2_OnChooseVictim"); + CreateDetour(hGameData, DTR_CTerrorPlayer_MaterializeFromGhost_Pre, DTR_CTerrorPlayer_MaterializeFromGhost_Post, "L4DD::CTerrorPlayer::MaterializeFromGhost", "L4D_DTR_CTerrorPlayer_MaterializeFromGhostPre"); + CreateDetour(hGameData, DTR_CTerrorPlayer_MaterializeFromGhost_Pre, DTR_CTerrorPlayer_MaterializeFromGhost_Post, "L4DD::CTerrorPlayer::MaterializeFromGhost", "L4D_OnMaterializeFromGhost", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CPipeBombProjectile_Create_Pre, DTR_CPipeBombProjectile_Create_Post, "L4DD::CPipeBombProjectile::Create", "L4D_PipeBombProjectile_Pre"); + CreateDetour(hGameData, DTR_CPipeBombProjectile_Create_Pre, DTR_CPipeBombProjectile_Create_Post, "L4DD::CPipeBombProjectile::Create", "L4D_PipeBombProjectile_Post", true); // Different forwards, same detour as above - same index. + CreateDetour(hGameData, DTR_CTerrorPlayer_Extinguish, INVALID_FUNCTION, "L4DD::CTerrorPlayer::Extinguish", "L4D_PlayerExtinguish"); + CreateDetour(hGameData, DTR_CBreakableProp_Break_Pre, DTR_CBreakableProp_Break_Post, "L4DD::CBreakableProp::Break", "L4D_CBreakableProp_Break"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnVomitedUpon, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnVomitedUpon", "L4D_OnVomitedUpon"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnPouncedOnSurvivor, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnPouncedOnSurvivor", "L4D_OnPouncedOnSurvivor"); + CreateDetour(hGameData, DTR_CTerrorPlayer_GrabVictimWithTongue, INVALID_FUNCTION, "L4DD::CTerrorPlayer::GrabVictimWithTongue", "L4D_OnGrabWithTongue"); if( !g_bLeft4Dead2 ) { - // Different detours, same forward (SpawnSpecial). - CreateDetour(hGameData, SpawnHunter, INVALID_FUNCTION, "SpawnHunter", "L4D_OnSpawnSpecial"); - CreateDetour(hGameData, SpawnBoomer, INVALID_FUNCTION, "SpawnBoomer", "L4D_OnSpawnSpecial"); - CreateDetour(hGameData, SpawnSmoker, INVALID_FUNCTION, "SpawnSmoker", "L4D_OnSpawnSpecial"); + // Different detours, same forward (L4D_OnSpawnSpecial). + CreateDetour(hGameData, DTR_ZombieManager_SpawnHunter, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnHunter", "L4D_OnSpawnSpecial"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnBoomer, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnBoomer", "L4D_OnSpawnSpecial"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnSmoker, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnSmoker", "L4D_OnSpawnSpecial"); } else { - CreateDetour(hGameData, OnPlayerFling, INVALID_FUNCTION, "CTerrorPlayer::Fling", "L4D2_OnPlayerFling"); - CreateDetour(hGameData, OnHitByVomitJar, INVALID_FUNCTION, "OnHitByVomitJar", "L4D2_OnHitByVomitJar"); - CreateDetour(hGameData, SpawnSpecial, INVALID_FUNCTION, "SpawnSpecial", "L4D_OnSpawnSpecial"); - CreateDetour(hGameData, SpawnWitchBride, INVALID_FUNCTION, "SpawnWitchBride", "L4D_OnSpawnWitchBride"); - CreateDetour(hGameData, GetScriptValueInt, INVALID_FUNCTION, "GetScriptValueInt", "L4D_OnGetScriptValueInt"); - CreateDetour(hGameData, GetScriptValueFloat, INVALID_FUNCTION, "GetScriptValueFloat", "L4D_OnGetScriptValueFloat"); - CreateDetour(hGameData, GetScriptValueString, INVALID_FUNCTION, "GetScriptValueString", "L4D_OnGetScriptValueString"); - CreateDetour(hGameData, HasConfigurableDifficulty, INVALID_FUNCTION, "HasConfigurableDifficulty", "L4D_OnHasConfigurableDifficulty"); - CreateDetour(hGameData, GetSurvivorSet, INVALID_FUNCTION, "GetSurvivorSet", "L4D_OnGetSurvivorSet"); - CreateDetour(hGameData, FastGetSurvivorSet, INVALID_FUNCTION, "FastGetSurvivorSet", "L4D_OnFastGetSurvivorSet"); - CreateDetour(hGameData, StartMeleeSwing, INVALID_FUNCTION, "StartMeleeSwing", "L4D_OnStartMeleeSwing"); - CreateDetour(hGameData, ChangeFinaleStage, INVALID_FUNCTION, "ChangeFinaleStage", "L4D2_OnChangeFinaleStage"); - CreateDetour(hGameData, AddonsDisabler, INVALID_FUNCTION, "FillServerInfo", "L4D2_OnClientDisableAddons", false, true); // Force detour to enable. + CreateDetour(hGameData, DTR_CTerrorPlayer_OnLeptOnSurvivor, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnLeptOnSurvivor", "L4D2_OnJockeyRide"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnStartCarryingVictim, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnStartCarryingVictim", "L4D2_OnStartCarryingVictim"); + CreateDetour(hGameData, DTR_CGasCanEvent_Killed, INVALID_FUNCTION, "L4DD::CGasCan::Event_Killed", "L4D2_CGasCan_EventKilled"); + CreateDetour(hGameData, DTR_CGasCan_OnActionComplete, INVALID_FUNCTION, "L4DD::CGasCan::OnActionComplete", "L4D2_CGasCan_ActionComplete"); + CreateDetour(hGameData, DTR_CInsectSwarm_CanHarm, INVALID_FUNCTION, "L4DD::CInsectSwarm::CanHarm", "L4D2_CInsectSwarm_CanHarm"); + CreateDetour(hGameData, DTR_CTerrorPlayer_Fling, INVALID_FUNCTION, "L4DD::CTerrorPlayer::Fling", "L4D2_OnPlayerFling"); + CreateDetour(hGameData, DTR_CTerrorPlayer_OnHitByVomitJar, INVALID_FUNCTION, "L4DD::CTerrorPlayer::OnHitByVomitJar", "L4D2_OnHitByVomitJar"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnSpecial, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnSpecial", "L4D_OnSpawnSpecial"); + CreateDetour(hGameData, DTR_ZombieManager_SpawnWitchBride, INVALID_FUNCTION, "L4DD::ZombieManager::SpawnWitchBride", "L4D2_OnSpawnWitchBride"); + CreateDetour(hGameData, DTR_CDirector_GetScriptValueInt, INVALID_FUNCTION, "L4DD::CDirector::GetScriptValueInt", "L4D_OnGetScriptValueInt"); + CreateDetour(hGameData, DTR_CDirector_GetScriptValueFloat, INVALID_FUNCTION, "L4DD::CDirector::GetScriptValueFloat", "L4D_OnGetScriptValueFloat"); + CreateDetour(hGameData, DTR_CDirector_GetScriptValueString, INVALID_FUNCTION, "L4DD::CDirector::GetScriptValueString", "L4D_OnGetScriptValueString"); + CreateDetour(hGameData, DTR_CTerrorGameRules_HasConfigurableDifficultySetting, INVALID_FUNCTION, "L4DD::CTerrorGameRules::HasConfigurableDifficultySetting", "L4D_OnHasConfigurableDifficulty"); + CreateDetour(hGameData, DTR_CTerrorGameRules_GetSurvivorSet, INVALID_FUNCTION, "L4DD::CTerrorGameRules::GetSurvivorSet", "L4D_OnGetSurvivorSet"); + CreateDetour(hGameData, DTR_CTerrorGameRules_FastGetSurvivorSet, INVALID_FUNCTION, "L4DD::CTerrorGameRules::FastGetSurvivorSet", "L4D_OnFastGetSurvivorSet"); + CreateDetour(hGameData, DTR_CTerrorMeleeWeapon_StartMeleeSwing, INVALID_FUNCTION, "L4DD::CTerrorMeleeWeapon::StartMeleeSwing", "L4D_OnStartMeleeSwing"); + CreateDetour(hGameData, DTR_CTerrorMeleeWeapon_GetDamageForVictim_Pre, DTR_CTerrorMeleeWeapon_GetDamageForVictim_Post, "L4DD::CTerrorMeleeWeapon::GetDamageForVictim", "L4D2_MeleeGetDamageForVictim"); + CreateDetour(hGameData, DTR_CDirectorScriptedEventManager_ChangeFinaleStage, INVALID_FUNCTION, "L4DD::CDirectorScriptedEventManager::ChangeFinaleStage", "L4D2_OnChangeFinaleStage"); + CreateDetour(hGameData, DTR_AddonsDisabler, INVALID_FUNCTION, "L4DD::CBaseServer::FillServerInfo", "L4D2_OnClientDisableAddons", false, true); // Force detour to enable. } // Deprecated, unused or broken. - // CreateDetour(hGameData, InfectedShoved, INVALID_FUNCTION, "InfectedShoved", "L4D_OnInfectedShoved"); // Missing signature - // CreateDetour(hGameData, OnWaterMovePre, OnWaterMove, "WaterMove", "L4D2_OnWaterMove"); // Does not return water state. Use FL_INWATER instead. - // CreateDetour(hGameData, GetRandomPZSpawnPos, INVALID_FUNCTION, "GetRandomPZSpawnPosition", "L4D_OnGetRandomPZSpawnPosition"); + // CreateDetour(hGameData, DTR_ZombieManager_GetRandomPZSpawnPosition, INVALID_FUNCTION, "L4DD::ZombieManager::GetRandomPZSpawnPosition", "L4D_OnGetRandomPZSpawnPosition"); + // CreateDetour(hGameData, DTR_InfectedShoved_OnShoved, INVALID_FUNCTION, "L4DD::InfectedShoved::OnShoved", "L4D_OnInfectedShoved"); // Missing signature + // CreateDetour(hGameData, DTR_CBasePlayer_WaterMove_Pre, DTR_CBasePlayer_WaterMove_Post, "L4DD::CBasePlayer::WaterMove", "L4D2_OnWaterMove"); // Does not return water state. Use FL_INWATER instead. g_bCreatedDetours = true; } @@ -2478,7 +2726,9 @@ void CreateDetour(GameData hGameData, DHookCallback fCallback, DHookCallback fPo static int index; if( useLast ) index -= 1; + g_aGameDataSigs.PushString(sName); g_aForwardNames.PushString(sForward); + g_aUseLastIndex.Push(useLast); g_aForwardIndex.Push(index++); g_aForceDetours.Push(forceOn); @@ -2486,7 +2736,7 @@ void CreateDetour(GameData hGameData, DHookCallback fCallback, DHookCallback fPo if( !useLast ) { Handle hDetour = DHookCreateFromConf(hGameData, sName); - if( !hDetour ) LogError("Failed to load \"%s\" signature.", sName); + if( !hDetour ) LogError("Failed to load detour \"%s\" signature.", sName); g_aDetoursHooked.Push(0); // Default disabled g_aDetourHandles.Push(hDetour); // Store handle @@ -2495,7 +2745,7 @@ void CreateDetour(GameData hGameData, DHookCallback fCallback, DHookCallback fPo else { // Enable detours - if( !useLast ) + if( !useLast ) // When using the last index, the pre and post detours are already hooked. Pre is always hooked even when only using post, to avoid crashes from dhooks. { int index = g_iCurrentIndex++; int current = g_aDetoursHooked.Get(index); @@ -2511,7 +2761,7 @@ void CreateDetour(GameData hGameData, DHookCallback fCallback, DHookCallback fPo PrintToServer("Enabling detour %d %s", index, sName); #endif - if( fCallback != INVALID_FUNCTION && !DHookEnableDetour(hDetour, false, fCallback) ) LogError("Failed to detour \"%s\".", sName); + if( fCallback != INVALID_FUNCTION && !DHookEnableDetour(hDetour, false, fCallback) ) LogError("Failed to detour pre \"%s\".", sName); if( fPostCallback != INVALID_FUNCTION && !DHookEnableDetour(hDetour, true, fPostCallback) ) LogError("Failed to detour post \"%s\".", sName); } else { g_aDetoursHooked.Set(index, 0); @@ -2519,7 +2769,7 @@ void CreateDetour(GameData hGameData, DHookCallback fCallback, DHookCallback fPo PrintToServer("Disabling detour %d %s", index, sName); #endif - if( fCallback != INVALID_FUNCTION && !DHookDisableDetour(hDetour, false, fCallback) ) LogError("Failed to disable detour \"%s\".", sName); + if( fCallback != INVALID_FUNCTION && !DHookDisableDetour(hDetour, false, fCallback) ) LogError("Failed to disable detour pre \"%s\".", sName); if( fPostCallback != INVALID_FUNCTION && !DHookDisableDetour(hDetour, true, fPostCallback) ) LogError("Failed to disable detour post \"%s\".", sName); } } @@ -2531,12 +2781,18 @@ void CreateDetour(GameData hGameData, DHookCallback fCallback, DHookCallback fPo // Loop through plugins, check which forwards are being used, then hook void CheckRequiredDetours(int client = 0) { + #if DEBUG || !DETOUR_ALL char filename[PLATFORM_MAX_PATH]; + #endif + + bool useLast; + char signatures[MAX_FWD_LEN]; char forwards[MAX_FWD_LEN]; ArrayList aHand = new ArrayList(); Handle hIter = GetPluginIterator(); Handle hPlug; int index; + int count; // Iterate plugins while( MorePlugins(hIter) ) @@ -2550,13 +2806,11 @@ void CheckRequiredDetours(int client = 0) { // Get detour index from forward list index = g_aForwardIndex.Get(i); - - // Get forward name - g_aForwardNames.GetString(i, forwards, sizeof(forwards)); + useLast = g_aUseLastIndex.Get(i); // Prevent checking forwards already known in use // ToDo: When using extra-api.ext, we will check all plugins to gather total number using each forward and store in g_aDetoursHooked - if( aHand.FindValue(index) == -1 ) + if( aHand.FindValue(index) == -1 || useLast ) { // Only if not enabling all detours #if !DETOUR_ALL @@ -2564,53 +2818,73 @@ void CheckRequiredDetours(int client = 0) // Force detour on? if( g_aForceDetours.Get(i) ) { - aHand.Push(index); + // Get forward name + g_aForwardNames.GetString(i, forwards, sizeof(forwards)); + g_aGameDataSigs.GetString(i, signatures, sizeof(signatures)); + + count++; + + if( !useLast ) + aHand.Push(index); #if DEBUG if( client == 0 ) { StopProfiling(g_vProf); g_fProf += GetProfilerTime(g_vProf); - PrintToServer("%40s> %s", "FORCED DETOUR", forwards); + PrintToServer("%2d %36s> %32s (%s)", count, "FORCED DETOUR", forwards, signatures); StartProfiling(g_vProf); } #endif if( client > 0 ) { - ReplyToCommand(client - 1, "%40s> %s", "FORCED DETOUR", forwards); + ReplyToCommand(client - 1, "%2d %36s> %32s (%s)", count, "FORCED DETOUR", forwards, signatures); } } // Check if used - else if( GetFunctionByName(hPlug, forwards) != INVALID_FUNCTION ) - #endif + else { - aHand.Push(index); + // Get forward name + g_aForwardNames.GetString(i, forwards, sizeof(forwards)); - #if DEBUG - if( client == 0 ) + if( GetFunctionByName(hPlug, forwards) != INVALID_FUNCTION ) + #endif { - #if DETOUR_ALL - filename = "THIS_PLUGIN_TEST"; - #else - GetPluginFilename(hPlug, filename, sizeof(filename)); - #endif + count++; - StopProfiling(g_vProf); - g_fProf += GetProfilerTime(g_vProf); - PrintToServer("%40s> %s", filename, forwards); - StartProfiling(g_vProf); - } - #endif + if( !useLast ) + aHand.Push(index); - if( client > 0 ) - { - #if DETOUR_ALL - ReplyToCommand(client - 1, "%40s %s", "FORCED DETOUR", forwards); - #else - GetPluginFilename(hPlug, filename, sizeof(filename)); - ReplyToCommand(client - 1, "%40s> %s", filename, forwards); + #if DEBUG + if( client == 0 ) + { + #if DETOUR_ALL + filename = "THIS_PLUGIN_TEST"; + #else + GetPluginFilename(hPlug, filename, sizeof(filename)); + #endif + + g_aGameDataSigs.GetString(i, signatures, sizeof(signatures)); + + StopProfiling(g_vProf); + g_fProf += GetProfilerTime(g_vProf); + PrintToServer("%2d %36s> %s (%s)", count, filename, forwards, signatures); + StartProfiling(g_vProf); + } #endif + + if( client > 0 ) + { + g_aGameDataSigs.GetString(i, signatures, sizeof(signatures)); + + #if DETOUR_ALL + ReplyToCommand(client - 1, "%2d %36s %32s (%s)", count, "FORCED DETOUR", forwards, signatures); + #else + GetPluginFilename(hPlug, filename, sizeof(filename)); + ReplyToCommand(client - 1, "%2d %36s> %32s (%s)", count, filename, forwards, signatures); + #endif + } } } } @@ -2648,7 +2922,7 @@ void CheckRequiredDetours(int client = 0) // ==================================================================================================== -// LOAD GAMEDATA +// MAP START - INITIALIZE - (LOAD GAMEDATA, DETOURS etc) // ==================================================================================================== public void OnMapStart() { @@ -2656,18 +2930,19 @@ public void OnMapStart() - // Putting this here so g_pGameRules is valid. + // Putting this here so g_pGameRules is valid. Changes for each map. LoadGameDataRules(); - // Enable or Disable detours as required. + // Benchmark #if DEBUG g_vProf = CreateProfiler(); g_fProf = 0.0; StartProfiling(g_vProf); #endif + // Enable or Disable detours as required. CheckRequiredDetours(); #if DEBUG @@ -2680,12 +2955,12 @@ public void OnMapStart() - // Because reload cmd calls this function. + // Because reload command calls this function. We only want these loaded on actual map start. if( !g_bMapStarted ) { g_bMapStarted = true; - GetGameMode(); + GetGameMode(); // Get current game mode // Precache Models, prevent crashing when spawning with SpawnSpecial() for( int i = 0; i < sizeof(g_sModels1); i++ ) @@ -2710,41 +2985,41 @@ public void OnMapStart() bDirectorVars = true; // Variable + default value you're passing, which may be used if the director var is not set. Probably uses cvar instead. Unknown. - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "MaxSpecials", 1); // This doesn't appear to work in the finale. At least for some maps. + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "MaxSpecials", 1); // This doesn't appear to work in the finale. At least for some maps. // These only appear to work in the Finale, or maybe some specific maps. Unknown. - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "SmokerLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "BoomerLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "HunterLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "SpitterLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "JockeyLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "ChargerLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TankLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "DominatorLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "WitchLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "CommonLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "SmokerLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "BoomerLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "HunterLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "SpitterLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "JockeyLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "ChargerLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TankLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "DominatorLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "WitchLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "CommonLimit", 1); // Challenge mode required? - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_MaxSpecials", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_BaseSpecialLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_SmokerLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_BoomerLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_HunterLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_SpitterLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_JockeyLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_ChargerLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_TankLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_DominatorLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_WitchLimit", 1); - SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "cm_CommonLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_MaxSpecials", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_BaseSpecialLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_SmokerLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_BoomerLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_HunterLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_SpitterLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_JockeyLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_ChargerLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_TankLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_DominatorLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_WitchLimit", 1); + SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "cm_CommonLimit", 1); // These also exist, required? - // SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TotalSmokers", 1); - // SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TotalBoomers", 1); - // SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TotalHunters", 1); - // SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TotalSpitter", 1); - // SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TotalJockey", 1); - // SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, "TotalCharger", 1); + // SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TotalSmokers", 1); + // SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TotalBoomers", 1); + // SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TotalHunters", 1); + // SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TotalSpitter", 1); + // SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TotalJockey", 1); + // SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, "TotalCharger", 1); } // Melee weapon IDs - They can change when switching map depending on what melee weapons are enabled @@ -2757,7 +3032,7 @@ public void OnMapStart() g_aMeleeIDs = new StringMap(); int iTable = FindStringTable("meleeweapons"); - if( iTable == INVALID_STRING_TABLE ) + if( iTable == INVALID_STRING_TABLE ) // Default to known IDs { g_aMeleeIDs.SetValue("fireaxe", 0); g_aMeleeIDs.SetValue("frying_pan", 1); @@ -2773,6 +3048,7 @@ public void OnMapStart() g_aMeleeIDs.SetValue("pitchfork", 11); g_aMeleeIDs.SetValue("shovel", 12); } else { + // Get actual IDs int iNum = GetStringTableNumStrings(iTable); char sName[PLATFORM_MAX_PATH]; @@ -2786,6 +3062,11 @@ public void OnMapStart() } } + + +// ==================================================================================================== +// LOAD GAMEDATA - (create natives, load offsets etc) +// ==================================================================================================== void LoadGameDataRules() { char sPath[PLATFORM_MAX_PATH]; @@ -2825,19 +3106,16 @@ void LoadGameData() // SDK CALLS // ==================================================================================================== // INTERNAL - if( g_bLeft4Dead2 ) + StartPrepSDKCall(SDKCall_Static); + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetWeaponInfo") == false ) { - StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetWeaponInfo") == false ) - { - LogError("Failed to find signature: GetWeaponInfo"); - } else { - PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); - PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetWeaponInfo = EndPrepSDKCall(); - if( g_hSDK_Call_GetWeaponInfo == null ) - LogError("Failed to create SDKCall: GetWeaponInfo"); - } + LogError("Failed to find signature: GetWeaponInfo"); + } else { + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + g_hSDK_GetWeaponInfo = EndPrepSDKCall(); + if( g_hSDK_GetWeaponInfo == null ) + LogError("Failed to create SDKCall: GetWeaponInfo"); } StartPrepSDKCall(SDKCall_Static); @@ -2846,8 +3124,8 @@ void LoadGameData() LogError("Failed to find signature: CTerrorGameRules::GetMissionInfo"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetMissionInfo = EndPrepSDKCall(); - if( g_hSDK_Call_GetMissionInfo == null ) + g_hSDK_CTerrorGameRules_GetMissionInfo = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_GetMissionInfo == null ) LogError("Failed to create SDKCall: CTerrorGameRules::GetMissionInfo"); } @@ -2862,8 +3140,8 @@ void LoadGameData() LogError("Failed to find signature: CTerrorPlayer::GetLastKnownArea"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetLastKnownArea = EndPrepSDKCall(); - if( g_hSDK_Call_GetLastKnownArea == null ) + g_hSDK_CTerrorPlayer_GetLastKnownArea = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_GetLastKnownArea == null ) LogError("Failed to create SDKCall: CTerrorPlayer::GetLastKnownArea"); } @@ -2875,8 +3153,8 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_Deafen = EndPrepSDKCall(); - if( g_hSDK_Call_Deafen == null ) + g_hSDK_CTerrorPlayer_Deafen = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_Deafen == null ) LogError("Failed to create SDKCall: CTerrorPlayer::Deafen"); } @@ -2890,8 +3168,8 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_MusicPlay = EndPrepSDKCall(); - if( g_hSDK_Call_MusicPlay == null ) + g_hSDK_Music_Play = EndPrepSDKCall(); + if( g_hSDK_Music_Play == null ) LogError("Failed to create SDKCall: Music::Play"); } @@ -2903,15 +3181,15 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_MusicStop = EndPrepSDKCall(); - if( g_hSDK_Call_MusicStop == null ) + g_hSDK_Music_StopPlaying = EndPrepSDKCall(); + if( g_hSDK_Music_StopPlaying == null ) LogError("Failed to create SDKCall: Music::StopPlaying"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CEntityDissolve_Create") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CEntityDissolve::Create") == false ) { - LogError("Failed to find signature: CEntityDissolve_Create"); + LogError("Failed to find signature: CEntityDissolve::Create"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); @@ -2919,9 +3197,9 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_Dissolve = EndPrepSDKCall(); - if( g_hSDK_Call_Dissolve == null ) - LogError("Failed to create SDKCall: CEntityDissolve_Create"); + g_hSDK_CEntityDissolve_Create = EndPrepSDKCall(); + if( g_hSDK_CEntityDissolve_Create == null ) + LogError("Failed to create SDKCall: CEntityDissolve::Create"); } StartPrepSDKCall(SDKCall_Player); @@ -2929,8 +3207,8 @@ void LoadGameData() { LogError("Failed to find signature: CTerrorPlayer::OnITExpired"); } else { - g_hSDK_Call_OnITExpired = EndPrepSDKCall(); - if( g_hSDK_Call_OnITExpired == null ) + g_hSDK_CTerrorPlayer_OnITExpired = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_OnITExpired == null ) LogError("Failed to create SDKCall: CTerrorPlayer::OnITExpired"); } @@ -2940,30 +3218,30 @@ void LoadGameData() LogError("Failed to find signature: CBaseEntity::ApplyLocalAngularVelocityImpulse"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); - g_hSDK_Call_AngularVelocity = EndPrepSDKCall(); - if( g_hSDK_Call_AngularVelocity == null ) + g_hSDK_CBaseEntity_ApplyLocalAngularVelocityImpulse = EndPrepSDKCall(); + if( g_hSDK_CBaseEntity_ApplyLocalAngularVelocityImpulse == null ) LogError("Failed to create SDKCall: CBaseEntity::ApplyLocalAngularVelocityImpulse"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetRandomPZSpawnPosition") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::GetRandomPZSpawnPosition") == false ) { - LogError("Failed to find signature: GetRandomPZSpawnPosition"); + LogError("Failed to find signature: ZombieManager::GetRandomPZSpawnPosition"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); // zombieClass PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); // Attempts PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWWORLD); // Client PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef, _, VENCODE_FLAG_COPYBACK); // Vector return PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_GetRandomPZSpawnPosition = EndPrepSDKCall(); - if( g_hSDK_Call_GetRandomPZSpawnPosition == null ) - LogError("Failed to create SDKCall: GetRandomPZSpawnPosition"); + g_hSDK_ZombieManager_GetRandomPZSpawnPosition = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_GetRandomPZSpawnPosition == null ) + LogError("Failed to create SDKCall: ZombieManager::GetRandomPZSpawnPosition"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetNearestNavArea") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CNavMesh::GetNearestNavArea") == false ) { - LogError("Failed to find signature: GetNearestNavArea"); + LogError("Failed to find signature: CNavMesh::GetNearestNavArea"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); @@ -2972,81 +3250,81 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetNearestNavArea = EndPrepSDKCall(); - if( g_hSDK_Call_GetNearestNavArea == null ) - LogError("Failed to create SDKCall: GetNearestNavArea"); + g_hSDK_CNavMesh_GetNearestNavArea = EndPrepSDKCall(); + if( g_hSDK_CNavMesh_GetNearestNavArea == null ) + LogError("Failed to create SDKCall: CNavMesh::GetNearestNavArea"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "FindRandomSpot") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "TerrorNavArea::FindRandomSpot") == false ) { - LogError("Failed to find signature: FindRandomSpot"); + LogError("Failed to find signature: TerrorNavArea::FindRandomSpot"); } else { PrepSDKCall_SetReturnInfo(SDKType_Vector, SDKPass_ByValue); - g_hSDK_Call_FindRandomSpot = EndPrepSDKCall(); - if( g_hSDK_Call_FindRandomSpot == null ) - LogError("Failed to create SDKCall: FindRandomSpot"); + g_hSDK_TerrorNavArea_FindRandomSpot = EndPrepSDKCall(); + if( g_hSDK_TerrorNavArea_FindRandomSpot == null ) + LogError("Failed to create SDKCall: TerrorNavArea::FindRandomSpot"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "HasAnySurvivorLeftSafeArea") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::HasAnySurvivorLeftSafeArea") == false ) { - LogError("Failed to find signature: HasAnySurvivorLeftSafeArea"); + LogError("Failed to find signature: CDirector::HasAnySurvivorLeftSafeArea"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_HasAnySurvivorLeftSafeArea = EndPrepSDKCall(); - if( g_hSDK_Call_HasAnySurvivorLeftSafeArea == null ) - LogError("Failed to create SDKCall: HasAnySurvivorLeftSafeArea"); + g_hSDK_CDirector_HasAnySurvivorLeftSafeArea = EndPrepSDKCall(); + if( g_hSDK_CDirector_HasAnySurvivorLeftSafeArea == null ) + LogError("Failed to create SDKCall: CDirector::HasAnySurvivorLeftSafeArea"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "IsAnySurvivorInStartArea") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::IsAnySurvivorInStartArea") == false ) { - LogError("Failed to find signature: IsAnySurvivorInStartArea"); + LogError("Failed to find signature: CDirector::IsAnySurvivorInStartArea"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_IsAnySurvivorInStartArea = EndPrepSDKCall(); - if( g_hSDK_Call_IsAnySurvivorInStartArea == null ) - LogError("Failed to create SDKCall: IsAnySurvivorInStartArea"); + g_hSDK_CDirector_IsAnySurvivorInStartArea = EndPrepSDKCall(); + if( g_hSDK_CDirector_IsAnySurvivorInStartArea == null ) + LogError("Failed to create SDKCall: CDirector::IsAnySurvivorInStartArea"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "IsAnySurvivorInExitCheckpoint") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::IsAnySurvivorInExitCheckpoint") == false ) { - LogError("Failed to find signature: IsAnySurvivorInExitCheckpoint"); + LogError("Failed to find signature: CDirector::IsAnySurvivorInExitCheckpoint"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_IsAnySurvivorInCheckpoint = EndPrepSDKCall(); - if( g_hSDK_Call_IsAnySurvivorInCheckpoint == null ) - LogError("Failed to create SDKCall: IsAnySurvivorInExitCheckpoint"); + g_hSDK_CDirector_IsAnySurvivorInExitCheckpoint = EndPrepSDKCall(); + if( g_hSDK_CDirector_IsAnySurvivorInExitCheckpoint == null ) + LogError("Failed to create SDKCall: CDirector::IsAnySurvivorInExitCheckpoint"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "HasPlayerControlledZombies") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::HasPlayerControlledZombies") == false ) { - LogError("Failed to find signature: HasPlayerControlledZombies"); + LogError("Failed to find signature: CTerrorGameRules::HasPlayerControlledZombies"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_HasPlayerControlledZombies = EndPrepSDKCall(); - if( g_hSDK_Call_HasPlayerControlledZombies == null ) - LogError("Failed to create SDKCall: HasPlayerControlledZombies"); + g_hSDK_CTerrorGameRules_HasPlayerControlledZombies = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_HasPlayerControlledZombies == null ) + LogError("Failed to create SDKCall: CTerrorGameRules::HasPlayerControlledZombies"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CPipeBombProjectile_Create") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CPipeBombProjectile::Create") == false ) { - LogError("Failed to find signature: CPipeBombProjectile_Create"); + LogError("Failed to find signature: CPipeBombProjectile::Create"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); - PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWWORLD); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_PipeBombPrj = EndPrepSDKCall(); - if( g_hSDK_Call_PipeBombPrj == null ) - LogError("Failed to create SDKCall: CPipeBombProjectile_Create"); + g_hSDK_CPipeBombProjectile_Create = EndPrepSDKCall(); + if( g_hSDK_CPipeBombProjectile_Create == null ) + LogError("Failed to create SDKCall: CPipeBombProjectile::Create"); } @@ -3055,10 +3333,9 @@ void LoadGameData() // DYNAMIC SIG SCANS // ========================= - // Load custom gamedata addresses to detour + // Automatically generate addresses from strings inside the custom temp gamedata used for some natives if( !g_bLinuxOS ) { - // AUTOMATICALLY GENERATE DETOURS // Search game memory for specific strings #define MAX_HOOKS 3 int iMaxHooks = g_bLeft4Dead2 ? 3 : 1; @@ -3124,7 +3401,7 @@ void LoadGameData() patchAddr = patches[i]; if( patchAddr ) { - Format(sAddress, sizeof(sAddress), "%X", patchAddr); + FormatEx(sAddress, sizeof(sAddress), "%X", patchAddr); ReverseAddress(sAddress, sHexAddr); // First byte of projectile functions is \x55 || \x8B @@ -3148,7 +3425,7 @@ void LoadGameData() } // Add call X address - StrCat(sAddress, sizeof(sAddress), "\\x68"); // Add "push" byte + StrCat(sAddress, sizeof(sAddress), "\\x68"); // Add "push" byte (this is found in the "Molotov", "VomitJar" and "GrenadeLauncher" functions only) - added to match better although not required StrCat(sAddress, sizeof(sAddress), sHexAddr); @@ -3198,83 +3475,83 @@ void LoadGameData() StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(g_bLinuxOS ? hGameData : hTempGameData, SDKConf_Signature, g_bLinuxOS ? "MolotovProjectile_Create" : "FindAddress_0") == false ) + if( PrepSDKCall_SetFromConf(g_bLinuxOS ? hGameData : hTempGameData, SDKConf_Signature, g_bLinuxOS ? "CMolotovProjectile::Create" : "FindAddress_0") == false ) { - LogError("Failed to find signature: MolotovProjectile_Create"); + LogError("Failed to find signature: CMolotovProjectile::Create"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); - PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWWORLD); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_MolotovPrj = EndPrepSDKCall(); - if( g_hSDK_Call_MolotovPrj == null ) - LogError("Failed to create SDKCall: MolotovProjectile_Create"); + g_hSDK_CMolotovProjectile_Create = EndPrepSDKCall(); + if( g_hSDK_CMolotovProjectile_Create == null ) + LogError("Failed to create SDKCall: CMolotovProjectile::Create"); } if( g_bLeft4Dead2 ) { StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(g_bLinuxOS ? hGameData : hTempGameData, SDKConf_Signature, g_bLinuxOS ? "VomitJarProjectile_Create" : "FindAddress_1") == false ) + if( PrepSDKCall_SetFromConf(g_bLinuxOS ? hGameData : hTempGameData, SDKConf_Signature, g_bLinuxOS ? "VomitJarProjectile::Create" : "FindAddress_1") == false ) { - LogError("Failed to find signature: VomitJarProjectile_Create"); + LogError("Failed to find signature: VomitJarProjectile::Create"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); - PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWWORLD); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_VomitJarPrj = EndPrepSDKCall(); - if( g_hSDK_Call_VomitJarPrj == null ) - LogError("Failed to create SDKCall: VomitJarProjectile_Create"); + g_hSDK_VomitJarProjectile_Create = EndPrepSDKCall(); + if( g_hSDK_VomitJarProjectile_Create == null ) + LogError("Failed to create SDKCall: VomitJarProjectile::Create"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(g_bLinuxOS ? hGameData : hTempGameData, SDKConf_Signature, g_bLinuxOS ? "GrenadeLauncher_Create" : "FindAddress_2") == false ) + if( PrepSDKCall_SetFromConf(g_bLinuxOS ? hGameData : hTempGameData, SDKConf_Signature, g_bLinuxOS ? "CGrenadeLauncher_Projectile::Create" : "FindAddress_2") == false ) { - LogError("Failed to find signature: GrenadeLauncher_Create"); + LogError("Failed to find signature: CGrenadeLauncher_Projectile::Create"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); - PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWWORLD); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_GrenadeLauncher = EndPrepSDKCall(); - if( g_hSDK_Call_GrenadeLauncher == null ) - LogError("Failed to create SDKCall: GrenadeLauncher_Create"); + g_hSDK_CGrenadeLauncher_Projectile_Create = EndPrepSDKCall(); + if( g_hSDK_CGrenadeLauncher_Projectile_Create == null ) + LogError("Failed to create SDKCall: CGrenadeLauncher_Projectile::Create"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CSpitterProjectile_Create") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CSpitterProjectile::Create") == false ) { - LogError("Failed to find signature: CSpitterProjectile_Create"); + LogError("Failed to find signature: CSpitterProjectile::Create"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); - PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer, VDECODE_FLAG_ALLOWWORLD); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpitterPrj = EndPrepSDKCall(); - if( g_hSDK_Call_SpitterPrj == null ) - LogError("Failed to create SDKCall: CSpitterProjectile_Create"); + g_hSDK_CSpitterProjectile_Create = EndPrepSDKCall(); + if( g_hSDK_CSpitterProjectile_Create == null ) + LogError("Failed to create SDKCall: CSpitterProjectile::Create"); } StartPrepSDKCall(SDKCall_GameRules); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "HasConfigurableDifficulty") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::HasConfigurableDifficultySetting") == false ) { - LogError("Failed to find signature: HasConfigurableDifficulty"); + LogError("Failed to find signature: CTerrorGameRules::HasConfigurableDifficultySetting"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_HasConfigurableDifficultySetting = EndPrepSDKCall(); - if( g_hSDK_Call_HasConfigurableDifficultySetting == null ) - LogError("Failed to create SDKCall: HasConfigurableDifficulty"); + g_hSDK_CTerrorGameRules_HasConfigurableDifficultySetting = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_HasConfigurableDifficultySetting == null ) + LogError("Failed to create SDKCall: CTerrorGameRules::HasConfigurableDifficultySetting"); } StartPrepSDKCall(SDKCall_Static); @@ -3286,48 +3563,49 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_NavAreaTravelDistance = EndPrepSDKCall(); - if( g_hSDK_Call_NavAreaTravelDistance == null ) + g_hSDK_NavAreaTravelDistance = EndPrepSDKCall(); + if( g_hSDK_NavAreaTravelDistance == null ) LogError("Failed to create SDKCall: NavAreaTravelDistance"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "OnAdrenalineUsed") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::OnAdrenalineUsed") == false ) { - LogError("Failed to find signature: OnAdrenalineUsed"); + LogError("Failed to find signature: CTerrorPlayer::OnAdrenalineUsed"); } else { PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_OnAdrenalineUsed = EndPrepSDKCall(); - if( g_hSDK_Call_OnAdrenalineUsed == null ) - LogError("Failed to create SDKCall: OnAdrenalineUsed"); + g_hSDK_CTerrorPlayer_OnAdrenalineUsed = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_OnAdrenalineUsed == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::OnAdrenalineUsed"); } + // "ForceNextStage" is now found by getting the call address from another function, instead of trying to match such a small signature, which requires using an offset byte that changes in game updates /* Verify ForceNextStage addresses are equal (B will break in future updates, where A should remain intact) - Address aa = hGameData.GetAddress("ForceNextStageAddress"); - Address bb = hGameData.GetAddress("ForceNextStage"); + Address aa = hGameData.GetAddress("CDirector::ForceNextStage::Address"); + Address bb = hGameData.GetAddress("CDirector::ForceNextStage"); PrintToServer("ForceNextStage: A: %d B: %d", aa, bb); */ StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Address, "ForceNextStageAddress") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Address, "CDirector::ForceNextStage::Address") == false ) { - LogError("Failed to find signature: ForceNextStageAddress"); + LogError("Failed to find signature: CDirector::ForceNextStage::Address"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_ForceNextStage = EndPrepSDKCall(); - if( g_hSDK_Call_ForceNextStage == null ) - LogError("Failed to create SDKCall: ForceNextStageAddress"); + g_hSDK_CDirector_ForceNextStage = EndPrepSDKCall(); + if( g_hSDK_CDirector_ForceNextStage == null ) + LogError("Failed to create SDKCall: CDirector::ForceNextStage::Address"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "IsTankInPlay") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::IsTankInPlay") == false ) { - LogError("Failed to find signature: IsTankInPlay"); + LogError("Failed to find signature: CDirector::IsTankInPlay"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_IsTankInPlay = EndPrepSDKCall(); - if( g_hSDK_Call_IsTankInPlay == null ) - LogError("Failed to create SDKCall: IsTankInPlay"); + g_hSDK_CDirector_IsTankInPlay = EndPrepSDKCall(); + if( g_hSDK_CDirector_IsTankInPlay == null ) + LogError("Failed to create SDKCall: CDirector::IsTankInPlay"); } StartPrepSDKCall(SDKCall_Player); @@ -3337,62 +3615,62 @@ void LoadGameData() } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_IsReachable = EndPrepSDKCall(); - if( g_hSDK_Call_IsReachable == null ) + g_hSDK_SurvivorBot_IsReachable = EndPrepSDKCall(); + if( g_hSDK_SurvivorBot_IsReachable == null ) LogError("Failed to create SDKCall: SurvivorBot::IsReachable"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetFurthestSurvivorFlow") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::GetFurthestSurvivorFlow") == false ) { - LogError("Failed to find signature: GetFurthestSurvivorFlow"); + LogError("Failed to find signature: CDirector::GetFurthestSurvivorFlow"); } else { PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_GetFurthestSurvivorFlow = EndPrepSDKCall(); - if( g_hSDK_Call_GetFurthestSurvivorFlow == null ) - LogError("Failed to create SDKCall: GetFurthestSurvivorFlow"); + g_hSDK_CDirector_GetFurthestSurvivorFlow = EndPrepSDKCall(); + if( g_hSDK_CDirector_GetFurthestSurvivorFlow == null ) + LogError("Failed to create SDKCall: CDirector::GetFurthestSurvivorFlow"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetScriptValueInt") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::GetScriptValueInt") == false ) { - LogError("Failed to find signature: GetScriptValueInt"); + LogError("Failed to find signature: CDirector::GetScriptValueInt"); } else { PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetScriptValueInt = EndPrepSDKCall(); - if( g_hSDK_Call_GetScriptValueInt == null ) - LogError("Failed to create SDKCall: GetScriptValueInt"); + g_hSDK_CDirector_GetScriptValueInt = EndPrepSDKCall(); + if( g_hSDK_CDirector_GetScriptValueInt == null ) + LogError("Failed to create SDKCall: CDirector::GetScriptValueInt"); } /* // Only returns default value provided. StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetScriptValueFloat") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::GetScriptValueFloat") == false ) { - LogError("Failed to find signature: GetScriptValueFloat"); + LogError("Failed to find signature: CDirector::GetScriptValueFloat"); } else { PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_GetScriptValueFloat = EndPrepSDKCall(); - if( g_hSDK_Call_GetScriptValueFloat == null ) - LogError("Failed to create SDKCall: GetScriptValueFloat"); + g_hSDK_CDirector_GetScriptValueFloat = EndPrepSDKCall(); + if( g_hSDK_CDirector_GetScriptValueFloat == null ) + LogError("Failed to create SDKCall: CDirector::GetScriptValueFloat"); } // Not implemented, request if really required. StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetScriptValueString") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::GetScriptValueString") == false ) { - LogError("Failed to find signature: GetScriptValueString"); + LogError("Failed to find signature: CDirector::GetScriptValueString"); } else { PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_String, SDKPass_Pointer); - g_hSDK_Call_GetScriptValueString = EndPrepSDKCall(); - if( g_hSDK_Call_GetScriptValueString == null ) - LogError("Failed to create SDKCall: GetScriptValueString"); + g_hSDK_CDirector_GetScriptValueString = EndPrepSDKCall(); + if( g_hSDK_CDirector_GetScriptValueString == null ) + LogError("Failed to create SDKCall: CDirector::GetScriptValueString"); } */ } @@ -3403,28 +3681,28 @@ void LoadGameData() // MAIN - left4downtown.inc // ========================= StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "RestartScenarioFromVote") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::RestartScenarioFromVote") == false ) { - LogError("Failed to find signature: RestartScenarioFromVote"); + LogError("Failed to find signature: CDirector::RestartScenarioFromVote"); } else { PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_RestartScenarioFromVote = EndPrepSDKCall(); - if( g_hSDK_Call_RestartScenarioFromVote == null ) - LogError("Failed to create SDKCall: RestartScenarioFromVote"); + g_hSDK_CDirector_RestartScenarioFromVote = EndPrepSDKCall(); + if( g_hSDK_CDirector_RestartScenarioFromVote == null ) + LogError("Failed to create SDKCall: CDirector::RestartScenarioFromVote"); } StartPrepSDKCall(SDKCall_GameRules); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetTeamScore") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::GetTeamScore") == false ) { - LogError("Failed to find signature: GetTeamScore"); + LogError("Failed to find signature: CTerrorGameRules::GetTeamScore"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetTeamScore = EndPrepSDKCall(); - if( g_hSDK_Call_GetTeamScore == null ) - LogError("Failed to create SDKCall: GetTeamScore"); + g_hSDK_CTerrorGameRules_GetTeamScore = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_GetTeamScore == null ) + LogError("Failed to create SDKCall: CTerrorGameRules::GetTeamScore"); } if( g_bLeft4Dead2 ) @@ -3433,9 +3711,9 @@ void LoadGameData() } else { StartPrepSDKCall(SDKCall_Static); } - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "IsFirstMapInScenario") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::IsFirstMapInScenario") == false ) { - LogError("Failed to find signature: IsFirstMapInScenario"); + LogError("Failed to find signature: CDirector::IsFirstMapInScenario"); } else { if( !g_bLeft4Dead2 ) { @@ -3444,252 +3722,267 @@ void LoadGameData() } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); } - g_hSDK_Call_IsFirstMapInScenario = EndPrepSDKCall(); - if( g_hSDK_Call_IsFirstMapInScenario == null ) + g_hSDK_CDirector_IsFirstMapInScenario = EndPrepSDKCall(); + if( g_hSDK_CDirector_IsFirstMapInScenario == null ) LogError("Failed to create SDKCall: IsFirstMapInScenario"); } StartPrepSDKCall(SDKCall_GameRules); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "IsMissionFinalMap") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::IsMissionFinalMap") == false ) { - LogError("Failed to find signature: IsMissionFinalMap"); + LogError("Failed to find signature: CTerrorGameRules::IsMissionFinalMap"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_IsMissionFinalMap = EndPrepSDKCall(); - if( g_hSDK_Call_IsMissionFinalMap == null ) - LogError("Failed to create SDKCall: IsMissionFinalMap"); + g_hSDK_CTerrorGameRules_IsMissionFinalMap = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_IsMissionFinalMap == null ) + LogError("Failed to create SDKCall: CTerrorGameRules::IsMissionFinalMap"); } if( !g_bLeft4Dead2 ) { StartPrepSDKCall(SDKCall_Raw); if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "KeyValues::GetString") == false ) - SetFailState("Could not load the \"KeyValues::GetString\" gamedata signature."); - PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); - PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); - PrepSDKCall_SetReturnInfo(SDKType_String, SDKPass_Pointer); - g_hSDK_Call_KV_GetString = EndPrepSDKCall(); - if( g_hSDK_Call_KV_GetString == null ) - SetFailState("Could not prep the \"KeyValues::GetString\" function."); + { + LogError("Could not load the \"KeyValues::GetString\" gamedata signature."); + } else { + PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); + PrepSDKCall_SetReturnInfo(SDKType_String, SDKPass_Pointer); + g_hSDK_KeyValues_GetString = EndPrepSDKCall(); + if( g_hSDK_KeyValues_GetString == null ) + LogError("Could not prep the \"KeyValues::GetString\" function."); + } } if( g_bLeft4Dead2 ) { StartPrepSDKCall(SDKCall_GameRules); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetNumChaptersForMissionAndMode") == false ) - SetFailState("Could not load the \"GetNumChaptersForMissionAndMode\" gamedata signature."); - PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetMaxChapters = EndPrepSDKCall(); - if( g_hSDK_Call_GetMaxChapters == null ) - SetFailState("Could not prep the \"GetNumChaptersForMissionAndMode\" function."); + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::GetNumChaptersForMissionAndMode") == false ) + { + LogError("Could not load the \"CTerrorGameRules::GetNumChaptersForMissionAndMode\" gamedata signature."); + } else { + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + g_hSDK_CTerrorGameRules_GetNumChaptersForMissionAndMode = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_GetNumChaptersForMissionAndMode == null ) + LogError("Could not prep the \"CTerrorGameRules::GetNumChaptersForMissionAndMode\" function."); + } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector_GetGameModeBase") == false ) - SetFailState("Could not load the \"CDirector_GetGameModeBase\" gamedata signature."); - PrepSDKCall_SetReturnInfo(SDKType_String, SDKPass_Pointer); - g_hSDK_Call_GetGameMode = EndPrepSDKCall(); - if( g_hSDK_Call_GetGameMode == null ) - SetFailState("Could not prep the \"CDirector_GetGameModeBase\" function."); + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::GetGameModeBase") == false ) + { + LogError("Could not load the \"CDirector::GetGameModeBase\" gamedata signature."); + } else { + PrepSDKCall_SetReturnInfo(SDKType_String, SDKPass_Pointer); + g_hSDK_CDirector_GetGameModeBase = EndPrepSDKCall(); + if( g_hSDK_CDirector_GetGameModeBase == null ) + LogError("Could not prep the \"CDirector::GetGameModeBase\" function."); + } StartPrepSDKCall(SDKCall_GameRules); if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::IsRealismMode") == false ) - SetFailState("Could not load the \"CTerrorGameRules::IsRealismMode\" gamedata signature."); - PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_IsRealismMode = EndPrepSDKCall(); - if( g_hSDK_Call_IsRealismMode == null ) - SetFailState("Could not prep the \"CTerrorGameRules::IsRealismMode\" function."); + { + LogError("Could not load the \"CTerrorGameRules::IsRealismMode\" gamedata signature."); + } else { + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + g_hSDK_CTerrorGameRules_IsRealismMode = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_IsRealismMode == null ) + LogError("Could not prep the \"CTerrorGameRules::IsRealismMode\" function."); + } StartPrepSDKCall(SDKCall_GameRules); if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::IsGenericCooperativeMode") == false ) - SetFailState("Could not load the \"CTerrorGameRules::IsGenericCooperativeMode\" gamedata signature."); - PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_IsGenericCooperativeMode = EndPrepSDKCall(); - if( g_hSDK_Call_IsGenericCooperativeMode == null ) - SetFailState("Could not prep the \"CTerrorGameRules::IsGenericCooperativeMode\" function."); + { + LogError("Could not load the \"CTerrorGameRules::IsGenericCooperativeMode\" gamedata signature."); + } else { + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + g_hSDK_CTerrorGameRules_IsGenericCooperativeMode = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_IsGenericCooperativeMode == null ) + LogError("Could not prep the \"CTerrorGameRules::IsGenericCooperativeMode\" function."); + } } StartPrepSDKCall(SDKCall_GameRules); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "NotifyNetworkStateChanged") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CGameRulesProxy::NotifyNetworkStateChanged") == false ) { - LogError("Failed to find signature: NotifyNetworkStateChanged"); + LogError("Failed to find signature: CGameRulesProxy::NotifyNetworkStateChanged"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_NotifyNetworkStateChanged = EndPrepSDKCall(); - if( g_hSDK_Call_NotifyNetworkStateChanged == null ) - LogError("Failed to create SDKCall: NotifyNetworkStateChanged"); + g_hSDK_CGameRulesProxy_NotifyNetworkStateChanged = EndPrepSDKCall(); + if( g_hSDK_CGameRulesProxy_NotifyNetworkStateChanged == null ) + LogError("Failed to create SDKCall: CGameRulesProxy::NotifyNetworkStateChanged"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "OnStaggered") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::OnStaggered") == false ) { LogError("Failed to find signature: StaggerPlayer"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_StaggerPlayer = EndPrepSDKCall(); - if( g_hSDK_Call_StaggerPlayer == null ) - LogError("Failed to create SDKCall: OnStaggered"); + g_hSDK_CTerrorPlayer_OnStaggered = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_OnStaggered == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::OnStaggered"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SendInRescueVehicle") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirectorScriptedEventManager::SendInRescueVehicle") == false ) { - LogError("Failed to find signature: SendInRescueVehicle"); + LogError("Failed to find signature: CDirectorScriptedEventManager::SendInRescueVehicle"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_SendInRescueVehicle = EndPrepSDKCall(); - if( g_hSDK_Call_SendInRescueVehicle == null ) - LogError("Failed to create SDKCall: SendInRescueVehicle"); + g_hSDK_CDirectorScriptedEventManager_SendInRescueVehicle = EndPrepSDKCall(); + if( g_hSDK_CDirectorScriptedEventManager_SendInRescueVehicle == null ) + LogError("Failed to create SDKCall: CDirectorScriptedEventManager::SendInRescueVehicle"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ReplaceTank") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::ReplaceTank") == false ) { - LogError("Failed to find signature: ReplaceTank"); + LogError("Failed to find signature: ZombieManager::ReplaceTank"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_ReplaceTank = EndPrepSDKCall(); - if( g_hSDK_Call_ReplaceTank == null ) - LogError("Failed to create SDKCall: ReplaceTank"); + g_hSDK_ZombieManager_ReplaceTank = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_ReplaceTank == null ) + LogError("Failed to create SDKCall: ZombieManager::ReplaceTank"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnTank") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnTank") == false ) { - LogError("Failed to find signature: SpawnTank"); + LogError("Failed to find signature: ZombieManager::SpawnTank"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnTank = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnTank == null ) - LogError("Failed to create SDKCall: SpawnTank"); + g_hSDK_ZombieManager_SpawnTank = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnTank == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnTank"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnWitch") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnWitch") == false ) { - LogError("Failed to find signature: SpawnWitch"); + LogError("Failed to find signature: ZombieManager::SpawnWitch"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnWitch = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnWitch == null ) - LogError("Failed to create SDKCall: SpawnWitch"); + g_hSDK_ZombieManager_SpawnWitch = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnWitch == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnWitch"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "IsFinaleEscapeInProgress") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::IsFinaleEscapeInProgress") == false ) { - LogError("Failed to find signature: IsFinaleEscapeInProgress"); + LogError("Failed to find signature: CDirector::IsFinaleEscapeInProgress"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_IsFinaleEscapeInProgress = EndPrepSDKCall(); - if( g_hSDK_Call_IsFinaleEscapeInProgress == null ) - LogError("Failed to create SDKCall: IsFinaleEscapeInProgress"); + g_hSDK_CDirector_IsFinaleEscapeInProgress = EndPrepSDKCall(); + if( g_hSDK_CDirector_IsFinaleEscapeInProgress == null ) + LogError("Failed to create SDKCall: CDirector::IsFinaleEscapeInProgress"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SetHumanSpec") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SurvivorBot::SetHumanSpectator") == false ) { - LogError("Failed to find signature: SetHumanSpec"); + LogError("Failed to find signature: SurvivorBot::SetHumanSpectator"); } else { PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_SetHumanSpec = EndPrepSDKCall(); - if( g_hSDK_Call_SetHumanSpec == null ) - LogError("Failed to create SDKCall: SetHumanSpec"); + g_hSDK_SurvivorBot_SetHumanSpectator = EndPrepSDKCall(); + if( g_hSDK_SurvivorBot_SetHumanSpectator == null ) + LogError("Failed to create SDKCall: SurvivorBot::SetHumanSpectator"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "TakeOverBot") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::TakeOverBot") == false ) { - LogError("Failed to find signature: TakeOverBot"); + LogError("Failed to find signature: CTerrorPlayer::TakeOverBot"); } else { PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_TakeOverBot = EndPrepSDKCall(); - if( g_hSDK_Call_TakeOverBot == null ) - LogError("Failed to create SDKCall: TakeOverBot"); + g_hSDK_CTerrorPlayer_TakeOverBot = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_TakeOverBot == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::TakeOverBot"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CanBecomeGhost") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::CanBecomeGhost") == false ) { - LogError("Failed to find signature: CanBecomeGhost"); + LogError("Failed to find signature: CTerrorPlayer::CanBecomeGhost"); } else { PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_CanBecomeGhost = EndPrepSDKCall(); - if( g_hSDK_Call_CanBecomeGhost == null ) - LogError("Failed to create SDKCall: CanBecomeGhost"); + g_hSDK_CTerrorPlayer_CanBecomeGhost = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_CanBecomeGhost == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::CanBecomeGhost"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "TryOfferingTankBot") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::TryOfferingTankBot") == false ) { - LogError("Failed to find signature: TryOfferingTankBot"); + LogError("Failed to find signature: CDirector::TryOfferingTankBot"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_TryOfferingTankBot = EndPrepSDKCall(); - if( g_hSDK_Call_TryOfferingTankBot == null ) - LogError("Failed to create SDKCall: TryOfferingTankBot"); + g_hSDK_CDirector_TryOfferingTankBot = EndPrepSDKCall(); + if( g_hSDK_CDirector_TryOfferingTankBot == null ) + LogError("Failed to create SDKCall: CDirector::TryOfferingTankBot"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetNavArea") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CNavMesh::GetNavArea") == false ) { - LogError("Failed to find signature: GetNavArea"); + LogError("Failed to find signature: CNavMesh::GetNavArea"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetNavArea = EndPrepSDKCall(); - if( g_hSDK_Call_GetNavArea == null ) - SetFailState("Failed to create SDKCall: GetNavArea"); + g_hSDK_CNavMesh_GetNavArea = EndPrepSDKCall(); + if( g_hSDK_CNavMesh_GetNavArea == null ) + LogError("Failed to create SDKCall: CNavMesh::GetNavArea"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetFlowDistance") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::GetFlowDistance") == false ) { - LogError("Failed to find signature: GetFlowDistance"); + LogError("Failed to find signature: CTerrorPlayer::GetFlowDistance"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_GetFlowDistance = EndPrepSDKCall(); - if( g_hSDK_Call_GetFlowDistance == null ) - SetFailState("Failed to create SDKCall: GetFlowDistance"); + g_hSDK_CTerrorPlayer_GetFlowDistance = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_GetFlowDistance == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::GetFlowDistance"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "DoAnimationEvent") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "CTerrorPlayer::DoAnimationEvent") == false ) { - LogError("Failed to find signature: DoAnimationEvent"); + LogError("Failed to find signature: CTerrorPlayer::DoAnimationEvent"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_DoAnimationEvent = EndPrepSDKCall(); - if( g_hSDK_Call_DoAnimationEvent == null ) - SetFailState("Failed to create SDKCall: DoAnimationEvent"); + g_hSDK_CTerrorPlayer_DoAnimationEvent = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_DoAnimationEvent == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::DoAnimationEvent"); } if( !g_bLeft4Dead2 ) { StartPrepSDKCall(SDKCall_GameRules); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "RecomputeTeamScores") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::RecomputeTeamScores") == false ) { - LogError("Failed to find signature: RecomputeTeamScores"); + LogError("Failed to find signature: CTerrorGameRules::RecomputeTeamScores"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_RecomputeTeamScores = EndPrepSDKCall(); - if( g_hSDK_Call_RecomputeTeamScores == null ) - SetFailState("Failed to create SDKCall: RecomputeTeamScores"); + g_hSDK_CTerrorGameRules_RecomputeTeamScores = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_RecomputeTeamScores == null ) + LogError("Failed to create SDKCall: CTerrorGameRules::RecomputeTeamScores"); } } @@ -3698,116 +3991,116 @@ void LoadGameData() if( g_bLeft4Dead2 ) { StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetMeleeWeaponInfo") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CMeleeWeaponInfoStore::GetMeleeWeaponInfo") == false ) { - LogError("Failed to find signature: GetMeleeWeaponInfo"); + LogError("Failed to find signature: CMeleeWeaponInfoStore::GetMeleeWeaponInfo"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetMeleeInfo = EndPrepSDKCall(); - if( g_hSDK_Call_GetMeleeInfo == null ) - LogError("Failed to create SDKCall: GetMeleeWeaponInfo"); + g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo = EndPrepSDKCall(); + if( g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo == null ) + LogError("Failed to create SDKCall: CMeleeWeaponInfoStore::GetMeleeWeaponInfo"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ResetMobTimer") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::ResetMobTimer") == false ) { - LogError("Failed to find signature: ResetMobTimer"); + LogError("Failed to find signature: CDirector::ResetMobTimer"); } else { - g_hSDK_Call_ResetMobTimer = EndPrepSDKCall(); - if( g_hSDK_Call_ResetMobTimer == null ) - LogError("Failed to create SDKCall: ResetMobTimer"); + g_hSDK_CDirector_ResetMobTimer = EndPrepSDKCall(); + if( g_hSDK_CDirector_ResetMobTimer == null ) + LogError("Failed to create SDKCall: CDirector::ResetMobTimer"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ChangeFinaleStage") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirectorScriptedEventManager::ChangeFinaleStage") == false ) { - LogError("Failed to find signature: ChangeFinaleStage"); + LogError("Failed to find signature: CDirectorScriptedEventManager::ChangeFinaleStage"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_ChangeFinaleStage = EndPrepSDKCall(); - if( g_hSDK_Call_ChangeFinaleStage == null ) - LogError("Failed to create SDKCall: ChangeFinaleStage"); + g_hSDK_CDirectorScriptedEventManager_ChangeFinaleStage = EndPrepSDKCall(); + if( g_hSDK_CDirectorScriptedEventManager_ChangeFinaleStage == null ) + LogError("Failed to create SDKCall: CDirectorScriptedEventManager::ChangeFinaleStage"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnSpecial") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnSpecial") == false ) { - LogError("Failed to find signature: SpawnSpecial"); + LogError("Failed to find signature: ZombieManager::SpawnSpecial"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnSpecial = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnSpecial == null ) - LogError("Failed to create SDKCall: SpawnSpecial"); + g_hSDK_ZombieManager_SpawnSpecial = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnSpecial == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnSpecial"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnWitchBride") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnWitchBride") == false ) { - LogError("Failed to find signature: SpawnWitchBride"); + LogError("Failed to find signature: ZombieManager::SpawnWitchBride"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnWitchBride = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnWitchBride == null ) - LogError("Failed to create SDKCall: SpawnWitchBride"); + g_hSDK_ZombieManager_SpawnWitchBride = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnWitchBride == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnWitchBride"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "AreWanderersAllowed") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::AreWanderersAllowed") == false ) { - LogError("Failed to find signature: AreWanderersAllowed"); + LogError("Failed to find signature: CDirector::AreWanderersAllowed"); } else { PrepSDKCall_SetReturnInfo(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_AreWanderersAllowed = EndPrepSDKCall(); - if( g_hSDK_Call_AreWanderersAllowed == null ) - LogError("Failed to create SDKCall: AreWanderersAllowed"); + g_hSDK_CDirector_AreWanderersAllowed = EndPrepSDKCall(); + if( g_hSDK_CDirector_AreWanderersAllowed == null ) + LogError("Failed to create SDKCall: CDirector::AreWanderersAllowed"); } } else { // L4D1 only: StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnHunter") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnHunter") == false ) { - LogError("Failed to find signature: SpawnHunter"); + LogError("Failed to find signature: ZombieManager::SpawnHunter"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnHunter = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnHunter == null ) - LogError("Failed to create SDKCall: SpawnHunter"); + g_hSDK_ZombieManager_SpawnHunter = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnHunter == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnHunter"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnBoomer") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnBoomer") == false ) { - LogError("Failed to find signature: SpawnBoomer"); + LogError("Failed to find signature: ZombieManager::SpawnBoomer"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnBoomer = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnBoomer == null ) - LogError("Failed to create SDKCall: SpawnBoomer"); + g_hSDK_ZombieManager_SpawnBoomer = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnBoomer == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnBoomer"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SpawnSmoker") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ZombieManager::SpawnSmoker") == false ) { - LogError("Failed to find signature: SpawnSmoker"); + LogError("Failed to find signature: ZombieManager::SpawnSmoker"); } else { PrepSDKCall_AddParameter(SDKType_Vector, SDKPass_ByRef); PrepSDKCall_AddParameter(SDKType_QAngle, SDKPass_ByRef); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_SpawnSmoker = EndPrepSDKCall(); - if( g_hSDK_Call_SpawnSmoker == null ) - LogError("Failed to create SDKCall: SpawnSmoker"); + g_hSDK_ZombieManager_SpawnSmoker = EndPrepSDKCall(); + if( g_hSDK_ZombieManager_SpawnSmoker == null ) + LogError("Failed to create SDKCall: ZombieManager::SpawnSmoker"); } } @@ -3817,151 +4110,151 @@ void LoadGameData() // l4d2addresses.txt // ========================= StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer_OnVomitedUpon") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::OnVomitedUpon") == false ) { - LogError("Failed to find signature: CTerrorPlayer_OnVomitedUpon"); + LogError("Failed to find signature: CTerrorPlayer::OnVomitedUpon"); } else { PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_CTerrorPlayer_OnVomitedUpon = EndPrepSDKCall(); - if( g_hSDK_Call_CTerrorPlayer_OnVomitedUpon == null ) - LogError("Failed to create SDKCall: CTerrorPlayer_OnVomitedUpon"); + g_hSDK_CTerrorPlayer_OnVomitedUpon = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_OnVomitedUpon == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::OnVomitedUpon"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CancelStagger") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::CancelStagger") == false ) { - LogError("Failed to find signature: CancelStagger"); + LogError("Failed to find signature: CTerrorPlayer::CancelStagger"); } else { - g_hSDK_Call_CancelStagger = EndPrepSDKCall(); - if( g_hSDK_Call_CancelStagger == null ) - LogError("Failed to create SDKCall: CancelStagger"); + g_hSDK_CTerrorPlayer_CancelStagger = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_CancelStagger == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::CancelStagger"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "RoundRespawn") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::RoundRespawn") == false ) { - LogError("Failed to find signature: RoundRespawn"); + LogError("Failed to find signature: CTerrorPlayer::RoundRespawn"); } else { - g_hSDK_Call_RoundRespawn = EndPrepSDKCall(); - if( g_hSDK_Call_RoundRespawn == null ) - LogError("Failed to create SDKCall: RoundRespawn"); + g_hSDK_CTerrorPlayer_RoundRespawn = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_RoundRespawn == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::RoundRespawn"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CreateRescuableSurvivors") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::CreateRescuableSurvivors") == false ) { - LogError("Failed to find signature: CreateRescuableSurvivors"); + LogError("Failed to find signature: CDirector::CreateRescuableSurvivors"); } else { - g_hSDK_Call_CreateRescuableSurvivors = EndPrepSDKCall(); - if( g_hSDK_Call_CreateRescuableSurvivors == null ) - LogError("Failed to create SDKCall: CreateRescuableSurvivors"); + g_hSDK_CDirector_CreateRescuableSurvivors = EndPrepSDKCall(); + if( g_hSDK_CDirector_CreateRescuableSurvivors == null ) + LogError("Failed to create SDKCall: CDirector::CreateRescuableSurvivors"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "OnRevived") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::OnRevived") == false ) { - LogError("Failed to find signature: OnRevived"); + LogError("Failed to find signature: CTerrorPlayer::OnRevived"); } else { - g_hSDK_Call_OnRevived = EndPrepSDKCall(); - if( g_hSDK_Call_OnRevived == null ) - LogError("Failed to create SDKCall: OnRevived"); + g_hSDK_CTerrorPlayer_OnRevived = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_OnRevived == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::OnRevived"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetHighestFlowSurvivor") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirectorTacticalServices::GetHighestFlowSurvivor") == false ) { - LogError("Failed to find signature: GetHighestFlowSurvivor"); + LogError("Failed to find signature: CDirectorTacticalServices::GetHighestFlowSurvivor"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_GetHighestFlowSurvivor = EndPrepSDKCall(); - if( g_hSDK_Call_GetHighestFlowSurvivor == null ) - LogError("Failed to create SDKCall: GetHighestFlowSurvivor"); + g_hSDK_CDirectorTacticalServices_GetHighestFlowSurvivor = EndPrepSDKCall(); + if( g_hSDK_CDirectorTacticalServices_GetHighestFlowSurvivor == null ) + LogError("Failed to create SDKCall: CDirectorTacticalServices::GetHighestFlowSurvivor"); } StartPrepSDKCall(SDKCall_Entity); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetInfectedFlowDistance") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "Infected::GetFlowDistance") == false ) { - LogError("Failed to find signature: GetInfectedFlowDistance"); + LogError("Failed to find signature: Infected::GetFlowDistance"); } else { PrepSDKCall_SetReturnInfo(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_GetInfectedFlowDistance = EndPrepSDKCall(); - if( g_hSDK_Call_GetInfectedFlowDistance == null ) - LogError("Failed to create SDKCall: GetInfectedFlowDistance"); + g_hSDK_Infected_GetFlowDistance = EndPrepSDKCall(); + if( g_hSDK_Infected_GetFlowDistance == null ) + LogError("Failed to create SDKCall: Infected::GetFlowDistance"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "TakeOverZombieBot") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::TakeOverZombieBot") == false ) { - LogError("Failed to find signature: TakeOverZombieBot"); + LogError("Failed to find signature: CTerrorPlayer::TakeOverZombieBot"); } else { PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); - g_hSDK_Call_TakeOverZombieBot = EndPrepSDKCall(); - if( g_hSDK_Call_TakeOverZombieBot == null ) - LogError("Failed to create SDKCall: TakeOverZombieBot"); + g_hSDK_CTerrorPlayer_TakeOverZombieBot = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_TakeOverZombieBot == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::TakeOverZombieBot"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "ReplaceWithBot") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::ReplaceWithBot") == false ) { - LogError("Failed to find signature: ReplaceWithBot"); + LogError("Failed to find signature: CTerrorPlayer::ReplaceWithBot"); } else { PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); - g_hSDK_Call_ReplaceWithBot = EndPrepSDKCall(); - if( g_hSDK_Call_ReplaceWithBot == null ) - LogError("Failed to create SDKCall: ReplaceWithBot"); + g_hSDK_CTerrorPlayer_ReplaceWithBot = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_ReplaceWithBot == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::ReplaceWithBot"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CullZombie") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::CullZombie") == false ) { - LogError("Failed to find signature: CullZombie"); + LogError("Failed to find signature: CTerrorPlayer::CullZombie"); } else { - g_hSDK_Call_CullZombie = EndPrepSDKCall(); - if( g_hSDK_Call_CullZombie == null ) - LogError("Failed to create SDKCall: CullZombie"); + g_hSDK_CTerrorPlayer_CullZombie = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_CullZombie == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::CullZombie"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SetClass") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::SetClass") == false ) { - LogError("Failed to find signature: SetClass"); + LogError("Failed to find signature: CTerrorPlayer::SetClass"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_SetClass = EndPrepSDKCall(); - if( g_hSDK_Call_SetClass == null ) - LogError("Failed to create SDKCall: SetClass"); + g_hSDK_CTerrorPlayer_SetClass = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_SetClass == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::SetClass"); } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CreateAbility") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CBaseAbility::CreateForPlayer") == false ) { - LogError("Failed to find signature: CreateAbility"); + LogError("Failed to find signature: CBaseAbility::CreateForPlayer"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_CreateAbility = EndPrepSDKCall(); - if( g_hSDK_Call_CreateAbility == null ) - LogError("Failed to create SDKCall: CreateAbility"); + g_hSDK_CBaseAbility_CreateForPlayer = EndPrepSDKCall(); + if( g_hSDK_CBaseAbility_CreateForPlayer == null ) + LogError("Failed to create SDKCall: CBaseAbility::CreateForPlayer"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "MaterializeFromGhost") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::MaterializeFromGhost") == false ) { - LogError("Failed to find signature: MaterializeFromGhost"); + LogError("Failed to find signature: CTerrorPlayer::MaterializeFromGhost"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_MaterializeFromGhost = EndPrepSDKCall(); - if( g_hSDK_Call_MaterializeFromGhost == null ) - LogError("Failed to create SDKCall: MaterializeFromGhost"); + g_hSDK_CTerrorPlayer_MaterializeFromGhost = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_MaterializeFromGhost == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::MaterializeFromGhost"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "BecomeGhost") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::BecomeGhost") == false ) { - LogError("Failed to find signature: BecomeGhost"); + LogError("Failed to find signature: CTerrorPlayer::BecomeGhost"); } else { if( g_bLeft4Dead2 ) PrepSDKCall_AddParameter(SDKType_Bool, SDKPass_Plain); @@ -3971,43 +4264,43 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); } PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_BecomeGhost = EndPrepSDKCall(); - if( g_hSDK_Call_BecomeGhost == null ) - LogError("Failed to create SDKCall: BecomeGhost"); + g_hSDK_CTerrorPlayer_BecomeGhost = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_BecomeGhost == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::BecomeGhost"); } StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "State_Transition") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CCSPlayer::State_Transition") == false ) { - LogError("Failed to find signature: State_Transition"); + LogError("Failed to find signature: CCSPlayer::State_Transition"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_State_Transition = EndPrepSDKCall(); - if( g_hSDK_Call_State_Transition == null ) - LogError("Failed to create SDKCall: State_Transition"); + g_hSDK_CCSPlayer_State_Transition = EndPrepSDKCall(); + if( g_hSDK_CCSPlayer_State_Transition == null ) + LogError("Failed to create SDKCall: CCSPlayer::State_Transition"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "RegisterForbiddenTarget") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::RegisterForbiddenTarget") == false ) { - LogError("Failed to find signature: RegisterForbiddenTarget"); + LogError("Failed to find signature: CDirector::RegisterForbiddenTarget"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_RegisterForbiddenTarget = EndPrepSDKCall(); - if( g_hSDK_Call_RegisterForbiddenTarget == null ) - LogError("Failed to create SDKCall: RegisterForbiddenTarget"); + g_hSDK_CDirector_RegisterForbiddenTarget = EndPrepSDKCall(); + if( g_hSDK_CDirector_RegisterForbiddenTarget == null ) + LogError("Failed to create SDKCall: CDirector::RegisterForbiddenTarget"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "UnRegisterForbiddenTarget") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::UnregisterForbiddenTarget") == false ) { - LogError("Failed to find signature: UnRegisterForbiddenTarget"); + LogError("Failed to find signature: CDirector::UnregisterForbiddenTarget"); } else { PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); - g_hSDK_Call_UnRegisterForbiddenTarget = EndPrepSDKCall(); - if( g_hSDK_Call_UnRegisterForbiddenTarget == null ) - LogError("Failed to create SDKCall: UnRegisterForbiddenTarget"); + g_hSDK_CDirector_UnregisterForbiddenTarget = EndPrepSDKCall(); + if( g_hSDK_CDirector_UnregisterForbiddenTarget == null ) + LogError("Failed to create SDKCall: CDirector::UnregisterForbiddenTarget"); } @@ -4015,25 +4308,25 @@ void LoadGameData() if( g_bLeft4Dead2 ) { StartPrepSDKCall(SDKCall_Player); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer_OnHitByVomitJar") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::OnHitByVomitJar") == false ) { - LogError("Failed to find signature: CTerrorPlayer_OnHitByVomitJar"); + LogError("Failed to find signature: CTerrorPlayer::OnHitByVomitJar"); } else { PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); - g_hSDK_Call_CTerrorPlayer_OnHitByVomitJar = EndPrepSDKCall(); - if( g_hSDK_Call_CTerrorPlayer_OnHitByVomitJar == null ) - LogError("Failed to create SDKCall: CTerrorPlayer_OnHitByVomitJar"); + g_hSDK_CTerrorPlayer_OnHitByVomitJar = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_OnHitByVomitJar == null ) + LogError("Failed to create SDKCall: CTerrorPlayer::OnHitByVomitJar"); } StartPrepSDKCall(SDKCall_Entity); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "Infected_OnHitByVomitJar") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "Infected::OnHitByVomitJar") == false ) { - LogError("Failed to find signature: Infected_OnHitByVomitJar"); + LogError("Failed to find signature: Infected::OnHitByVomitJar"); } else { PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); - g_hSDK_Call_Infected_OnHitByVomitJar = EndPrepSDKCall(); - if( g_hSDK_Call_Infected_OnHitByVomitJar == null ) - LogError("Failed to create SDKCall: Infected_OnHitByVomitJar"); + g_hSDK_Infected_OnHitByVomitJar = EndPrepSDKCall(); + if( g_hSDK_Infected_OnHitByVomitJar == null ) + LogError("Failed to create SDKCall: Infected::OnHitByVomitJar"); } StartPrepSDKCall(SDKCall_Player); @@ -4045,108 +4338,108 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); - g_hSDK_Call_CTerrorPlayer_Fling = EndPrepSDKCall(); - if( g_hSDK_Call_CTerrorPlayer_Fling == null ) + g_hSDK_CTerrorPlayer_Fling = EndPrepSDKCall(); + if( g_hSDK_CTerrorPlayer_Fling == null ) LogError("Failed to create SDKCall: CTerrorPlayer::Fling"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "GetVersusCompletionPlayer") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorGameRules::GetVersusCompletion") == false ) { - LogError("Failed to find signature: GetVersusCompletionPlayer"); + LogError("Failed to find signature: CTerrorGameRules::GetVersusCompletion"); } else { PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetVersusCompletionPlayer = EndPrepSDKCall(); - if( g_hSDK_Call_GetVersusCompletionPlayer == null ) - LogError("Failed to create SDKCall: GetVersusCompletionPlayer"); + g_hSDK_CTerrorGameRules_GetVersusCompletion = EndPrepSDKCall(); + if( g_hSDK_CTerrorGameRules_GetVersusCompletion == null ) + LogError("Failed to create SDKCall: CTerrorGameRules::GetVersusCompletion"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SwapTeams") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::SwapTeams") == false ) { - LogError("Failed to find signature: SwapTeams"); + LogError("Failed to find signature: CDirector::SwapTeams"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_SwapTeams = EndPrepSDKCall(); - if( g_hSDK_Call_SwapTeams == null ) - LogError("Failed to create SDKCall: SwapTeams"); + g_hSDK_CDirector_SwapTeams = EndPrepSDKCall(); + if( g_hSDK_CDirector_SwapTeams == null ) + LogError("Failed to create SDKCall: CDirector::SwapTeams"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "AreTeamsFlipped") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::AreTeamsFlipped") == false ) { - LogError("Failed to find signature: AreTeamsFlipped"); + LogError("Failed to find signature: CDirector::AreTeamsFlipped"); } else { PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_AreTeamsFlipped = EndPrepSDKCall(); - if( g_hSDK_Call_AreTeamsFlipped == null ) - LogError("Failed to create SDKCall: AreTeamsFlipped"); + g_hSDK_CDirector_AreTeamsFlipped = EndPrepSDKCall(); + if( g_hSDK_CDirector_AreTeamsFlipped == null ) + LogError("Failed to create SDKCall: CDirector::AreTeamsFlipped"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "StartRematchVote") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::StartRematchVote") == false ) { - LogError("Failed to find signature: StartRematchVote"); + LogError("Failed to find signature: CDirector::StartRematchVote"); } else { - g_hSDK_Call_StartRematchVote = EndPrepSDKCall(); - if( g_hSDK_Call_StartRematchVote == null ) - LogError("Failed to create SDKCall: StartRematchVote"); + g_hSDK_CDirector_StartRematchVote = EndPrepSDKCall(); + if( g_hSDK_CDirector_StartRematchVote == null ) + LogError("Failed to create SDKCall: CDirector::StartRematchVote"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "FullRestart") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::FullRestart") == false ) { - LogError("Failed to find signature: FullRestart"); + LogError("Failed to find signature: CDirector::FullRestart"); } else { - g_hSDK_Call_FullRestart = EndPrepSDKCall(); - if( g_hSDK_Call_FullRestart == null ) - LogError("Failed to create SDKCall: FullRestart"); + g_hSDK_CDirector_FullRestart = EndPrepSDKCall(); + if( g_hSDK_CDirector_FullRestart == null ) + LogError("Failed to create SDKCall: CDirector::FullRestart"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "HideVersusScoreboard") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirectorVersusMode::HideScoreboardNonVirtual") == false ) { - LogError("Failed to find signature: HideVersusScoreboard"); + LogError("Failed to find signature: CDirectorVersusMode::HideScoreboardNonVirtual"); } else { - g_hSDK_Call_HideVersusScoreboard = EndPrepSDKCall(); - if( g_hSDK_Call_HideVersusScoreboard == null ) - LogError("Failed to create SDKCall: HideVersusScoreboard"); + g_hSDK_CDirectorVersusMode_HideScoreboardNonVirtual = EndPrepSDKCall(); + if( g_hSDK_CDirectorVersusMode_HideScoreboardNonVirtual == null ) + LogError("Failed to create SDKCall: CDirectorVersusMode::HideScoreboardNonVirtual"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "HideScavengeScoreboard") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirectorScavengeMode::HideScoreboardNonVirtual") == false ) { - LogError("Failed to find signature: HideScavengeScoreboard"); + LogError("Failed to find signature: CDirectorScavengeMode::HideScoreboardNonVirtual"); } else { - g_hSDK_Call_HideScavengeScoreboard = EndPrepSDKCall(); - if( g_hSDK_Call_HideScavengeScoreboard == null ) - LogError("Failed to create SDKCall: HideScavengeScoreboard"); + g_hSDK_CDirectorScavengeMode_HideScoreboardNonVirtual = EndPrepSDKCall(); + if( g_hSDK_CDirectorScavengeMode_HideScoreboardNonVirtual == null ) + LogError("Failed to create SDKCall: CDirectorScavengeMode::HideScoreboardNonVirtual"); } StartPrepSDKCall(SDKCall_Raw); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "HideScoreboard") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CDirector::HideScoreboard") == false ) { - LogError("Failed to find signature: HideScoreboard"); + LogError("Failed to find signature: CDirectorHideScoreboard"); } else { - g_hSDK_Call_HideScoreboard = EndPrepSDKCall(); - if( g_hSDK_Call_HideScoreboard == null ) - LogError("Failed to create SDKCall: HideScoreboard"); + g_hSDK_CDirector_HideScoreboard = EndPrepSDKCall(); + if( g_hSDK_CDirector_HideScoreboard == null ) + LogError("Failed to create SDKCall: CDirector::HideScoreboard"); } } StartPrepSDKCall(SDKCall_Static); - if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "SetReservationCookie") == false ) + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CBaseServer::SetReservationCookie") == false ) { - LogError("Failed to find signature: SetReservationCookie"); + LogError("Failed to find signature: CBaseServer::SetReservationCookie"); } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_String, SDKPass_Pointer); - g_hSDK_Call_LobbyUnreserve = EndPrepSDKCall(); - if( g_hSDK_Call_LobbyUnreserve == null ) - LogError("Failed to create SDKCall: SetReservationCookie"); + g_hSDK_CBaseServer_SetReservationCookie = EndPrepSDKCall(); + if( g_hSDK_CBaseServer_SetReservationCookie == null ) + LogError("Failed to create SDKCall: CBaseServer::SetReservationCookie"); } @@ -4161,8 +4454,8 @@ void LoadGameData() PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_GetCampaignScores = EndPrepSDKCall(); - if( g_hSDK_Call_GetCampaignScores == null ) + g_hSDK_GetCampaignScores = EndPrepSDKCall(); + if( g_hSDK_GetCampaignScores == null ) LogError("Failed to create SDKCall: GetCampaignScores"); } // */ @@ -4175,8 +4468,8 @@ void LoadGameData() } else { PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); - g_hSDK_Call_LobbyIsReserved = EndPrepSDKCall(); - if( g_hSDK_Call_LobbyIsReserved == null ) + g_hSDK_LobbyIsReserved = EndPrepSDKCall(); + if( g_hSDK_LobbyIsReserved == null ) LogError("Failed to create SDKCall: LobbyIsReserved"); } // */ @@ -4188,25 +4481,25 @@ void LoadGameData() // ========================= if( g_bLeft4Dead2 ) { - ScavengeModePtr = hGameData.GetOffset("ScavengeModePtr"); - ValidateOffset(ScavengeModePtr, "ScavengeModePtr"); + g_pScavengeMode = hGameData.GetOffset("ScavengeModePtr"); + ValidateOffset(g_pScavengeMode, "ScavengeModePtr"); - VersusModePtr = hGameData.GetOffset("VersusModePtr"); - ValidateOffset(VersusModePtr, "VersusModePtr"); + g_pVersusMode = hGameData.GetOffset("VersusModePtr"); + ValidateOffset(g_pVersusMode, "VersusModePtr"); - ScriptedEventManagerPtr = hGameData.GetOffset("ScriptedEventManagerPtr"); - ValidateOffset(ScriptedEventManagerPtr, "ScriptedEventManagerPtr"); + g_pScriptedEventManager = hGameData.GetOffset("ScriptedEventManagerPtr"); + ValidateOffset(g_pScriptedEventManager, "ScriptedEventManagerPtr"); // DisableAddons - VanillaModeAddress = hGameData.GetAddress("VanillaModeAddress"); - ValidateAddress(VanillaModeAddress, "VanillaModeAddress", true); + g_pVanillaModeAddress = hGameData.GetAddress("VanillaModeAddress"); + ValidateAddress(g_pVanillaModeAddress, "VanillaModeAddress", true); - VanillaModeOffset = hGameData.GetOffset("VanillaModeOffset"); - ValidateOffset(VanillaModeOffset, "VanillaModeOffset"); + g_iOff_VanillaModeOffset = hGameData.GetOffset("VanillaModeOffset"); + ValidateOffset(g_iOff_VanillaModeOffset, "VanillaModeOffset"); // } else { - // TeamScoresAddress = hGameData.GetAddress("ClearTeamScores"); - // if( TeamScoresAddress == Address_Null ) LogError("Failed to find \"ClearTeamScores\" address."); + // TeamScoresAddress = hGameData.GetAddress("CTerrorGameRules::ClearTeamScores"); + // if( TeamScoresAddress == Address_Null ) LogError("Failed to find \"CTerrorGameRules::ClearTeamScores\" address."); // ClearTeamScore_A = hGameData.GetOffset("ClearTeamScore_A"); // if( ClearTeamScore_A == -1 ) LogError("Failed to find \"ClearTeamScore_A\" offset."); @@ -4220,11 +4513,11 @@ void LoadGameData() { PrintToServer(""); PrintToServer("Ptr Offsets:"); - PrintToServer("%12d == VersusModePtr", VersusModePtr); - PrintToServer("%12d == ScavengeModePtr", ScavengeModePtr); - PrintToServer("%12d == ScriptedEventManagerPtr", ScriptedEventManagerPtr); - PrintToServer("%12d == VanillaModeAddress", VanillaModeAddress); - PrintToServer("%12d == VanillaModeOffset (Win=0, Nix=4)", VanillaModeOffset); + PrintToServer("%12d == VersusModePtr", g_pVersusMode); + PrintToServer("%12d == ScavengeModePtr", g_pScavengeMode); + PrintToServer("%12d == ScriptedEventManagerPtr", g_pScriptedEventManager); + PrintToServer("%12d == VanillaModeAddress", g_pVanillaModeAddress); + PrintToServer("%12d == VanillaModeOffset (Win=0, Nix=4)", g_iOff_VanillaModeOffset); // } else { // PrintToServer("%12d == TeamScoresAddress", TeamScoresAddress); // PrintToServer("%12d == ClearTeamScore_A", ClearTeamScore_A); @@ -4250,25 +4543,25 @@ void LoadGameData() g_pServer = hGameData.GetAddress("ServerAddr"); ValidateAddress(g_pServer, "g_pServer", true); + g_pWeaponInfoDatabase = hGameData.GetAddress("WeaponInfoDatabase"); + ValidateAddress(g_pWeaponInfoDatabase, "g_pWeaponInfoDatabase", true); + if( g_bLeft4Dead2 ) { - g_pWeaponInfoDatabase = hGameData.GetAddress("WeaponInfoDatabase"); - ValidateAddress(g_pWeaponInfoDatabase, "g_pWeaponInfoDatabase", true); - g_pMeleeWeaponInfoStore = hGameData.GetAddress("MeleeWeaponInfoStore"); ValidateAddress(g_pMeleeWeaponInfoStore, "g_pMeleeWeaponInfoStore", true); - ScriptedEventManagerPtr = LoadFromAddress(g_pDirector + view_as
    (ScriptedEventManagerPtr), NumberType_Int32); - ValidateAddress(ScriptedEventManagerPtr, "ScriptedEventManagerPtr", true); + g_pScriptedEventManager = LoadFromAddress(g_pDirector + view_as
    (g_pScriptedEventManager), NumberType_Int32); + ValidateAddress(g_pScriptedEventManager, "ScriptedEventManagerPtr", true); - VersusModePtr = LoadFromAddress(g_pDirector + view_as
    (VersusModePtr), NumberType_Int32); - ValidateAddress(VersusModePtr, "VersusModePtr", true); + g_pVersusMode = LoadFromAddress(g_pDirector + view_as
    (g_pVersusMode), NumberType_Int32); + ValidateAddress(g_pVersusMode, "VersusModePtr", true); - ScavengeModePtr = LoadFromAddress(g_pDirector + view_as
    (ScavengeModePtr), NumberType_Int32); - ValidateAddress(ScavengeModePtr, "ScavengeModePtr", true); + g_pScavengeMode = LoadFromAddress(g_pDirector + view_as
    (g_pScavengeMode), NumberType_Int32); + ValidateAddress(g_pScavengeMode, "ScavengeModePtr", true); } else { - // L4D1: g_pDirector is also VersusModePtr. - VersusModePtr = view_as(g_pDirector); + // L4D1: g_pDirector is also g_pVersusMode. + g_pVersusMode = view_as(g_pDirector); } #if DEBUG @@ -4283,13 +4576,13 @@ void LoadGameData() PrintToServer("%12d == g_pGameRules", g_pGameRules); PrintToServer("%12d == g_pNavMesh", g_pNavMesh); PrintToServer("%12d == g_pServer", g_pServer); + PrintToServer("%12d == g_pWeaponInfoDatabase", g_pWeaponInfoDatabase); if( g_bLeft4Dead2 ) { - PrintToServer("%12d == g_pWeaponInfoDatabase", g_pWeaponInfoDatabase); PrintToServer("%12d == g_pMeleeWeaponInfoStore", g_pMeleeWeaponInfoStore); - PrintToServer("%12d == ScriptedEventManagerPtr", ScriptedEventManagerPtr); - PrintToServer("%12d == VersusModePtr", VersusModePtr); - PrintToServer("%12d == ScavengeModePtr", ScavengeModePtr); + PrintToServer("%12d == ScriptedEventManagerPtr", g_pScriptedEventManager); + PrintToServer("%12d == VersusModePtr", g_pVersusMode); + PrintToServer("%12d == g_pScavengeMode", g_pScavengeMode); } PrintToServer(""); #endif @@ -4304,98 +4597,98 @@ void LoadGameData() PrintToServer("Various Offsets:"); #endif - m_iCampaignScores = hGameData.GetOffset("m_iCampaignScores"); - ValidateOffset(m_iCampaignScores, "m_iCampaignScores"); + g_iOff_m_iCampaignScores = hGameData.GetOffset("m_iCampaignScores"); + ValidateOffset(g_iOff_m_iCampaignScores, "m_iCampaignScores"); - m_fTankSpawnFlowPercent = hGameData.GetOffset("m_fTankSpawnFlowPercent"); - ValidateOffset(m_fTankSpawnFlowPercent, "m_fTankSpawnFlowPercent"); + g_iOff_m_fTankSpawnFlowPercent = hGameData.GetOffset("m_fTankSpawnFlowPercent"); + ValidateOffset(g_iOff_m_fTankSpawnFlowPercent, "m_fTankSpawnFlowPercent"); - m_fWitchSpawnFlowPercent = hGameData.GetOffset("m_fWitchSpawnFlowPercent"); - ValidateOffset(m_fWitchSpawnFlowPercent, "m_fWitchSpawnFlowPercent"); + g_iOff_m_fWitchSpawnFlowPercent = hGameData.GetOffset("m_fWitchSpawnFlowPercent"); + ValidateOffset(g_iOff_m_fWitchSpawnFlowPercent, "m_fWitchSpawnFlowPercent"); - m_iTankPassedCount = hGameData.GetOffset("m_iTankPassedCount"); - ValidateOffset(m_iTankPassedCount, "m_iTankPassedCount"); + g_iOff_m_iTankPassedCount = hGameData.GetOffset("m_iTankPassedCount"); + ValidateOffset(g_iOff_m_iTankPassedCount, "m_iTankPassedCount"); - m_bTankThisRound = hGameData.GetOffset("m_bTankThisRound"); - ValidateOffset(m_bTankThisRound, "m_bTankThisRound"); + g_iOff_m_bTankThisRound = hGameData.GetOffset("m_bTankThisRound"); + ValidateOffset(g_iOff_m_bTankThisRound, "m_bTankThisRound"); - m_bWitchThisRound = hGameData.GetOffset("m_bWitchThisRound"); - ValidateOffset(m_bWitchThisRound, "m_bWitchThisRound"); + g_iOff_m_bWitchThisRound = hGameData.GetOffset("m_bWitchThisRound"); + ValidateOffset(g_iOff_m_bWitchThisRound, "m_bWitchThisRound"); - InvulnerabilityTimer = hGameData.GetOffset("InvulnerabilityTimer"); - ValidateOffset(InvulnerabilityTimer, "InvulnerabilityTimer"); + g_iOff_InvulnerabilityTimer = hGameData.GetOffset("InvulnerabilityTimer"); + ValidateOffset(g_iOff_InvulnerabilityTimer, "InvulnerabilityTimer"); - m_iTankTickets = hGameData.GetOffset("m_iTankTickets"); - ValidateOffset(m_iTankTickets, "m_iTankTickets"); + g_iOff_m_iTankTickets = hGameData.GetOffset("m_iTankTickets"); + ValidateOffset(g_iOff_m_iTankTickets, "m_iTankTickets"); if( !g_bLeft4Dead2 ) { - m_iSurvivorHealthBonus = hGameData.GetOffset("m_iSurvivorHealthBonus"); - ValidateOffset(m_iSurvivorHealthBonus, "m_iSurvivorHealthBonus"); + g_iOff_m_iSurvivorHealthBonus = hGameData.GetOffset("m_iSurvivorHealthBonus"); + ValidateOffset(g_iOff_m_iSurvivorHealthBonus, "m_iSurvivorHealthBonus"); - m_bFirstSurvivorLeftStartArea = hGameData.GetOffset("m_bFirstSurvivorLeftStartArea"); - ValidateOffset(m_bFirstSurvivorLeftStartArea, "m_bFirstSurvivorLeftStartArea"); + g_iOff_m_bFirstSurvivorLeftStartArea = hGameData.GetOffset("m_bFirstSurvivorLeftStartArea"); + ValidateOffset(g_iOff_m_bFirstSurvivorLeftStartArea, "m_bFirstSurvivorLeftStartArea"); } - m_flow = hGameData.GetOffset("m_flow"); - ValidateOffset(m_flow, "m_flow"); + g_iOff_m_flow = hGameData.GetOffset("m_flow"); + ValidateOffset(g_iOff_m_flow, "m_flow"); - m_chapter = hGameData.GetOffset("m_chapter"); - ValidateOffset(m_chapter, "m_chapter"); + g_iOff_m_chapter = hGameData.GetOffset("m_chapter"); + ValidateOffset(g_iOff_m_chapter, "m_chapter"); - m_PendingMobCount = hGameData.GetOffset("m_PendingMobCount"); - ValidateOffset(m_PendingMobCount, "m_PendingMobCount"); + g_iOff_m_PendingMobCount = hGameData.GetOffset("m_PendingMobCount"); + ValidateOffset(g_iOff_m_PendingMobCount, "m_PendingMobCount"); - m_fMapMaxFlowDistance = hGameData.GetOffset("m_fMapMaxFlowDistance"); - ValidateOffset(m_fMapMaxFlowDistance, "m_fMapMaxFlowDistance"); + g_iOff_m_fMapMaxFlowDistance = hGameData.GetOffset("m_fMapMaxFlowDistance"); + ValidateOffset(g_iOff_m_fMapMaxFlowDistance, "m_fMapMaxFlowDistance"); - m_rescueCheckTimer = hGameData.GetOffset("m_rescueCheckTimer"); - ValidateOffset(m_rescueCheckTimer, "m_rescueCheckTimer"); + g_iOff_m_rescueCheckTimer = hGameData.GetOffset("m_rescueCheckTimer"); + ValidateOffset(g_iOff_m_rescueCheckTimer, "m_rescueCheckTimer"); - VersusMaxCompletionScore = hGameData.GetOffset("VersusMaxCompletionScore"); - ValidateOffset(VersusMaxCompletionScore, "VersusMaxCompletionScore"); + g_iOff_VersusMaxCompletionScore = hGameData.GetOffset("VersusMaxCompletionScore"); + ValidateOffset(g_iOff_VersusMaxCompletionScore, "VersusMaxCompletionScore"); - m_iTankCount = hGameData.GetOffset("m_iTankCount"); - ValidateOffset(m_iTankCount, "m_iTankCount"); + g_iOff_m_iTankCount = hGameData.GetOffset("m_iTankCount"); + ValidateOffset(g_iOff_m_iTankCount, "m_iTankCount"); - MobSpawnTimer = hGameData.GetOffset("MobSpawnTimer"); - ValidateOffset(MobSpawnTimer, "MobSpawnTimer"); + g_iOff_MobSpawnTimer = hGameData.GetOffset("MobSpawnTimer"); + ValidateOffset(g_iOff_MobSpawnTimer, "MobSpawnTimer"); if( g_bLeft4Dead2 ) { - g_iAddonEclipse1 = hGameData.GetOffset("AddonEclipse1"); - ValidateOffset(g_iAddonEclipse1, "AddonEclipse1"); - g_iAddonEclipse2 = hGameData.GetOffset("AddonEclipse2"); - ValidateOffset(g_iAddonEclipse2, "AddonEclipse2"); + g_iOff_AddonEclipse1 = hGameData.GetOffset("AddonEclipse1"); + ValidateOffset(g_iOff_AddonEclipse1, "AddonEclipse1"); + g_iOff_AddonEclipse2 = hGameData.GetOffset("AddonEclipse2"); + ValidateOffset(g_iOff_AddonEclipse2, "AddonEclipse2"); - SpawnTimer = hGameData.GetOffset("SpawnTimer"); - ValidateOffset(SpawnTimer, "SpawnTimer"); + g_iOff_SpawnTimer = hGameData.GetOffset("SpawnTimer"); + ValidateOffset(g_iOff_SpawnTimer, "SpawnTimer"); - OnBeginRoundSetupTime = hGameData.GetOffset("OnBeginRoundSetupTime"); - ValidateOffset(OnBeginRoundSetupTime, "OnBeginRoundSetupTime"); + g_iOff_OnBeginRoundSetupTime = hGameData.GetOffset("OnBeginRoundSetupTime"); + ValidateOffset(g_iOff_OnBeginRoundSetupTime, "OnBeginRoundSetupTime"); - m_iWitchCount = hGameData.GetOffset("m_iWitchCount"); - ValidateOffset(m_iWitchCount, "m_iWitchCount"); + g_iOff_m_iWitchCount = hGameData.GetOffset("m_iWitchCount"); + ValidateOffset(g_iOff_m_iWitchCount, "m_iWitchCount"); - OvertimeGraceTimer = hGameData.GetOffset("OvertimeGraceTimer"); - ValidateOffset(OvertimeGraceTimer, "OvertimeGraceTimer"); + g_iOff_OvertimeGraceTimer = hGameData.GetOffset("OvertimeGraceTimer"); + ValidateOffset(g_iOff_OvertimeGraceTimer, "OvertimeGraceTimer"); - m_iShovePenalty = hGameData.GetOffset("m_iShovePenalty"); - ValidateOffset(m_iShovePenalty, "m_iShovePenalty"); + g_iOff_m_iShovePenalty = hGameData.GetOffset("m_iShovePenalty"); + ValidateOffset(g_iOff_m_iShovePenalty, "m_iShovePenalty"); - m_fNextShoveTime = hGameData.GetOffset("m_fNextShoveTime"); - ValidateOffset(m_fNextShoveTime, "m_fNextShoveTime"); + g_iOff_m_fNextShoveTime = hGameData.GetOffset("m_fNextShoveTime"); + ValidateOffset(g_iOff_m_fNextShoveTime, "m_fNextShoveTime"); - m_preIncapacitatedHealth = hGameData.GetOffset("m_preIncapacitatedHealth"); - ValidateOffset(m_preIncapacitatedHealth, "m_preIncapacitatedHealth"); + g_iOff_m_preIncapacitatedHealth = hGameData.GetOffset("m_preIncapacitatedHealth"); + ValidateOffset(g_iOff_m_preIncapacitatedHealth, "m_preIncapacitatedHealth"); - m_preIncapacitatedHealthBuffer = hGameData.GetOffset("m_preIncapacitatedHealthBuffer"); - ValidateOffset(m_preIncapacitatedHealthBuffer, "m_preIncapacitatedHealthBuffer"); + g_iOff_m_preIncapacitatedHealthBuffer = hGameData.GetOffset("m_preIncapacitatedHealthBuffer"); + ValidateOffset(g_iOff_m_preIncapacitatedHealthBuffer, "m_preIncapacitatedHealthBuffer"); - m_maxFlames = hGameData.GetOffset("m_maxFlames"); - ValidateOffset(m_maxFlames, "m_maxFlames"); + g_iOff_m_maxFlames = hGameData.GetOffset("m_maxFlames"); + ValidateOffset(g_iOff_m_maxFlames, "m_maxFlames"); // l4d2timers.inc offsets L4D2CountdownTimer_Offsets[0] = hGameData.GetOffset("L4D2CountdownTimer_MobSpawnTimer") + view_as(g_pDirector); @@ -4405,7 +4698,7 @@ void LoadGameData() L4D2CountdownTimer_Offsets[4] = hGameData.GetOffset("L4D2CountdownTimer_SpitterSpawnTimer") + view_as(g_pDirector); L4D2CountdownTimer_Offsets[5] = hGameData.GetOffset("L4D2CountdownTimer_JockeySpawnTimer") + view_as(g_pDirector); L4D2CountdownTimer_Offsets[6] = hGameData.GetOffset("L4D2CountdownTimer_ChargerSpawnTimer") + view_as(g_pDirector); - L4D2CountdownTimer_Offsets[7] = hGameData.GetOffset("L4D2CountdownTimer_VersusStartTimer") + VersusModePtr; + L4D2CountdownTimer_Offsets[7] = hGameData.GetOffset("L4D2CountdownTimer_VersusStartTimer") + g_pVersusMode; L4D2CountdownTimer_Offsets[8] = hGameData.GetOffset("L4D2CountdownTimer_UpdateMarkersTimer") + view_as(g_pDirector); L4D2IntervalTimer_Offsets[0] = hGameData.GetOffset("L4D2IntervalTimer_SmokerDeathTimer") + view_as(g_pDirector); L4D2IntervalTimer_Offsets[1] = hGameData.GetOffset("L4D2IntervalTimer_BoomerDeathTimer") + view_as(g_pDirector); @@ -4415,26 +4708,6 @@ void LoadGameData() L4D2IntervalTimer_Offsets[5] = hGameData.GetOffset("L4D2IntervalTimer_ChargerDeathTimer") + view_as(g_pDirector); // l4d2weapons.inc offsets - L4D2IntWeapon_Offsets[0] = hGameData.GetOffset("L4D2IntWeapon_Damage"); - L4D2IntWeapon_Offsets[1] = hGameData.GetOffset("L4D2IntWeapon_Bullets"); - L4D2IntWeapon_Offsets[2] = hGameData.GetOffset("L4D2IntWeapon_ClipSize"); - L4D2FloatWeapon_Offsets[0] = hGameData.GetOffset("L4D2FloatWeapon_MaxPlayerSpeed"); - L4D2FloatWeapon_Offsets[1] = hGameData.GetOffset("L4D2FloatWeapon_SpreadPerShot"); - L4D2FloatWeapon_Offsets[2] = hGameData.GetOffset("L4D2FloatWeapon_MaxSpread"); - L4D2FloatWeapon_Offsets[3] = hGameData.GetOffset("L4D2FloatWeapon_SpreadDecay"); - L4D2FloatWeapon_Offsets[4] = hGameData.GetOffset("L4D2FloatWeapon_MinDuckingSpread"); - L4D2FloatWeapon_Offsets[5] = hGameData.GetOffset("L4D2FloatWeapon_MinStandingSpread"); - L4D2FloatWeapon_Offsets[6] = hGameData.GetOffset("L4D2FloatWeapon_MinInAirSpread"); - L4D2FloatWeapon_Offsets[7] = hGameData.GetOffset("L4D2FloatWeapon_MaxMovementSpread"); - L4D2FloatWeapon_Offsets[8] = hGameData.GetOffset("L4D2FloatWeapon_PenetrationNumLayers"); - L4D2FloatWeapon_Offsets[9] = hGameData.GetOffset("L4D2FloatWeapon_PenetrationPower"); - L4D2FloatWeapon_Offsets[10] = hGameData.GetOffset("L4D2FloatWeapon_PenetrationMaxDist"); - L4D2FloatWeapon_Offsets[11] = hGameData.GetOffset("L4D2FloatWeapon_CharPenetrationMaxDist"); - L4D2FloatWeapon_Offsets[12] = hGameData.GetOffset("L4D2FloatWeapon_Range"); - L4D2FloatWeapon_Offsets[13] = hGameData.GetOffset("L4D2FloatWeapon_RangeModifier"); - L4D2FloatWeapon_Offsets[14] = hGameData.GetOffset("L4D2FloatWeapon_CycleTime"); - L4D2FloatWeapon_Offsets[15] = hGameData.GetOffset("L4D2FloatWeapon_ScatterPitch"); - L4D2FloatWeapon_Offsets[16] = hGameData.GetOffset("L4D2FloatWeapon_ScatterYaw"); L4D2BoolMeleeWeapon_Offsets[0] = hGameData.GetOffset("L4D2BoolMeleeWeapon_Decapitates"); L4D2IntMeleeWeapon_Offsets[0] = hGameData.GetOffset("L4D2IntMeleeWeapon_DamageFlags"); L4D2IntMeleeWeapon_Offsets[1] = hGameData.GetOffset("L4D2IntMeleeWeapon_RumbleEffect"); @@ -4442,56 +4715,79 @@ void LoadGameData() L4D2FloatMeleeWeapon_Offsets[1] = hGameData.GetOffset("L4D2FloatMeleeWeapon_RefireDelay"); L4D2FloatMeleeWeapon_Offsets[2] = hGameData.GetOffset("L4D2FloatMeleeWeapon_WeaponIdleTime"); } else { - VersusStartTimer = hGameData.GetOffset("VersusStartTimer"); - ValidateOffset(VersusStartTimer, "VersusStartTimer"); + g_iOff_VersusStartTimer = hGameData.GetOffset("VersusStartTimer"); + ValidateOffset(g_iOff_VersusStartTimer, "VersusStartTimer"); #if DEBUG - PrintToServer("VersusStartTimer = %d", VersusStartTimer); + PrintToServer("VersusStartTimer = %d", g_iOff_VersusStartTimer); #endif } + // l4d2weapons.inc offsets + L4D2IntWeapon_Offsets[0] = hGameData.GetOffset("L4D2IntWeapon_Damage"); + L4D2IntWeapon_Offsets[1] = hGameData.GetOffset("L4D2IntWeapon_Bullets"); + L4D2IntWeapon_Offsets[2] = hGameData.GetOffset("L4D2IntWeapon_ClipSize"); + L4D2FloatWeapon_Offsets[0] = hGameData.GetOffset("L4D2FloatWeapon_MaxPlayerSpeed"); + L4D2FloatWeapon_Offsets[1] = hGameData.GetOffset("L4D2FloatWeapon_SpreadPerShot"); + L4D2FloatWeapon_Offsets[2] = hGameData.GetOffset("L4D2FloatWeapon_MaxSpread"); + L4D2FloatWeapon_Offsets[3] = hGameData.GetOffset("L4D2FloatWeapon_SpreadDecay"); + L4D2FloatWeapon_Offsets[4] = hGameData.GetOffset("L4D2FloatWeapon_MinDuckingSpread"); + L4D2FloatWeapon_Offsets[5] = hGameData.GetOffset("L4D2FloatWeapon_MinStandingSpread"); + L4D2FloatWeapon_Offsets[6] = hGameData.GetOffset("L4D2FloatWeapon_MinInAirSpread"); + L4D2FloatWeapon_Offsets[7] = hGameData.GetOffset("L4D2FloatWeapon_MaxMovementSpread"); + L4D2FloatWeapon_Offsets[8] = hGameData.GetOffset("L4D2FloatWeapon_PenetrationNumLayers"); + L4D2FloatWeapon_Offsets[9] = hGameData.GetOffset("L4D2FloatWeapon_PenetrationPower"); + L4D2FloatWeapon_Offsets[10] = hGameData.GetOffset("L4D2FloatWeapon_PenetrationMaxDist"); + L4D2FloatWeapon_Offsets[11] = hGameData.GetOffset("L4D2FloatWeapon_CharPenetrationMaxDist"); + L4D2FloatWeapon_Offsets[12] = hGameData.GetOffset("L4D2FloatWeapon_Range"); + L4D2FloatWeapon_Offsets[13] = hGameData.GetOffset("L4D2FloatWeapon_RangeModifier"); + L4D2FloatWeapon_Offsets[14] = hGameData.GetOffset("L4D2FloatWeapon_CycleTime"); + L4D2FloatWeapon_Offsets[15] = hGameData.GetOffset("L4D2FloatWeapon_ScatterPitch"); + L4D2FloatWeapon_Offsets[16] = hGameData.GetOffset("L4D2FloatWeapon_ScatterYaw"); + #if DEBUG - PrintToServer("m_iCampaignScores = %d", m_iCampaignScores); - PrintToServer("m_fTankSpawnFlowPercent = %d", m_fTankSpawnFlowPercent); - PrintToServer("m_fWitchSpawnFlowPercent = %d", m_fWitchSpawnFlowPercent); - PrintToServer("m_iTankPassedCount = %d", m_iTankPassedCount); - PrintToServer("m_bTankThisRound = %d", m_bTankThisRound); - PrintToServer("m_bWitchThisRound = %d", m_bWitchThisRound); - PrintToServer("InvulnerabilityTimer = %d", InvulnerabilityTimer); - PrintToServer("m_iTankTickets = %d", m_iTankTickets); - PrintToServer("m_flow = %d", m_flow); - PrintToServer("m_chapter = %d", m_chapter); - PrintToServer("m_PendingMobCount = %d", m_PendingMobCount); - PrintToServer("m_fMapMaxFlowDistance = %d", m_fMapMaxFlowDistance); - PrintToServer("m_rescueCheckTimer = %d", m_rescueCheckTimer); - PrintToServer("VersusMaxCompletionScore = %d", VersusMaxCompletionScore); - PrintToServer("m_iTankCount = %d", m_iTankCount); - PrintToServer("MobSpawnTimer = %d", MobSpawnTimer); + PrintToServer("m_iCampaignScores = %d", g_iOff_m_iCampaignScores); + PrintToServer("m_fTankSpawnFlowPercent = %d", g_iOff_m_fTankSpawnFlowPercent); + PrintToServer("m_fWitchSpawnFlowPercent = %d", g_iOff_m_fWitchSpawnFlowPercent); + PrintToServer("m_iTankPassedCount = %d", g_iOff_m_iTankPassedCount); + PrintToServer("m_bTankThisRound = %d", g_iOff_m_bTankThisRound); + PrintToServer("m_bWitchThisRound = %d", g_iOff_m_bWitchThisRound); + PrintToServer("InvulnerabilityTimer = %d", g_iOff_InvulnerabilityTimer); + PrintToServer("m_iTankTickets = %d", g_iOff_m_iTankTickets); + PrintToServer("m_flow = %d", g_iOff_m_flow); + PrintToServer("m_chapter = %d", g_iOff_m_chapter); + PrintToServer("m_PendingMobCount = %d", g_iOff_m_PendingMobCount); + PrintToServer("m_fMapMaxFlowDistance = %d", g_iOff_m_fMapMaxFlowDistance); + PrintToServer("m_rescueCheckTimer = %d", g_iOff_m_rescueCheckTimer); + PrintToServer("VersusMaxCompletionScore = %d", g_iOff_VersusMaxCompletionScore); + PrintToServer("m_iTankCount = %d", g_iOff_m_iTankCount); + PrintToServer("MobSpawnTimer = %d", g_iOff_MobSpawnTimer); + + for( int i = 0; i < sizeof(L4D2CountdownTimer_Offsets); i++ ) PrintToServer("L4D2CountdownTimer_Offsets[%d] == %d", i, L4D2CountdownTimer_Offsets[i]); + for( int i = 0; i < sizeof(L4D2IntervalTimer_Offsets); i++ ) PrintToServer("L4D2IntervalTimer_Offsets[%d] == %d", i, L4D2IntervalTimer_Offsets[i]); + for( int i = 0; i < sizeof(L4D2IntWeapon_Offsets); i++ ) PrintToServer("L4D2IntWeapon_Offsets[%d] == %d", i, L4D2IntWeapon_Offsets[i]); + for( int i = 0; i < sizeof(L4D2FloatWeapon_Offsets); i++ ) PrintToServer("L4D2FloatWeapon_Offsets[%d] == %d", i, L4D2FloatWeapon_Offsets[i]); if( g_bLeft4Dead2 ) { - PrintToServer("g_iAddonEclipse1 = %d", g_iAddonEclipse1); - PrintToServer("g_iAddonEclipse2 = %d", g_iAddonEclipse2); - PrintToServer("SpawnTimer = %d", SpawnTimer); - PrintToServer("OnBeginRoundSetupTime = %d", OnBeginRoundSetupTime); - PrintToServer("m_iWitchCount = %d", m_iWitchCount); - PrintToServer("OvertimeGraceTimer = %d", OvertimeGraceTimer); - PrintToServer("m_iShovePenalty = %d", m_iShovePenalty); - PrintToServer("m_fNextShoveTime = %d", m_fNextShoveTime); - PrintToServer("m_preIncapacitatedHealth = %d", m_preIncapacitatedHealth); - PrintToServer("m_preIncapacitatedHealthBuffer = %d", m_preIncapacitatedHealthBuffer); - PrintToServer("m_maxFlames = %d", m_maxFlames); - PrintToServer(""); - - for( int i = 0; i < sizeof(L4D2CountdownTimer_Offsets); i++ ) PrintToServer("L4D2CountdownTimer_Offsets[%d] == %d", i, L4D2CountdownTimer_Offsets[i]); - for( int i = 0; i < sizeof(L4D2IntervalTimer_Offsets); i++ ) PrintToServer("L4D2IntervalTimer_Offsets[%d] == %d", i, L4D2IntervalTimer_Offsets[i]); - for( int i = 0; i < sizeof(L4D2IntWeapon_Offsets); i++ ) PrintToServer("L4D2IntWeapon_Offsets[%d] == %d", i, L4D2IntWeapon_Offsets[i]); - for( int i = 0; i < sizeof(L4D2FloatWeapon_Offsets); i++ ) PrintToServer("L4D2FloatWeapon_Offsets[%d] == %d", i, L4D2FloatWeapon_Offsets[i]); for( int i = 0; i < sizeof(L4D2BoolMeleeWeapon_Offsets); i++ ) PrintToServer("L4D2BoolMeleeWeapon_Offsets[%d] == %d", i, L4D2BoolMeleeWeapon_Offsets[i]); for( int i = 0; i < sizeof(L4D2IntMeleeWeapon_Offsets); i++ ) PrintToServer("L4D2IntMeleeWeapon_Offsets[%d] == %d", i, L4D2IntMeleeWeapon_Offsets[i]); for( int i = 0; i < sizeof(L4D2FloatMeleeWeapon_Offsets); i++ ) PrintToServer("L4D2FloatMeleeWeapon_Offsets[%d] == %d", i, L4D2FloatMeleeWeapon_Offsets[i]); + + PrintToServer("AddonEclipse1 = %d", g_iOff_AddonEclipse1); + PrintToServer("AddonEclipse2 = %d", g_iOff_AddonEclipse2); + PrintToServer("SpawnTimer = %d", g_iOff_SpawnTimer); + PrintToServer("OnBeginRoundSetupTime = %d", g_iOff_OnBeginRoundSetupTime); + PrintToServer("m_iWitchCount = %d", g_iOff_m_iWitchCount); + PrintToServer("OvertimeGraceTimer = %d", g_iOff_OvertimeGraceTimer); + PrintToServer("m_iShovePenalty = %d", g_iOff_m_iShovePenalty); + PrintToServer("m_fNextShoveTime = %d", g_iOff_m_fNextShoveTime); + PrintToServer("m_preIncapacitatedHealth = %d", g_iOff_m_preIncapacitatedHealth); + PrintToServer("m_preIncapacitatedHealthBuffer = %d", g_iOff_m_preIncapacitatedHealthBuffer); + PrintToServer("m_maxFlames = %d", g_iOff_m_maxFlames); + PrintToServer(""); } #endif @@ -4581,14 +4877,14 @@ public int Native_GetVScriptOutput(Handle plugin, int numParams) return success; } -public int Native_HasConfigurableDifficultySetting(Handle plugin, int numParams) +public int Native_CTerrorGameRules_HasConfigurableDifficultySetting(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_HasConfigurableDifficultySetting, "HasConfigurableDifficultySetting"); + ValidateNatives(g_hSDK_CTerrorGameRules_HasConfigurableDifficultySetting, "CTerrorGameRules::HasConfigurableDifficultySetting"); - //PrintToServer("#### CALL g_hSDK_Call_HasConfigurableDifficultySetting"); - return SDKCall(g_hSDK_Call_HasConfigurableDifficultySetting, g_pGameRules); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_HasConfigurableDifficultySetting"); + return SDKCall(g_hSDK_CTerrorGameRules_HasConfigurableDifficultySetting, g_pGameRules); } public any Native_GetTempHealth(Handle plugin, int numParams) @@ -4602,6 +4898,8 @@ public int Native_SetTempHealth(Handle plugin, int numParams) int client = GetNativeCell(1); float health = GetNativeCell(2); SetTempHealth(client, health); + + return 0; } public int Native_PlayMusic(Handle plugin, int numParams) @@ -4620,8 +4918,10 @@ public int Native_PlayMusic(Handle plugin, int numParams) char[] music_str = new char[maxlength]; GetNativeString(2, music_str, maxlength); - //PrintToServer("#### CALL g_hSDK_Call_MusicPlay"); - SDKCall(g_hSDK_Call_MusicPlay, music_address, music_str, source_ent, one_float, one_bool, two_bool); + //PrintToServer("#### CALL g_hSDK_Music_Play"); + SDKCall(g_hSDK_Music_Play, music_address, music_str, source_ent, one_float, one_bool, two_bool); + + return 0; } public int Native_StopMusic(Handle plugin, int numParams) @@ -4638,23 +4938,27 @@ public int Native_StopMusic(Handle plugin, int numParams) char[] music_str = new char[maxlength]; GetNativeString(2, music_str, maxlength); - //PrintToServer("#### CALL g_hSDK_Call_MusicStop"); - SDKCall(g_hSDK_Call_MusicStop, music_address, music_str, one_float, one_bool); + //PrintToServer("#### CALL g_hSDK_Music_StopPlaying"); + SDKCall(g_hSDK_Music_StopPlaying, music_address, music_str, one_float, one_bool); + + return 0; } -public int Native_Deafen(Handle plugin, int numParams) +public int Native_CTerrorPlayer_Deafen(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_Deafen, "Deafen"); + ValidateNatives(g_hSDK_CTerrorPlayer_Deafen, "CTerrorPlayer::Deafen"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_Deafen"); - SDKCall(g_hSDK_Call_Deafen, client, 1.0, 0.0, 0.01 ); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_Deafen"); + SDKCall(g_hSDK_CTerrorPlayer_Deafen, client, 1.0, 0.0, 0.01 ); + + return 0; } -public int Native_Dissolve(Handle plugin, int numParams) +public int Native_CEntityDissolve_Create(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_Dissolve, "Dissolve"); + ValidateNatives(g_hSDK_CEntityDissolve_Create, "CEntityDissolve::Create"); int entity = GetNativeCell(1); if( entity > MaxClients ) @@ -4663,8 +4967,8 @@ public int Native_Dissolve(Handle plugin, int numParams) SDKHook(entity, SDKHook_OnTakeDamage, OnCommonDamage); } - //PrintToServer("#### CALL g_hSDK_Call_Dissolve"); - int dissolver = SDKCall(g_hSDK_Call_Dissolve, entity, "", GetGameTime() + 0.8, 2, false); + //PrintToServer("#### CALL g_hSDK_CEntityDissolve_Create"); + int dissolver = SDKCall(g_hSDK_CEntityDissolve_Create, entity, "", GetGameTime() + 0.8, 2, false); SetEntPropFloat(dissolver, Prop_Send, "m_flFadeOutStart", 0.0); // Fixes broken particles return dissolver; } @@ -4680,98 +4984,104 @@ public Action OnCommonDamage(int victim, int &attacker, int &inflictor, float &d return Plugin_Continue; } -public int Native_OnITExpired(Handle plugin, int numParams) +public int Native_CTerrorPlayer_OnITExpired(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_OnITExpired, "OnITExpired"); + ValidateNatives(g_hSDK_CTerrorPlayer_OnITExpired, "CTerrorPlayer::OnITExpired"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_OnITExpired"); - SDKCall(g_hSDK_Call_OnITExpired, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_OnITExpired"); + SDKCall(g_hSDK_CTerrorPlayer_OnITExpired, client); + + return 0; } -public int Native_AngularVelocity(Handle plugin, int numParams) +public int Native_CBaseEntity_ApplyLocalAngularVelocityImpulse(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_AngularVelocity, "AngularVelocity"); + ValidateNatives(g_hSDK_CBaseEntity_ApplyLocalAngularVelocityImpulse, "CBaseEntity::ApplyLocalAngularVelocityImpulse"); float vAng[3]; int entity = GetNativeCell(1); GetNativeArray(2, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_AngularVelocity"); - SDKCall(g_hSDK_Call_AngularVelocity, entity, vAng); + //PrintToServer("#### CALL g_hSDK_CBaseEntity_ApplyLocalAngularVelocityImpulse"); + SDKCall(g_hSDK_CBaseEntity_ApplyLocalAngularVelocityImpulse, entity, vAng); + + return 0; } -public int Native_GetRandomPZSpawnPosition(Handle plugin, int numParams) +public int Native_ZombieManager_GetRandomPZSpawnPosition(Handle plugin, int numParams) { ValidateAddress(g_pZombieManager, "g_pZombieManager"); - ValidateNatives(g_hSDK_Call_GetRandomPZSpawnPosition, "GetRandomPZSpawnPosition"); + ValidateNatives(g_hSDK_ZombieManager_GetRandomPZSpawnPosition, "ZombieManager::GetRandomPZSpawnPosition"); float vPos[3]; int client = GetNativeCell(1); int zombieClass = GetNativeCell(2); int attempts = GetNativeCell(3); - //PrintToServer("#### CALL g_hSDK_Call_GetRandomPZSpawnPosition"); - int result = SDKCall(g_hSDK_Call_GetRandomPZSpawnPosition, g_pZombieManager, zombieClass, attempts, client, vPos); + //PrintToServer("#### CALL g_hSDK_ZombieManager_GetRandomPZSpawnPosition"); + int result = SDKCall(g_hSDK_ZombieManager_GetRandomPZSpawnPosition, g_pZombieManager, zombieClass, attempts, client, vPos); SetNativeArray(4, vPos, 3); return result; } -public int Native_GetNearestNavArea(Handle plugin, int numParams) +public int Native_CNavMesh_GetNearestNavArea(Handle plugin, int numParams) { ValidateAddress(g_pNavMesh, "g_pNavMesh"); - ValidateNatives(g_hSDK_Call_GetNearestNavArea, "GetNearestNavArea"); + ValidateNatives(g_hSDK_CNavMesh_GetNearestNavArea, "CNavMesh::GetNearestNavArea"); float vPos[3]; GetNativeArray(1, vPos, 3); - //PrintToServer("#### CALL Native_GetNearestNavArea"); - int result = SDKCall(g_hSDK_Call_GetNearestNavArea, g_pNavMesh, vPos, 0, 10000.0, 0, 1, 0); + //PrintToServer("#### CALL Native_CNavMesh_GetNearestNavArea"); + int result = SDKCall(g_hSDK_CNavMesh_GetNearestNavArea, g_pNavMesh, vPos, 0, 10000.0, 0, 1, 0); return result; } -public int Native_GetLastKnownarea(Handle plugin, int numParams) +public int Native_CTerrorPlayer_GetLastKnownArea(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_GetLastKnownArea, "GetLastKnownArea"); + ValidateNatives(g_hSDK_CTerrorPlayer_GetLastKnownArea, "CTerrorPlayer::GetLastKnownArea"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_GetLastKnownArea"); - return SDKCall(g_hSDK_Call_GetLastKnownArea, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_GetLastKnownArea"); + return SDKCall(g_hSDK_CTerrorPlayer_GetLastKnownArea, client); } -public int Native_FindRandomSpot(Handle plugin, int numParams) +public int Native_TerrorNavArea_FindRandomSpot(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_FindRandomSpot, "FindRandomSpot"); + ValidateNatives(g_hSDK_TerrorNavArea_FindRandomSpot, "TerrorNavArea::FindRandomSpot"); float vPos[3]; int area = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_FindRandomSpot"); - SDKCall(g_hSDK_Call_FindRandomSpot, area, vPos, sizeof(vPos)); + //PrintToServer("#### CALL g_hSDK_TerrorNavArea_FindRandomSpot"); + SDKCall(g_hSDK_TerrorNavArea_FindRandomSpot, area, vPos, sizeof(vPos)); SetNativeArray(2, vPos, sizeof(vPos)); + + return 0; } -public int Native_HasAnySurvivorLeftSafeArea(Handle plugin, int numParams) +public int Native_CDirector_HasAnySurvivorLeftSafeArea(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_HasAnySurvivorLeftSafeArea, "HasAnySurvivorLeftSafeArea"); + ValidateNatives(g_hSDK_CDirector_HasAnySurvivorLeftSafeArea, "CDirector::HasAnySurvivorLeftSafeArea"); - //PrintToServer("#### CALL g_hSDK_Call_HasAnySurvivorLeftSafeArea"); - return SDKCall(g_hSDK_Call_HasAnySurvivorLeftSafeArea, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_HasAnySurvivorLeftSafeArea"); + return SDKCall(g_hSDK_CDirector_HasAnySurvivorLeftSafeArea, g_pDirector); } -public int Native_IsAnySurvivorInStartArea(Handle plugin, int numParams) +public int Native_CDirector_IsAnySurvivorInStartArea(Handle plugin, int numParams) { if( g_bLeft4Dead2 ) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_IsAnySurvivorInStartArea, "IsAnySurvivorInStartArea"); + ValidateNatives(g_hSDK_CDirector_IsAnySurvivorInStartArea, "CDirector::IsAnySurvivorInStartArea"); - //PrintToServer("#### CALL g_hSDK_Call_IsAnySurvivorInStartArea"); - return SDKCall(g_hSDK_Call_IsAnySurvivorInStartArea, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_IsAnySurvivorInStartArea"); + return SDKCall(g_hSDK_CDirector_IsAnySurvivorInStartArea, g_pDirector); } else { for( int i = 1; i <= MaxClients; i++ ) { @@ -4785,13 +5095,13 @@ public int Native_IsAnySurvivorInStartArea(Handle plugin, int numParams) } } -public int Native_IsAnySurvivorInCheckpoint(Handle plugin, int numParams) +public int Native_CDirector_IsAnySurvivorInExitCheckpoint(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_IsAnySurvivorInCheckpoint, "IsAnySurvivorInCheckpoint"); + ValidateNatives(g_hSDK_CDirector_IsAnySurvivorInExitCheckpoint, "CDirector::IsAnySurvivorInExitCheckpoint"); - //PrintToServer("#### CALL g_hSDK_Call_IsAnySurvivorInCheckpoint"); - return SDKCall(g_hSDK_Call_IsAnySurvivorInCheckpoint, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_IsAnySurvivorInExitCheckpoint"); + return SDKCall(g_hSDK_CDirector_IsAnySurvivorInExitCheckpoint, g_pDirector); } public int Native_IsInFirstCheckpoint(Handle plugin, int numParams) @@ -4810,100 +5120,100 @@ bool InCheckpoint(int client, bool start) { if( g_bCheckpoint[client] ) { - ValidateAddress(m_flow, "m_flow"); - ValidateNatives(g_hSDK_Call_GetLastKnownArea, "GetLastKnownArea"); + ValidateAddress(g_iOff_m_flow, "m_flow"); + ValidateNatives(g_hSDK_CTerrorPlayer_GetLastKnownArea, "CTerrorPlayer::GetLastKnownArea"); - //PrintToServer("#### CALL InCheckpoint %d g_hSDK_Call_GetLastKnownArea", start); - int area = SDKCall(g_hSDK_Call_GetLastKnownArea, client); + //PrintToServer("#### CALL InCheckpoint %d g_hSDK_CTerrorPlayer_GetLastKnownArea", start); + int area = SDKCall(g_hSDK_CTerrorPlayer_GetLastKnownArea, client); if( area == 0 ) return false; - float flow = view_as(LoadFromAddress(view_as
    (area + m_flow), NumberType_Int32)); + float flow = view_as(LoadFromAddress(view_as
    (area + g_iOff_m_flow), NumberType_Int32)); return (start ? flow < 3000.0 : flow > 3000.0); } return false; } -public int Native_HasPlayerControlledZombies(Handle plugin, int numParams) +public int Native_CTerrorGameRules_HasPlayerControlledZombies(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_HasPlayerControlledZombies, "HasPlayerControlledZombies"); + ValidateNatives(g_hSDK_CTerrorGameRules_HasPlayerControlledZombies, "CTerrorGameRules::HasPlayerControlledZombies"); - //PrintToServer("#### CALL g_hSDK_Call_HasPlayerControlledZombies"); - return SDKCall(g_hSDK_Call_HasPlayerControlledZombies); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_HasPlayerControlledZombies"); + return SDKCall(g_hSDK_CTerrorGameRules_HasPlayerControlledZombies); } -public int Native_PipeBombPrj(Handle plugin, int numParams) +public int Native_CPipeBombProjectile_Create(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_PipeBombPrj, "PipeBombPrj"); + ValidateNatives(g_hSDK_CPipeBombProjectile_Create, "CPipeBombProjectile::Create"); float vPos[3], vAng[3]; int client = GetNativeCell(1); GetNativeArray(2, vPos, 3); GetNativeArray(3, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_PipeBombPrj"); - return SDKCall(g_hSDK_Call_PipeBombPrj, vPos, vAng, vAng, vAng, client, 2.0); + //PrintToServer("#### CALL g_hSDK_CPipeBombProjectile_Create"); + return SDKCall(g_hSDK_CPipeBombProjectile_Create, vPos, vAng, vAng, vAng, client, 2.0); } -public int Native_MolotovPrj(Handle plugin, int numParams) +public int Native_CMolotovProjectile_Create(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_MolotovPrj, "MolotovPrj"); + ValidateNatives(g_hSDK_CMolotovProjectile_Create, "CMolotovProjectile::Create"); float vPos[3], vAng[3]; int client = GetNativeCell(1); GetNativeArray(2, vPos, 3); GetNativeArray(3, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_MolotovPrj"); - return SDKCall(g_hSDK_Call_MolotovPrj, vPos, vAng, vAng, vAng, client, 2.0); + //PrintToServer("#### CALL g_hSDK_CMolotovProjectile_Create"); + return SDKCall(g_hSDK_CMolotovProjectile_Create, vPos, vAng, vAng, vAng, client, 2.0); } -public int Native_VomitJarPrj(Handle plugin, int numParams) +public int Native_VomitJarProjectile_Create(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_VomitJarPrj, "VomitJarPrj"); + ValidateNatives(g_hSDK_VomitJarProjectile_Create, "VomitJarProjectile::Create"); float vPos[3], vAng[3]; int client = GetNativeCell(1); GetNativeArray(2, vPos, 3); GetNativeArray(3, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_VomitJarPrj"); - return SDKCall(g_hSDK_Call_VomitJarPrj, vPos, vAng, vAng, vAng, client, 2.0); + //PrintToServer("#### CALL g_hSDK_VomitJarProjectile_Create"); + return SDKCall(g_hSDK_VomitJarProjectile_Create, vPos, vAng, vAng, vAng, client, 2.0); } -public int Native_GrenadeLauncher(Handle plugin, int numParams) +public int Native_CGrenadeLauncher_Projectile_Create(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_GrenadeLauncher, "CGrenadeLauncher"); + ValidateNatives(g_hSDK_CGrenadeLauncher_Projectile_Create, "CGrenadeLauncher_Projectile::Create"); float vPos[3], vAng[3]; int client = GetNativeCell(1); GetNativeArray(2, vPos, 3); GetNativeArray(3, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_GrenadeLauncher"); - return SDKCall(g_hSDK_Call_GrenadeLauncher, vPos, vAng, vAng, vAng, client, 2.0); + //PrintToServer("#### CALL g_hSDK_CGrenadeLauncher_Projectile_Create"); + return SDKCall(g_hSDK_CGrenadeLauncher_Projectile_Create, vPos, vAng, vAng, vAng, client, 2.0); } -public int Native_SpitterPrj(Handle plugin, int numParams) +public int Native_CSpitterProjectile_Create(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_SpitterPrj, "SpitterPrj"); + ValidateNatives(g_hSDK_CSpitterProjectile_Create, "CSpitterProjectile::Create"); float vPos[3], vAng[3]; int client = GetNativeCell(1); GetNativeArray(2, vPos, 3); GetNativeArray(3, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_SpitterPrj"); - return SDKCall(g_hSDK_Call_SpitterPrj, vPos, vAng, vAng, vAng, client); + //PrintToServer("#### CALL g_hSDK_CSpitterProjectile_Create"); + return SDKCall(g_hSDK_CSpitterProjectile_Create, vPos, vAng, vAng, vAng, client); } -public int Native_OnAdrenalineUsed(Handle plugin, int numParams) +public int Native_CTerrorPlayer_OnAdrenalineUsed(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_OnAdrenalineUsed, "OnAdrenalineUsed"); + ValidateNatives(g_hSDK_CTerrorPlayer_OnAdrenalineUsed, "CTerrorPlayer::OnAdrenalineUsed"); int client = GetNativeCell(1); float fTime = GetNativeCell(2); @@ -4913,7 +5223,7 @@ public int Native_OnAdrenalineUsed(Handle plugin, int numParams) if( heal ) { float fHealth = GetTempHealth(client); - fHealth += g_hPillsHealth.FloatValue; + fHealth += g_hCvar_PillsHealth.FloatValue; if( fHealth > 100.0 ) fHealth = 100.0; SetTempHealth(client, fHealth); @@ -4927,44 +5237,48 @@ public int Native_OnAdrenalineUsed(Handle plugin, int numParams) } } - //PrintToServer("#### CALL g_hSDK_Call_OnAdrenalineUsed"); - SDKCall(g_hSDK_Call_OnAdrenalineUsed, client, fTime); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_OnAdrenalineUsed"); + SDKCall(g_hSDK_CTerrorPlayer_OnAdrenalineUsed, client, fTime); + + return 0; } public int Native_GetCurrentFinaleStage(Handle plugin, int numParams) { - ValidateAddress(ScriptedEventManagerPtr, "ScriptedEventManagerPtr"); + ValidateAddress(g_pScriptedEventManager, "g_pScriptedEventManager"); - return LoadFromAddress(view_as
    (ScriptedEventManagerPtr + 0x04), NumberType_Int32); + return LoadFromAddress(view_as
    (g_pScriptedEventManager + 0x04), NumberType_Int32); } -public int Native_ForceNextStage(Handle plugin, int numParams) +public int Native_CDirector_ForceNextStage(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_ForceNextStage, "ForceNextStage"); + ValidateNatives(g_hSDK_CDirector_ForceNextStage, "CDirector::ForceNextStage"); + + //PrintToServer("#### CALL g_hSDK_CDirector_ForceNextStage"); + SDKCall(g_hSDK_CDirector_ForceNextStage, g_pDirector); - //PrintToServer("#### CALL g_hSDK_Call_ForceNextStage"); - SDKCall(g_hSDK_Call_ForceNextStage, g_pDirector); + return 0; } -public int Native_IsTankInPlay(Handle plugin, int numParams) +public int Native_CDirector_IsTankInPlay(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_IsTankInPlay, "IsTankInPlay"); + ValidateNatives(g_hSDK_CDirector_IsTankInPlay, "CDirector_IsTankInPlay"); - //PrintToServer("#### CALL g_hSDK_Call_IsTankInPlay"); - return SDKCall(g_hSDK_Call_IsTankInPlay, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_IsTankInPlay"); + return SDKCall(g_hSDK_CDirector_IsTankInPlay, g_pDirector); } -public int Native_IsReachable(Handle plugin, int numParams) +public int Native_SurvivorBot_IsReachable(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_IsReachable, "IsReachable"); + ValidateNatives(g_hSDK_SurvivorBot_IsReachable, "SurvivorBot::IsReachable"); int client = GetNativeCell(1); @@ -4994,26 +5308,26 @@ public int Native_IsReachable(Handle plugin, int numParams) float vPos[3]; GetNativeArray(2, vPos, 3); - //PrintToServer("#### CALL g_hSDK_Call_IsReachable"); - return SDKCall(g_hSDK_Call_IsReachable, client, vPos); + //PrintToServer("#### CALL g_hSDK_SurvivorBot_IsReachable"); + return SDKCall(g_hSDK_SurvivorBot_IsReachable, client, vPos); } -public any Native_GetFurthestSurvivorFlow(Handle plugin, int numParams) +public any Native_CDirector_GetFurthestSurvivorFlow(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_GetFurthestSurvivorFlow, "GetFurthestSurvivorFlow"); + ValidateNatives(g_hSDK_CDirector_GetFurthestSurvivorFlow, "CDirector::GetFurthestSurvivorFlow"); - //PrintToServer("#### CALL g_hSDK_Call_GetFurthestSurvivorFlow"); - return SDKCall(g_hSDK_Call_GetFurthestSurvivorFlow, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_GetFurthestSurvivorFlow"); + return SDKCall(g_hSDK_CDirector_GetFurthestSurvivorFlow, g_pDirector); } public int Native_NavAreaTravelDistance(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_NavAreaTravelDistance, "NavAreaTravelDistance"); + ValidateNatives(g_hSDK_NavAreaTravelDistance, "NavAreaTravelDistance"); float vPos[3], vEnd[3]; @@ -5021,16 +5335,16 @@ public int Native_NavAreaTravelDistance(Handle plugin, int numParams) GetNativeArray(2, vEnd, sizeof(vEnd)); int a3 = GetNativeCell(3); - //PrintToServer("#### CALL g_hSDK_Call_NavAreaTravelDistance"); - return SDKCall(g_hSDK_Call_NavAreaTravelDistance, vPos, vEnd, a3); + //PrintToServer("#### CALL g_hSDK_NavAreaTravelDistance"); + return SDKCall(g_hSDK_NavAreaTravelDistance, vPos, vEnd, a3); } -public int Native_GetScriptValueInt(Handle plugin, int numParams) +public int Native_CDirector_GetScriptValueInt(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_GetScriptValueInt, "GetScriptValueInt"); + ValidateNatives(g_hSDK_CDirector_GetScriptValueInt, "CDirector::GetScriptValueInt"); int maxlength; GetNativeStringLength(1, maxlength); @@ -5040,15 +5354,15 @@ public int Native_GetScriptValueInt(Handle plugin, int numParams) int value = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_GetScriptValueInt"); - return SDKCall(g_hSDK_Call_GetScriptValueInt, g_pDirector, key, value); + //PrintToServer("#### CALL g_hSDK_CDirector_GetScriptValueInt"); + return SDKCall(g_hSDK_CDirector_GetScriptValueInt, g_pDirector, key, value); } /* // Only returns default value provided. -public any Native_GetScriptValueFloat(Handle plugin, int numParams) +public any Native_CDirector_GetScriptValueFloat(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_GetScriptValueFloat, "GetScriptValueFloat"); + ValidateNatives(g_hSDK_CDirector_GetScriptValueFloat, "CDirector::GetScriptValueFloat"); int maxlength; GetNativeStringLength(1, maxlength); @@ -5058,15 +5372,15 @@ public any Native_GetScriptValueFloat(Handle plugin, int numParams) float value = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_GetScriptValueFloat"); - return SDKCall(g_hSDK_Call_GetScriptValueFloat, g_pDirector, key, value); + //PrintToServer("#### CALL g_hSDK_CDirector_GetScriptValueFloat"); + return SDKCall(g_hSDK_CDirector_GetScriptValueFloat, g_pDirector, key, value); } // Not implemented, request if really required. -public int Native_GetScriptValueString(Handle plugin, int numParams) +public int Native_CDirector_GetScriptValueString(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_GetScriptValueString, "GetScriptValueString"); + ValidateNatives(g_hSDK_CDirector_GetScriptValueString, "CDirector::GetScriptValueString"); // Key int maxlength; @@ -5085,8 +5399,8 @@ public int Native_GetScriptValueString(Handle plugin, int numParams) maxlength = GetNativeCell(4); char[] retValue = new char[maxlength]; - //PrintToServer("#### CALL g_hSDK_Call_GetScriptValueString"); - SDKCall(g_hSDK_Call_GetScriptValueString, g_pDirector, key, value, retValue, maxlength); + //PrintToServer("#### CALL g_hSDK_CDirector_GetScriptValueString"); + SDKCall(g_hSDK_CDirector_GetScriptValueString, g_pDirector, key, value, retValue, maxlength); SetNativeString(3, retValue, maxlength); } */ @@ -5102,21 +5416,21 @@ public int Native_ScavengeBeginRoundSetupTime(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(ScavengeModePtr, "ScavengeModePtr"); - ValidateAddress(OnBeginRoundSetupTime, "OnBeginRoundSetupTime"); + ValidateAddress(g_pScavengeMode, "ScavengeModePtr"); + ValidateAddress(g_iOff_OnBeginRoundSetupTime, "OnBeginRoundSetupTime"); - return LoadFromAddress(view_as
    (ScavengeModePtr + OnBeginRoundSetupTime + 4), NumberType_Int32); + return LoadFromAddress(view_as
    (g_pScavengeMode + g_iOff_OnBeginRoundSetupTime + 4), NumberType_Int32); } -public int Native_ResetMobTimer(Handle plugin, int numParams) +public int Native_CDirector_ResetMobTimer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_ResetMobTimer, "ResetMobTimer"); + ValidateNatives(g_hSDK_CDirector_ResetMobTimer, "CDirector::ResetMobTimer"); - //PrintToServer("#### CALL g_hSDK_Call_ResetMobTimer"); - SDKCall(g_hSDK_Call_ResetMobTimer, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_ResetMobTimer"); + SDKCall(g_hSDK_CDirector_ResetMobTimer, g_pDirector); return 0; } @@ -5124,72 +5438,72 @@ public any Native_GetPlayerSpawnTime(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(SpawnTimer, "SpawnTimer"); + ValidateAddress(g_iOff_SpawnTimer, "SpawnTimer"); int client = GetNativeCell(1); - return (view_as(LoadFromAddress(GetEntityAddress(client) + view_as
    (SpawnTimer + 8), NumberType_Int32)) - GetGameTime()); + return (view_as(LoadFromAddress(GetEntityAddress(client) + view_as
    (g_iOff_SpawnTimer + 8), NumberType_Int32)) - GetGameTime()); } -public int Native_RestartScenarioFromVote(Handle plugin, int numParams) +public int Native_CDirector_RestartScenarioFromVote(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_RestartScenarioFromVote, "RestartScenarioFromVote"); + ValidateNatives(g_hSDK_CDirector_RestartScenarioFromVote, "CDirector::RestartScenarioFromVote"); char map[64]; GetNativeString(1, map, sizeof(map)); - //PrintToServer("#### CALL g_hSDK_Call_RestartScenarioFromVote"); - return SDKCall(g_hSDK_Call_RestartScenarioFromVote, g_pDirector, map); + //PrintToServer("#### CALL g_hSDK_CDirector_RestartScenarioFromVote"); + return SDKCall(g_hSDK_CDirector_RestartScenarioFromVote, g_pDirector, map); } public int Native_GetVersusMaxCompletionScore(Handle plugin, int numParams) { ValidateAddress(g_pGameRules, "g_pGameRules"); - ValidateAddress(VersusMaxCompletionScore, "VersusMaxCompletionScore"); + ValidateAddress(g_iOff_VersusMaxCompletionScore, "VersusMaxCompletionScore"); if( g_bLeft4Dead2 ) { - return LoadFromAddress(g_pGameRules + view_as
    (VersusMaxCompletionScore), NumberType_Int32); + return LoadFromAddress(g_pGameRules + view_as
    (g_iOff_VersusMaxCompletionScore), NumberType_Int32); } else { - ValidateAddress(m_chapter, "m_chapter"); + ValidateAddress(g_iOff_m_chapter, "m_chapter"); - int chapter = LoadFromAddress(g_pDirector + view_as
    (m_chapter), NumberType_Int32); - return LoadFromAddress(g_pGameRules + view_as
    (chapter * 4 + VersusMaxCompletionScore), NumberType_Int32); + int chapter = LoadFromAddress(g_pDirector + view_as
    (g_iOff_m_chapter), NumberType_Int32); + return LoadFromAddress(g_pGameRules + view_as
    (chapter * 4 + g_iOff_VersusMaxCompletionScore), NumberType_Int32); } } public int Native_SetVersusMaxCompletionScore(Handle plugin, int numParams) { ValidateAddress(g_pGameRules, "g_pGameRules"); - ValidateAddress(VersusMaxCompletionScore, "VersusMaxCompletionScore"); + ValidateAddress(g_iOff_VersusMaxCompletionScore, "VersusMaxCompletionScore"); int value = GetNativeCell(1); if( g_bLeft4Dead2 ) { - StoreToAddress(g_pGameRules + view_as
    (VersusMaxCompletionScore), value, NumberType_Int32); + StoreToAddress(g_pGameRules + view_as
    (g_iOff_VersusMaxCompletionScore), value, NumberType_Int32); } else { - ValidateAddress(m_chapter, "m_chapter"); + ValidateAddress(g_iOff_m_chapter, "m_chapter"); - int chapter = LoadFromAddress(g_pDirector + view_as
    (m_chapter), NumberType_Int32); - StoreToAddress(g_pGameRules + view_as
    (chapter * 4 + VersusMaxCompletionScore), value, NumberType_Int32); + int chapter = LoadFromAddress(g_pDirector + view_as
    (g_iOff_m_chapter), NumberType_Int32); + StoreToAddress(g_pGameRules + view_as
    (chapter * 4 + g_iOff_VersusMaxCompletionScore), value, NumberType_Int32); } return 0; } -public int Native_GetTeamScore(Handle plugin, int numParams) +public int Native_CTerrorGameRules_GetTeamScore(Handle plugin, int numParams) { // #define SCORE_TEAM_A 1 // #define SCORE_TEAM_B 2 #define SCORE_TYPE_ROUND 0 #define SCORE_TYPE_CAMPAIGN 1 - ValidateNatives(g_hSDK_Call_GetTeamScore, "GetTeamScore"); + ValidateNatives(g_hSDK_CTerrorGameRules_GetTeamScore, "CTerrorGameRules::GetTeamScore"); //sanity check that the team index is valid int team = GetNativeCell(1); @@ -5205,23 +5519,23 @@ public int Native_GetTeamScore(Handle plugin, int numParams) ThrowNativeError(SP_ERROR_PARAM, "campaign_score %d is invalid. Accepted values: 0 or 1", score); } - //PrintToServer("#### CALL g_hSDK_Call_GetTeamScore"); - return SDKCall(g_hSDK_Call_GetTeamScore, team, score); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_GetTeamScore"); + return SDKCall(g_hSDK_CTerrorGameRules_GetTeamScore, team, score); } -public int Native_IsFirstMapInScenario(Handle plugin, int numParams) +public int Native_CDirector_IsFirstMapInScenario(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_IsFirstMapInScenario, "IsFirstMapInScenario"); + ValidateNatives(g_hSDK_CDirector_IsFirstMapInScenario, "CDirector::IsFirstMapInScenario"); if( !g_bLeft4Dead2 ) { - ValidateNatives(g_hSDK_Call_KV_GetString, "KV_GetString"); + ValidateNatives(g_hSDK_KeyValues_GetString, "KV_GetString"); static char sMap[64], check[64]; /* // NULL PTR - METHOD (kept for demonstration) // "malloc" replacement hack (method by @Rostu) - Address pNull = GetEntityAddress(0) + view_as
    (m_iClrRender); + Address pNull = GetEntityAddress(0) + view_as
    (g_iOff_m_iClrRender); // Save old value int iRestore = LoadFromAddress(pNull, NumberType_Int32); @@ -5237,12 +5551,12 @@ public int Native_IsFirstMapInScenario(Handle plugin, int numParams) // Should be 0 to match the original call arguments StoreToAddress(pNull, 0, NumberType_Int32); - //PrintToServer("#### CALL g_hSDK_Call_IsFirstMapInScenario"); - int keyvalue = SDKCall(g_hSDK_Call_IsFirstMapInScenario, pNull); // NULL PTR - METHOD (kept for demonstration) + //PrintToServer("#### CALL g_hSDK_CDirector_IsFirstMapInScenario"); + int keyvalue = SDKCall(g_hSDK_CDirector_IsFirstMapInScenario, pNull); // NULL PTR - METHOD (kept for demonstration) // */ - //PrintToServer("#### CALL g_hSDK_Call_IsFirstMapInScenario"); - int keyvalue = SDKCall(g_hSDK_Call_IsFirstMapInScenario, 0); + //PrintToServer("#### CALL g_hSDK_CDirector_IsFirstMapInScenario"); + int keyvalue = SDKCall(g_hSDK_CDirector_IsFirstMapInScenario, 0); // Restore the old value // StoreToAddress(pNull, iRestore, NumberType_Int32); // NULL PTR - METHOD (kept for demonstration) @@ -5264,8 +5578,8 @@ public int Native_IsFirstMapInScenario(Handle plugin, int numParams) if( keyvalue ) { - //PrintToServer("#### CALL g_hSDK_Call_KV_GetString"); - SDKCall(g_hSDK_Call_KV_GetString, keyvalue, check, sizeof(check), "map", "N/A"); + //PrintToServer("#### CALL g_hSDK_KeyValues_GetString"); + SDKCall(g_hSDK_KeyValues_GetString, keyvalue, check, sizeof(check), "map", "N/A"); GetCurrentMap(sMap, sizeof(sMap)); return strcmp(sMap, check) == 0; @@ -5274,30 +5588,30 @@ public int Native_IsFirstMapInScenario(Handle plugin, int numParams) return 0; } - //PrintToServer("#### CALL g_hSDK_Call_IsFirstMapInScenario"); - return SDKCall(g_hSDK_Call_IsFirstMapInScenario, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_IsFirstMapInScenario"); + return SDKCall(g_hSDK_CDirector_IsFirstMapInScenario, g_pDirector); } -public int Native_IsMissionFinalMap(Handle plugin, int numParams) +public int Native_CTerrorGameRules_IsMissionFinalMap(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_IsMissionFinalMap, "IsMissionFinalMap"); + ValidateNatives(g_hSDK_CTerrorGameRules_IsMissionFinalMap, "CTerrorGameRules::IsMissionFinalMap"); - //PrintToServer("#### CALL g_hSDK_Call_IsMissionFinalMap"); - return SDKCall(g_hSDK_Call_IsMissionFinalMap); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_IsMissionFinalMap"); + return SDKCall(g_hSDK_CTerrorGameRules_IsMissionFinalMap); } -public int Native_NotifyNetworkStateChanged(Handle plugin, int numParams) +public int Native_CGameRulesProxy_NotifyNetworkStateChanged(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_NotifyNetworkStateChanged, "NotifyNetworkStateChanged"); + ValidateNatives(g_hSDK_CGameRulesProxy_NotifyNetworkStateChanged, "CGameRulesProxy::NotifyNetworkStateChanged"); - //PrintToServer("#### CALL g_hSDK_Call_NotifyNetworkStateChanged"); - SDKCall(g_hSDK_Call_NotifyNetworkStateChanged); + //PrintToServer("#### CALL g_hSDK_CGameRulesProxy_NotifyNetworkStateChanged"); + SDKCall(g_hSDK_CGameRulesProxy_NotifyNetworkStateChanged); return 0; } -public int Native_StaggerPlayer(Handle plugin, int numParams) +public int Native_CTerrorPlayer_OnStaggered(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_StaggerPlayer, "StaggerPlayer"); + ValidateNatives(g_hSDK_CTerrorPlayer_OnStaggered, "CTerrorPlayer::OnStaggered"); int a1 = GetNativeCell(1); int a2 = GetNativeCell(2); @@ -5309,14 +5623,14 @@ public int Native_StaggerPlayer(Handle plugin, int numParams) GetEntPropVector(a2, Prop_Send, "m_vecOrigin", vDir); } - //PrintToServer("#### CALL g_hSDK_Call_StaggerPlayer"); - SDKCall(g_hSDK_Call_StaggerPlayer, a1, a2, vDir); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_OnStaggered"); + SDKCall(g_hSDK_CTerrorPlayer_OnStaggered, a1, a2, vDir); return 0; } -public int Native_ReplaceTank(Handle plugin, int numParams) +public int Native_ZombieManager_ReplaceTank(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_ReplaceTank, "ReplaceTank"); + ValidateNatives(g_hSDK_ZombieManager_ReplaceTank, "ZombieManager::ReplaceTank"); int oldtank = GetNativeCell(1); int newtank = GetNativeCell(2); @@ -5332,55 +5646,55 @@ public int Native_ReplaceTank(Handle plugin, int numParams) // GetClientEyePosition(oldtank, vOld); // GetClientAbsOrigin(newtank, vNew); - //PrintToServer("#### CALL g_hSDK_Call_ReplaceTank"); - SDKCall(g_hSDK_Call_ReplaceTank, g_pZombieManager, oldtank, newtank); + //PrintToServer("#### CALL g_hSDK_ZombieManager_ReplaceTank"); + SDKCall(g_hSDK_ZombieManager_ReplaceTank, g_pZombieManager, oldtank, newtank); // TeleportEntity(oldtank, vOld, vAng, NULL_VECTOR); // TeleportEntity(newtank, vNew, NULL_VECTOR, NULL_VECTOR); return 0; } -public int Native_SendInRescueVehicle(Handle plugin, int numParams) +public int Native_CDirectorScriptedEventManager_SendInRescueVehicle(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_SendInRescueVehicle, "SendInRescueVehicle"); - if( g_bLeft4Dead2 ) ValidateAddress(ScriptedEventManagerPtr, "ScriptedEventManagerPtr"); + ValidateNatives(g_hSDK_CDirectorScriptedEventManager_SendInRescueVehicle, "CDirectorScriptedEventManager::SendInRescueVehicle"); + if( g_bLeft4Dead2 ) ValidateAddress(g_pScriptedEventManager, "ScriptedEventManagerPtr"); else ValidateAddress(g_pDirector, "g_pDirector"); - //PrintToServer("#### CALL g_hSDK_Call_SendInRescueVehicle"); - SDKCall(g_hSDK_Call_SendInRescueVehicle, g_bLeft4Dead2 ? ScriptedEventManagerPtr : view_as(g_pDirector)); + //PrintToServer("#### CALL g_hSDK_CDirectorScriptedEventManager_SendInRescueVehicle"); + SDKCall(g_hSDK_CDirectorScriptedEventManager_SendInRescueVehicle, g_bLeft4Dead2 ? g_pScriptedEventManager : view_as(g_pDirector)); return 0; } -public int Native_ChangeFinaleStage(Handle plugin, int numParams) +public int Native_CDirectorScriptedEventManager_ChangeFinaleStage(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(ScriptedEventManagerPtr, "ScriptedEventManagerPtr"); - ValidateNatives(g_hSDK_Call_ChangeFinaleStage, "ChangeFinaleStage"); + ValidateAddress(g_pScriptedEventManager, "ScriptedEventManagerPtr"); + ValidateNatives(g_hSDK_CDirectorScriptedEventManager_ChangeFinaleStage, "CDirectorScriptedEventManager::ChangeFinaleStage"); static char arg[64]; int finaleType = GetNativeCell(1); GetNativeString(2, arg, sizeof(arg)); - //PrintToServer("#### CALL g_hSDK_Call_ChangeFinaleStage"); - SDKCall(g_hSDK_Call_ChangeFinaleStage, ScriptedEventManagerPtr, finaleType, arg); + //PrintToServer("#### CALL g_hSDK_CDirectorScriptedEventManager_ChangeFinaleStage"); + SDKCall(g_hSDK_CDirectorScriptedEventManager_ChangeFinaleStage, g_pScriptedEventManager, finaleType, arg); return 0; } -public int Native_SpawnTank(Handle plugin, int numParams) +public int Native_ZombieManager_SpawnTank(Handle plugin, int numParams) { ValidateAddress(g_pZombieManager, "g_pZombieManager"); - ValidateNatives(g_hSDK_Call_SpawnTank, "SpawnTank"); + ValidateNatives(g_hSDK_ZombieManager_SpawnTank, "ZombieManager::SpawnTank"); float vPos[3], vAng[3]; GetNativeArray(1, vPos, 3); GetNativeArray(2, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_SpawnTank"); - return SDKCall(g_hSDK_Call_SpawnTank, g_pZombieManager, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnTank"); + return SDKCall(g_hSDK_ZombieManager_SpawnTank, g_pZombieManager, vPos, vAng); } -public int Native_SpawnSpecial(Handle plugin, int numParams) +public int Native_ZombieManager_SpawnSpecial(Handle plugin, int numParams) { ValidateAddress(g_pZombieManager, "g_pZombieManager"); @@ -5391,10 +5705,10 @@ public int Native_SpawnSpecial(Handle plugin, int numParams) if( g_bLeft4Dead2 ) { - ValidateNatives(g_hSDK_Call_SpawnSpecial, "SpawnSpecial"); + ValidateNatives(g_hSDK_ZombieManager_SpawnSpecial, "ZombieManager::SpawnSpecial"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnSpecial"); - return SDKCall(g_hSDK_Call_SpawnSpecial, g_pZombieManager, zombieClass, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnSpecial"); + return SDKCall(g_hSDK_ZombieManager_SpawnSpecial, g_pZombieManager, zombieClass, vPos, vAng); } else { @@ -5402,24 +5716,24 @@ public int Native_SpawnSpecial(Handle plugin, int numParams) { case 1: { - ValidateNatives(g_hSDK_Call_SpawnSmoker, "SpawnSmoker"); + ValidateNatives(g_hSDK_ZombieManager_SpawnSmoker, "ZombieManager::SpawnSmoker"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnSmoker"); - return SDKCall(g_hSDK_Call_SpawnSmoker, g_pZombieManager, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnSmoker"); + return SDKCall(g_hSDK_ZombieManager_SpawnSmoker, g_pZombieManager, vPos, vAng); } case 2: { - ValidateNatives(g_hSDK_Call_SpawnBoomer, "SpawnBoomer"); + ValidateNatives(g_hSDK_ZombieManager_SpawnBoomer, "ZombieManager::SpawnBoomer"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnBoomer"); - return SDKCall(g_hSDK_Call_SpawnBoomer, g_pZombieManager, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnBoomer"); + return SDKCall(g_hSDK_ZombieManager_SpawnBoomer, g_pZombieManager, vPos, vAng); } case 3: { - ValidateNatives(g_hSDK_Call_SpawnHunter, "SpawnHunter"); + ValidateNatives(g_hSDK_ZombieManager_SpawnHunter, "ZombieManager::SpawnHunter"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnHunter"); - return SDKCall(g_hSDK_Call_SpawnHunter, g_pZombieManager, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnHunter"); + return SDKCall(g_hSDK_ZombieManager_SpawnHunter, g_pZombieManager, vPos, vAng); } } } @@ -5427,59 +5741,61 @@ public int Native_SpawnSpecial(Handle plugin, int numParams) return 0; } -public int Native_SpawnWitch(Handle plugin, int numParams) +public int Native_ZombieManager_SpawnWitch(Handle plugin, int numParams) { ValidateAddress(g_pZombieManager, "g_pZombieManager"); - ValidateNatives(g_hSDK_Call_SpawnWitch, "SpawnWitch"); + ValidateNatives(g_hSDK_ZombieManager_SpawnWitch, "ZombieManager::SpawnWitch"); float vPos[3], vAng[3]; GetNativeArray(1, vPos, 3); GetNativeArray(2, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_SpawnWitch"); - return SDKCall(g_hSDK_Call_SpawnWitch, g_pZombieManager, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnWitch"); + return SDKCall(g_hSDK_ZombieManager_SpawnWitch, g_pZombieManager, vPos, vAng); } -public int Native_SpawnWitchBride(Handle plugin, int numParams) +public int Native_ZombieManager_SpawnWitchBride(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pZombieManager, "g_pZombieManager"); - ValidateNatives(g_hSDK_Call_SpawnWitchBride, "SpawnWitchBride"); + ValidateNatives(g_hSDK_ZombieManager_SpawnWitchBride, "ZombieManager::SpawnWitchBride"); float vPos[3], vAng[3]; GetNativeArray(1, vPos, 3); GetNativeArray(2, vAng, 3); - //PrintToServer("#### CALL g_hSDK_Call_SpawnWitchBride"); - return SDKCall(g_hSDK_Call_SpawnWitchBride, g_pZombieManager, vPos, vAng); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnWitchBride"); + return SDKCall(g_hSDK_ZombieManager_SpawnWitchBride, g_pZombieManager, vPos, vAng); } public any Native_GetMobSpawnTimerRemaining(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateAddress(MobSpawnTimer, "MobSpawnTimer"); + ValidateAddress(g_iOff_MobSpawnTimer, "MobSpawnTimer"); - float timestamp = view_as(LoadFromAddress(g_pDirector + view_as
    (MobSpawnTimer + 8), NumberType_Int32)); + float timestamp = view_as(LoadFromAddress(g_pDirector + view_as
    (g_iOff_MobSpawnTimer + 8), NumberType_Int32)); return timestamp - GetGameTime(); } public any Native_GetMobSpawnTimerDuration(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateAddress(MobSpawnTimer, "MobSpawnTimer"); + ValidateAddress(g_iOff_MobSpawnTimer, "MobSpawnTimer"); - float duration = view_as(LoadFromAddress(g_pDirector + view_as
    (MobSpawnTimer + 4), NumberType_Int32)); + float duration = view_as(LoadFromAddress(g_pDirector + view_as
    (g_iOff_MobSpawnTimer + 4), NumberType_Int32)); return duration > 0.0 ? duration : 0.0; } -public int Native_LobbyUnreserve(Handle plugin, int numParams) +public int Native_CBaseServer_SetReservationCookie(Handle plugin, int numParams) { ValidateAddress(g_pServer, "g_pServer"); - ValidateNatives(g_hSDK_Call_LobbyUnreserve, "LobbyUnreserve"); + ValidateNatives(g_hSDK_CBaseServer_SetReservationCookie, "CBaseServer::SetReservationCookie"); + + //PrintToServer("#### CALL g_hSDK_CBaseServer_SetReservationCookie"); + SDKCall(g_hSDK_CBaseServer_SetReservationCookie, g_pServer, 0, 0, "Unreserved by Left 4 DHooks"); - //PrintToServer("#### CALL g_hSDK_Call_LobbyUnreserve"); - SDKCall(g_hSDK_Call_LobbyUnreserve, g_pServer, 0, 0, "Unreserved by Left 4 DHooks"); + return 0; } //DEPRECATED @@ -5500,7 +5816,7 @@ public int Native_LobbyUnreserve(Handle plugin, int numParams) int GetWeaponPointer() { ValidateAddress(g_pWeaponInfoDatabase, "g_pWeaponInfoDatabase"); - ValidateNatives(g_hSDK_Call_GetWeaponInfo, "GetWeaponInfo"); + ValidateNatives(g_hSDK_GetWeaponInfo, "GetWeaponInfo"); static char weaponName[32]; GetNativeString(1, weaponName, sizeof(weaponName)); @@ -5520,8 +5836,8 @@ int GetWeaponPointer() return -1; } - //PrintToServer("#### CALL g_hSDK_Call_GetWeaponInfo"); - if( ptr ) ptr = SDKCall(g_hSDK_Call_GetWeaponInfo, ptr); + //PrintToServer("#### CALL g_hSDK_GetWeaponInfo"); + if( ptr ) ptr = SDKCall(g_hSDK_GetWeaponInfo, ptr); if( ptr ) g_aWeaponPtrs.SetValue(weaponName, ptr); } @@ -5532,13 +5848,13 @@ int GetWeaponPointer() int GetMeleePointer(int id) { ValidateAddress(g_pMeleeWeaponInfoStore, "g_pMeleeWeaponInfoStore"); - ValidateNatives(g_hSDK_Call_GetMeleeInfo, "GetMeleeInfo"); + ValidateNatives(g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo, "CMeleeWeaponInfoStore::GetMeleeWeaponInfo"); int ptr = g_aMeleePtrs.FindValue(id, 0); if( ptr == -1 ) { - //PrintToServer("#### CALL g_hSDK_Call_GetMeleeInfo"); - ptr = SDKCall(g_hSDK_Call_GetMeleeInfo, g_pMeleeWeaponInfoStore, id); + //PrintToServer("#### CALL g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo"); + ptr = SDKCall(g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo, g_pMeleeWeaponInfoStore, id); if( ptr ) { @@ -5563,17 +5879,34 @@ int GetMeleePointer(int id) // ================================================== // Natives // ================================================== -public int Native_IsValidWeapon(Handle plugin, int numParams) +public int Native_GetWeaponID(Handle plugin, int numParams) { - if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); + static char weaponName[32]; + GetNativeString(1, weaponName, sizeof(weaponName)); + + // Add "weapon_" if missing, required for usage with stored StringMap. + if( strncmp(weaponName, "weapon_", 7) ) + { + Format(weaponName, sizeof(weaponName), "weapon_%s", weaponName); + } + + int wepID; + + if( g_aWeaponIDs.GetValue(weaponName, wepID) == false ) + { + return -1; + } + return wepID; +} + +public int Native_IsValidWeapon(Handle plugin, int numParams) +{ return GetWeaponPointer() != -1; } public int Native_GetIntWeaponAttribute(Handle plugin, int numParams) { - if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - int attr = GetNativeCell(2); if( attr >= view_as(MAX_SIZE_L4D2IntWeaponAttributes) ) // view_as to avoid tag mismatch from enum "type" ThrowNativeError(SP_ERROR_PARAM, "Invalid attribute id"); @@ -5590,8 +5923,6 @@ public int Native_GetIntWeaponAttribute(Handle plugin, int numParams) public any Native_GetFloatWeaponAttribute(Handle plugin, int numParams) { - if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - int attr = GetNativeCell(2); if( attr >= view_as(MAX_SIZE_L4D2FloatWeaponAttributes) ) // view_as to avoid tag mismatch from enum "type" ThrowNativeError(SP_ERROR_PARAM, "Invalid attribute id"); @@ -5608,8 +5939,6 @@ public any Native_GetFloatWeaponAttribute(Handle plugin, int numParams) public int Native_SetIntWeaponAttribute(Handle plugin, int numParams) { - if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - int attr = GetNativeCell(2); if( attr >= view_as(MAX_SIZE_L4D2IntWeaponAttributes) ) // view_as to avoid tag mismatch from enum "type" ThrowNativeError(SP_ERROR_PARAM, "Invalid attribute id"); @@ -5617,8 +5946,16 @@ public int Native_SetIntWeaponAttribute(Handle plugin, int numParams) int ptr = GetWeaponPointer(); if( ptr != -1 ) { - attr = L4D2IntWeapon_Offsets[attr]; // Offset - StoreToAddress(view_as
    (ptr + attr), GetNativeCell(3), NumberType_Int32); + if( !g_bLeft4Dead2 && attr == view_as(L4D2FWA_PenetrationNumLayers) ) + { + attr = L4D2IntWeapon_Offsets[attr]; // Offset + StoreToAddress(view_as
    (ptr + attr), RoundToCeil(GetNativeCell(3)), NumberType_Int32); + } + else + { + attr = L4D2IntWeapon_Offsets[attr]; // Offset + StoreToAddress(view_as
    (ptr + attr), GetNativeCell(3), NumberType_Int32); + } } return ptr; @@ -5626,8 +5963,6 @@ public int Native_SetIntWeaponAttribute(Handle plugin, int numParams) public int Native_SetFloatWeaponAttribute(Handle plugin, int numParams) { - if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - int attr = GetNativeCell(2); if( attr >= view_as(MAX_SIZE_L4D2FloatWeaponAttributes) ) // view_as to avoid tag mismatch from enum "type" ThrowNativeError(SP_ERROR_PARAM, "Invalid attribute id"); @@ -5644,8 +5979,6 @@ public int Native_SetFloatWeaponAttribute(Handle plugin, int numParams) public int Native_GetMeleeWeaponIndex(Handle plugin, int numParams) { - if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - static char weaponName[32]; GetNativeString(1, weaponName, sizeof(weaponName)); @@ -5727,6 +6060,8 @@ public int Native_SetIntMeleeAttribute(Handle plugin, int numParams) attr = L4D2IntMeleeWeapon_Offsets[attr]; // Offset StoreToAddress(view_as
    (ptr + attr), value, NumberType_Int32); } + + return 0; } public int Native_SetFloatMeleeAttribute(Handle plugin, int numParams) @@ -5744,6 +6079,8 @@ public int Native_SetFloatMeleeAttribute(Handle plugin, int numParams) attr = L4D2FloatMeleeWeapon_Offsets[attr]; // Offset StoreToAddress(view_as
    (ptr + attr), view_as(value), NumberType_Int32); } + + return 0; } public int Native_SetBoolMeleeAttribute(Handle plugin, int numParams) @@ -5761,6 +6098,8 @@ public int Native_SetBoolMeleeAttribute(Handle plugin, int numParams) attr = L4D2BoolMeleeWeapon_Offsets[attr]; // Offset StoreToAddress(view_as
    (ptr + attr), value, NumberType_Int32); } + + return 0; } @@ -5781,6 +6120,8 @@ public int Native_CTimerReset(Handle plugin, int numParams) float timestamp = GetGameTime(); StoreToAddress(view_as
    (off + 8), view_as(timestamp), NumberType_Int32); + + return 0; } public int Native_CTimerStart(Handle plugin, int numParams) @@ -5796,6 +6137,8 @@ public int Native_CTimerStart(Handle plugin, int numParams) StoreToAddress(view_as
    (off + 4), view_as(duration), NumberType_Int32); StoreToAddress(view_as
    (off + 8), view_as(timestamp), NumberType_Int32); + + return 0; } public int Native_CTimerInvalidate(Handle plugin, int numParams) @@ -5809,6 +6152,8 @@ public int Native_CTimerInvalidate(Handle plugin, int numParams) float timestamp = -1.0; StoreToAddress(view_as
    (off + 8), view_as(timestamp), NumberType_Int32); + + return 0; } public int Native_CTimerHasStarted(Handle plugin, int numParams) @@ -5892,6 +6237,8 @@ public int Native_ITimerStart(Handle plugin, int numParams) float timestamp = GetGameTime(); StoreToAddress(view_as
    (off + 4), view_as(timestamp), NumberType_Int32); + + return 0; } public int Native_ITimerInvalidate(Handle plugin, int numParams) @@ -5905,6 +6252,8 @@ public int Native_ITimerInvalidate(Handle plugin, int numParams) float timestamp = -1.0; StoreToAddress(view_as
    (off + 4), view_as(timestamp), NumberType_Int32); + + return 0; } public int Native_ITimerHasStarted(Handle plugin, int numParams) @@ -5942,7 +6291,7 @@ public int Native_GetTankCount(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - int val = LoadFromAddress(g_pDirector + view_as
    (m_iTankCount), NumberType_Int32); + int val = LoadFromAddress(g_pDirector + view_as
    (g_iOff_m_iTankCount), NumberType_Int32); return val; } @@ -5955,7 +6304,7 @@ public int Native_GetWitchCount(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - val = LoadFromAddress(g_pDirector + view_as
    (m_iWitchCount), NumberType_Int32); + val = LoadFromAddress(g_pDirector + view_as
    (g_iOff_m_iWitchCount), NumberType_Int32); } else { int entity = -1; while( (entity = FindEntityByClassname(entity, "witch")) != INVALID_ENT_REFERENCE ) @@ -5969,40 +6318,40 @@ public int Native_GetWitchCount(Handle plugin, int numParams) public int Native_GetCurrentChapter(Handle plugin, int numParams) { - ValidateAddress(m_chapter, "m_chapter"); + ValidateAddress(g_iOff_m_chapter, "m_chapter"); - return LoadFromAddress(g_pDirector + view_as
    (m_chapter), NumberType_Int32) + 1; + return LoadFromAddress(g_pDirector + view_as
    (g_iOff_m_chapter), NumberType_Int32) + 1; } -public int Native_GetMaxChapters(Handle plugin, int numParams) +public int Native_CTerrorGameRules_GetNumChaptersForMissionAndMode(Handle plugin, int numParams) { if( g_bLeft4Dead2 ) { - ValidateNatives(g_hSDK_Call_GetMaxChapters, "GetMaxChapters"); + ValidateNatives(g_hSDK_CTerrorGameRules_GetNumChaptersForMissionAndMode, "CTerrorGameRules::GetNumChaptersForMissionAndMode"); - //PrintToServer("#### CALL g_hSDK_Call_GetMaxChapters"); - return SDKCall(g_hSDK_Call_GetMaxChapters); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_GetNumChaptersForMissionAndMode"); + return SDKCall(g_hSDK_CTerrorGameRules_GetNumChaptersForMissionAndMode); } else { if( g_iMaxChapters == 0 ) { - ValidateNatives(g_hSDK_Call_KV_GetString, "KV_GetString"); - ValidateNatives(g_hSDK_Call_GetMissionInfo, "GetMissionInfo"); + ValidateNatives(g_hSDK_KeyValues_GetString, "KeyValues::GetString"); + ValidateNatives(g_hSDK_CTerrorGameRules_GetMissionInfo, "CTerrorGameRules::GetMissionInfo"); - //PrintToServer("#### CALL g_hSDK_Call_GetMissionInfo"); - int infoPointer = SDKCall(g_hSDK_Call_GetMissionInfo); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_GetMissionInfo"); + int infoPointer = SDKCall(g_hSDK_CTerrorGameRules_GetMissionInfo); char sMode[64]; char sTemp[64]; char sRet[64]; - g_hMPGameMode.GetString(sMode, sizeof(sMode)); + g_hCvar_MPGameMode.GetString(sMode, sizeof(sMode)); int index = 1; while( index < 20 ) { - Format(sTemp, sizeof(sTemp), "modes/%s/%d/Map", sMode, index); + FormatEx(sTemp, sizeof(sTemp), "modes/%s/%d/Map", sMode, index); - // PrintToServer("#### CALL g_hSDK_Call_KV_GetString"); - SDKCall(g_hSDK_Call_KV_GetString, infoPointer, sRet, sizeof(sRet), sTemp, ""); + // PrintToServer("#### CALL g_hSDK_KeyValues_GetString"); + SDKCall(g_hSDK_KeyValues_GetString, infoPointer, sRet, sizeof(sRet), sTemp, ""); if( strcmp(sRet, "") == 0 ) { @@ -6020,67 +6369,67 @@ public int Native_GetMaxChapters(Handle plugin, int numParams) return 0; } -public int Native_IsFinaleEscapeInProgress(Handle plugin, int numParams) +public int Native_CDirector_IsFinaleEscapeInProgress(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_IsFinaleEscapeInProgress, "IsFinaleEscapeInProgress"); + ValidateNatives(g_hSDK_CDirector_IsFinaleEscapeInProgress, "CDirector::IsFinaleEscapeInProgress"); ValidateAddress(g_pDirector, "g_pDirector"); - //PrintToServer("#### CALL g_hSDK_Call_IsFinaleEscapeInProgress"); - return SDKCall(g_hSDK_Call_IsFinaleEscapeInProgress, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_IsFinaleEscapeInProgress"); + return SDKCall(g_hSDK_CDirector_IsFinaleEscapeInProgress, g_pDirector); } -public int Native_SetHumanSpec(Handle plugin, int numParams) +public int Native_SurvivorBot_SetHumanSpectator(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_SetHumanSpec, "SetHumanSpec"); + ValidateNatives(g_hSDK_SurvivorBot_SetHumanSpectator, "SurvivorBot::SetHumanSpectator"); int bot = GetNativeCell(1); int client = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_SetHumanSpec"); - return SDKCall(g_hSDK_Call_SetHumanSpec, bot, client); + //PrintToServer("#### CALL g_hSDK_SurvivorBot_SetHumanSpectator"); + return SDKCall(g_hSDK_SurvivorBot_SetHumanSpectator, bot, client); } -public int Native_TakeOverBot(Handle plugin, int numParams) +public int Native_CTerrorPlayer_TakeOverBot(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_TakeOverBot, "TakeOverBot"); + ValidateNatives(g_hSDK_CTerrorPlayer_TakeOverBot, "CTerrorPlayer::TakeOverBot"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_TakeOverBot"); - return SDKCall(g_hSDK_Call_TakeOverBot, client, true); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_TakeOverBot"); + return SDKCall(g_hSDK_CTerrorPlayer_TakeOverBot, client, true); } -public int Native_CanBecomeGhost(Handle plugin, int numParams) +public int Native_CTerrorPlayer_CanBecomeGhost(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_CanBecomeGhost, "CanBecomeGhost"); + ValidateNatives(g_hSDK_CTerrorPlayer_CanBecomeGhost, "CTerrorPlayer::CanBecomeGhost"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_CanBecomeGhost"); - return SDKCall(g_hSDK_Call_CanBecomeGhost, client, true); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_CanBecomeGhost"); + return SDKCall(g_hSDK_CTerrorPlayer_CanBecomeGhost, client, true); } -public int Native_AreWanderersAllowed(Handle plugin, int numParams) +public int Native_CDirector_AreWanderersAllowed(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_AreWanderersAllowed, "AreWanderersAllowed"); + ValidateNatives(g_hSDK_CDirector_AreWanderersAllowed, "CDirector::AreWanderersAllowed"); ValidateAddress(g_pDirector, "g_pDirector"); - //PrintToServer("#### CALL g_hSDK_Call_AreWanderersAllowed"); - return SDKCall(g_hSDK_Call_AreWanderersAllowed, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_AreWanderersAllowed"); + return SDKCall(g_hSDK_CDirector_AreWanderersAllowed, g_pDirector); } public int Native_GetVersusCampaignScores(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(VersusModePtr, "m_iCampaignScores"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "m_iCampaignScores"); int vals[2]; - vals[0] = LoadFromAddress(view_as
    (VersusModePtr + m_iCampaignScores), NumberType_Int32); - vals[1] = LoadFromAddress(view_as
    (VersusModePtr + m_iCampaignScores + 4), NumberType_Int32); + vals[0] = LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_iCampaignScores), NumberType_Int32); + vals[1] = LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_iCampaignScores + 4), NumberType_Int32); SetNativeArray(1, vals, 2); return 0; @@ -6090,25 +6439,27 @@ public int Native_SetVersusCampaignScores(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(VersusModePtr, "m_iCampaignScores"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "m_iCampaignScores"); int vals[2]; GetNativeArray(1, vals, 2); - StoreToAddress(view_as
    (VersusModePtr + m_iCampaignScores), vals[0], NumberType_Int32); - StoreToAddress(view_as
    (VersusModePtr + m_iCampaignScores + 4), vals[1], NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_iCampaignScores), vals[0], NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_iCampaignScores + 4), vals[1], NumberType_Int32); + + return 0; } public int Native_GetVersusTankFlowPercent(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(VersusModePtr, "m_fTankSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "m_fTankSpawnFlowPercent"); float vals[2]; - vals[0] = view_as(LoadFromAddress(view_as
    (VersusModePtr + m_fTankSpawnFlowPercent), NumberType_Int32)); - vals[1] = view_as(LoadFromAddress(view_as
    (VersusModePtr + m_fTankSpawnFlowPercent + 4), NumberType_Int32)); + vals[0] = view_as(LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_fTankSpawnFlowPercent), NumberType_Int32)); + vals[1] = view_as(LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_fTankSpawnFlowPercent + 4), NumberType_Int32)); SetNativeArray(1, vals, 2); return 0; @@ -6118,25 +6469,27 @@ public int Native_SetVersusTankFlowPercent(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(VersusModePtr, "m_fTankSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "m_fTankSpawnFlowPercent"); float vals[2]; GetNativeArray(1, vals, 2); - StoreToAddress(view_as
    (VersusModePtr + m_fTankSpawnFlowPercent), view_as(vals[0]), NumberType_Int32); - StoreToAddress(view_as
    (VersusModePtr + m_fTankSpawnFlowPercent + 4), view_as(vals[1]), NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_fTankSpawnFlowPercent), view_as(vals[0]), NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_fTankSpawnFlowPercent + 4), view_as(vals[1]), NumberType_Int32); + + return 0; } public int Native_GetVersusWitchFlowPercent(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(VersusModePtr, "m_fWitchSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "m_fWitchSpawnFlowPercent"); float vals[2]; - vals[0] = view_as(LoadFromAddress(view_as
    (VersusModePtr + m_fWitchSpawnFlowPercent), NumberType_Int32)); - vals[1] = view_as(LoadFromAddress(view_as
    (VersusModePtr + m_fWitchSpawnFlowPercent + 4), NumberType_Int32)); + vals[0] = view_as(LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_fWitchSpawnFlowPercent), NumberType_Int32)); + vals[1] = view_as(LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_fWitchSpawnFlowPercent + 4), NumberType_Int32)); SetNativeArray(1, vals, 2); return 0; @@ -6146,13 +6499,15 @@ public int Native_SetVersusWitchFlowPercent(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(VersusModePtr, "m_fWitchSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "m_fWitchSpawnFlowPercent"); float vals[2]; GetNativeArray(1, vals, 2); - StoreToAddress(view_as
    (VersusModePtr + m_fWitchSpawnFlowPercent), view_as(vals[0]), NumberType_Int32); - StoreToAddress(view_as
    (VersusModePtr + m_fWitchSpawnFlowPercent + 4), view_as(vals[1]), NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_fWitchSpawnFlowPercent), view_as(vals[0]), NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_fWitchSpawnFlowPercent + 4), view_as(vals[1]), NumberType_Int32); + + return 0; } @@ -6170,26 +6525,28 @@ public int Direct_GetTankCount(Handle plugin, int numParams) public int Direct_GetPendingMobCount(Handle plugin, int numParams) { ValidateAddress(g_pZombieManager, "g_pZombieManager"); - ValidateAddress(m_PendingMobCount, "m_PendingMobCount"); + ValidateAddress(g_iOff_m_PendingMobCount, "m_PendingMobCount"); - return LoadFromAddress(g_pZombieManager + view_as
    (m_PendingMobCount), NumberType_Int32); + return LoadFromAddress(g_pZombieManager + view_as
    (g_iOff_m_PendingMobCount), NumberType_Int32); } public int Direct_SetPendingMobCount(Handle plugin, int numParams) { ValidateAddress(g_pZombieManager, "g_pZombieManager"); - ValidateAddress(m_PendingMobCount, "m_PendingMobCount"); + ValidateAddress(g_iOff_m_PendingMobCount, "m_PendingMobCount"); int count = GetNativeCell(1); - StoreToAddress(g_pZombieManager + view_as
    (m_PendingMobCount), count, NumberType_Int32); + StoreToAddress(g_pZombieManager + view_as
    (g_iOff_m_PendingMobCount), count, NumberType_Int32); + + return 0; } public any Direct_GetMobSpawnTimer(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateAddress(MobSpawnTimer, "MobSpawnTimer"); + ValidateAddress(g_iOff_MobSpawnTimer, "MobSpawnTimer"); - return view_as(g_pDirector + view_as
    (MobSpawnTimer)); + return view_as(g_pDirector + view_as
    (g_iOff_MobSpawnTimer)); } public any Direct_GetSIClassDeathTimer(Handle plugin, int numParams) @@ -6221,161 +6578,175 @@ public any Direct_GetSIClassSpawnTimer(Handle plugin, int numParams) public int Direct_GetTankPassedCount(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); + ValidateAddress(g_pDirector, "m_iTankPassedCount"); - return LoadFromAddress(g_pDirector + view_as
    (m_iTankPassedCount), NumberType_Int32); + return LoadFromAddress(g_pDirector + view_as
    (g_iOff_m_iTankPassedCount), NumberType_Int32); } public int Direct_SetTankPassedCount(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); + ValidateAddress(g_pDirector, "m_iTankPassedCount"); int passes = GetNativeCell(1); - StoreToAddress(g_pDirector + view_as
    (m_iTankPassedCount), passes, NumberType_Int32); + StoreToAddress(g_pDirector + view_as
    (g_iOff_m_iTankPassedCount), passes, NumberType_Int32); + + return 0; } public int Direct_GetVSCampaignScore(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_iCampaignScores, "m_iCampaignScores"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_iCampaignScores, "m_iCampaignScores"); int team = GetNativeCell(1); if( team < 0 || team > 1 ) return -1; - return LoadFromAddress(view_as
    (VersusModePtr + m_iCampaignScores + (team * 4)), NumberType_Int32); + return LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_iCampaignScores + (team * 4)), NumberType_Int32); } public int Direct_SetVSCampaignScore(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_iCampaignScores, "m_iCampaignScores"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_iCampaignScores, "m_iCampaignScores"); int team = GetNativeCell(1); - if( team < 0 || team > 1 ) return; + if( team < 0 || team > 1 ) return 0; int score = GetNativeCell(2); - StoreToAddress(view_as
    (VersusModePtr + m_iCampaignScores + (team * 4)), score, NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_iCampaignScores + (team * 4)), score, NumberType_Int32); + + return 0; } public any Direct_GetVSTankFlowPercent(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_fTankSpawnFlowPercent, "m_fTankSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_fTankSpawnFlowPercent, "m_fTankSpawnFlowPercent"); int round = GetNativeCell(1); if( round < 0 || round > 1 ) return -1.0; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); - return LoadFromAddress(view_as
    (VersusModePtr + m_fTankSpawnFlowPercent + (team * 4)), NumberType_Int32); + return LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_fTankSpawnFlowPercent + (team * 4)), NumberType_Int32); } public int Direct_SetVSTankFlowPercent(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_fTankSpawnFlowPercent, "m_fTankSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_fTankSpawnFlowPercent, "m_fTankSpawnFlowPercent"); int round = GetNativeCell(1); - if( round < 0 || round > 1 ) return; + if( round < 0 || round > 1 ) return 0; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); float flow = GetNativeCell(2); - StoreToAddress(view_as
    (VersusModePtr + m_fTankSpawnFlowPercent + (team * 4)), view_as(flow), NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_fTankSpawnFlowPercent + (team * 4)), view_as(flow), NumberType_Int32); + + return 0; } public int Direct_GetVSTankToSpawnThisRound(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_bTankThisRound, "m_bTankThisRound"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_bTankThisRound, "m_bTankThisRound"); int round = GetNativeCell(1); if( round < 0 || round > 1 ) return false; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); - return LoadFromAddress(view_as
    (VersusModePtr + m_bTankThisRound + team), NumberType_Int8); + return LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_bTankThisRound + team), NumberType_Int8); } public int Direct_SetVSTankToSpawnThisRound(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_bTankThisRound, "m_bTankThisRound"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_bTankThisRound, "m_bTankThisRound"); int round = GetNativeCell(1); - if( round < 0 || round > 1 ) return; + if( round < 0 || round > 1 ) return 0; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); bool spawn = GetNativeCell(2); - StoreToAddress(view_as
    (VersusModePtr + m_bTankThisRound + team), spawn, NumberType_Int8); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_bTankThisRound + team), spawn, NumberType_Int8); + + return 0; } public any Direct_GetVSWitchFlowPercent(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_fWitchSpawnFlowPercent, "m_fWitchSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_fWitchSpawnFlowPercent, "m_fWitchSpawnFlowPercent"); int round = GetNativeCell(1); if( round < 0 || round > 1 ) return false; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); - return LoadFromAddress(view_as
    (VersusModePtr + m_fWitchSpawnFlowPercent + (team * 4)), NumberType_Int32); + return LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_fWitchSpawnFlowPercent + (team * 4)), NumberType_Int32); } public int Direct_SetVSWitchFlowPercent(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_fWitchSpawnFlowPercent, "m_fWitchSpawnFlowPercent"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_fWitchSpawnFlowPercent, "m_fWitchSpawnFlowPercent"); int round = GetNativeCell(1); - if( round < 0 || round > 1 ) return; + if( round < 0 || round > 1 ) return 0; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); float flow = GetNativeCell(2); - StoreToAddress(view_as
    (VersusModePtr + m_fWitchSpawnFlowPercent + (team * 4)), view_as(flow), NumberType_Int32); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_fWitchSpawnFlowPercent + (team * 4)), view_as(flow), NumberType_Int32); + + return 0; } public int Direct_GetVSWitchToSpawnThisRound(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_bWitchThisRound, "m_bWitchThisRound"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_bWitchThisRound, "m_bWitchThisRound"); int round = GetNativeCell(1); if( round < 0 || round > 1 ) return false; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); - return LoadFromAddress(view_as
    (VersusModePtr + m_bWitchThisRound + team), NumberType_Int8); + return LoadFromAddress(view_as
    (g_pVersusMode + g_iOff_m_bWitchThisRound + team), NumberType_Int8); } public int Direct_SetVSWitchToSpawnThisRound(Handle plugin, int numParams) { - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateAddress(m_bWitchThisRound, "m_bWitchThisRound"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateAddress(g_iOff_m_bWitchThisRound, "m_bWitchThisRound"); int round = GetNativeCell(1); - if( round < 0 || round > 1 ) return; + if( round < 0 || round > 1 ) return 0; int team = round ^ GameRules_GetProp("m_bInSecondHalfOfRound") != GameRules_GetProp("m_bAreTeamsFlipped"); bool spawn = GetNativeCell(2); - StoreToAddress(view_as
    (VersusModePtr + m_bWitchThisRound + team), spawn, NumberType_Int8); + StoreToAddress(view_as
    (g_pVersusMode + g_iOff_m_bWitchThisRound + team), spawn, NumberType_Int8); + + return 0; } public any Direct_GetVSStartTimer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); int offset; if( g_bLeft4Dead2 ) offset = L4D2CountdownTimer_Offsets[7]; // L4D2CountdownTimer_VersusStartTimer else - offset = VersusModePtr + VersusStartTimer; + offset = g_pVersusMode + g_iOff_VersusStartTimer; ValidateAddress(offset, "VersusStartTimer"); return view_as(view_as
    (offset)); @@ -6385,35 +6756,35 @@ public any Direct_GetScavengeRoundSetupTimer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(ScavengeModePtr, "ScavengeModePtr"); - ValidateAddress(OnBeginRoundSetupTime, "OnBeginRoundSetupTime"); + ValidateAddress(g_pScavengeMode, "ScavengeModePtr"); + ValidateAddress(g_iOff_OnBeginRoundSetupTime, "OnBeginRoundSetupTime"); - return view_as(view_as
    (ScavengeModePtr + OnBeginRoundSetupTime)); + return view_as(view_as
    (g_pScavengeMode + g_iOff_OnBeginRoundSetupTime)); } public any Direct_GetScavengeOvertimeGraceTimer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(ScavengeModePtr, "ScavengeModePtr"); - ValidateAddress(OvertimeGraceTimer, "OvertimeGraceTimer"); + ValidateAddress(g_pScavengeMode, "ScavengeModePtr"); + ValidateAddress(g_iOff_OvertimeGraceTimer, "OvertimeGraceTimer"); - return view_as(view_as
    (ScavengeModePtr + OvertimeGraceTimer)); + return view_as(view_as
    (g_pScavengeMode + g_iOff_OvertimeGraceTimer)); } public any Direct_GetMapMaxFlowDistance(Handle plugin, int numParams) { ValidateAddress(g_pNavMesh, "g_pNavMesh"); - ValidateAddress(m_fMapMaxFlowDistance, "m_fMapMaxFlowDistance"); + ValidateAddress(g_iOff_m_fMapMaxFlowDistance, "m_fMapMaxFlowDistance"); - return LoadFromAddress(g_pNavMesh + view_as
    (m_fMapMaxFlowDistance), NumberType_Int32); + return LoadFromAddress(g_pNavMesh + view_as
    (g_iOff_m_fMapMaxFlowDistance), NumberType_Int32); } public any Direct_GetSpawnTimer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(SpawnTimer, "SpawnTimer"); + ValidateAddress(g_iOff_SpawnTimer, "SpawnTimer"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6423,12 +6794,12 @@ public any Direct_GetSpawnTimer(Handle plugin, int numParams) if( pEntity == Address_Null ) return CTimer_Null; - return view_as(pEntity + view_as
    (SpawnTimer)); + return view_as(pEntity + view_as
    (g_iOff_SpawnTimer)); } public any Direct_GetInvulnerabilityTimer(Handle plugin, int numParams) { - ValidateAddress(InvulnerabilityTimer, "InvulnerabilityTimer"); + ValidateAddress(g_iOff_InvulnerabilityTimer, "InvulnerabilityTimer"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6438,12 +6809,12 @@ public any Direct_GetInvulnerabilityTimer(Handle plugin, int numParams) if( pEntity == Address_Null ) return CTimer_Null; - return view_as(pEntity + view_as
    (InvulnerabilityTimer)); + return view_as(pEntity + view_as
    (g_iOff_InvulnerabilityTimer)); } public int Direct_GetTankTickets(Handle plugin, int numParams) { - ValidateAddress(m_iTankTickets, "m_iTankTickets"); + ValidateAddress(g_iOff_m_iTankTickets, "m_iTankTickets"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6453,30 +6824,32 @@ public int Direct_GetTankTickets(Handle plugin, int numParams) if( pEntity == Address_Null ) return -1; - return LoadFromAddress(pEntity + view_as
    (m_iTankTickets), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_iTankTickets), NumberType_Int32); } public int Direct_SetTankTickets(Handle plugin, int numParams) { - ValidateAddress(m_iTankTickets, "m_iTankTickets"); + ValidateAddress(g_iOff_m_iTankTickets, "m_iTankTickets"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) - return; + return 0; Address pEntity = GetEntityAddress(client); if( pEntity == Address_Null ) - return; + return 0; int tickets = GetNativeCell(2); - StoreToAddress(pEntity + view_as
    (m_iTankTickets), tickets, NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_iTankTickets), tickets, NumberType_Int32); + + return 0; } public int Direct_GetShovePenalty(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_iShovePenalty, "m_iShovePenalty"); + ValidateAddress(g_iOff_m_iShovePenalty, "m_iShovePenalty"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6486,32 +6859,34 @@ public int Direct_GetShovePenalty(Handle plugin, int numParams) if( pEntity == Address_Null ) return -1; - return LoadFromAddress(pEntity + view_as
    (m_iShovePenalty), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_iShovePenalty), NumberType_Int32); } public int Direct_SetShovePenalty(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_iShovePenalty, "m_iShovePenalty"); + ValidateAddress(g_iOff_m_iShovePenalty, "m_iShovePenalty"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) - return; + return 0; Address pEntity = GetEntityAddress(client); if( pEntity == Address_Null ) - return; + return 0; int penalty = GetNativeCell(2); - StoreToAddress(pEntity + view_as
    (m_iShovePenalty), penalty, NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_iShovePenalty), penalty, NumberType_Int32); + + return 0; } public any Direct_GetNextShoveTime(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_fNextShoveTime, "m_fNextShoveTime"); + ValidateAddress(g_iOff_m_fNextShoveTime, "m_fNextShoveTime"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6521,32 +6896,34 @@ public any Direct_GetNextShoveTime(Handle plugin, int numParams) if( pEntity == Address_Null ) return 0.0; - return LoadFromAddress(pEntity + view_as
    (m_fNextShoveTime), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_fNextShoveTime), NumberType_Int32); } public int Direct_SetNextShoveTime(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_fNextShoveTime, "m_fNextShoveTime"); + ValidateAddress(g_iOff_m_fNextShoveTime, "m_fNextShoveTime"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) - return; + return 0; Address pEntity = GetEntityAddress(client); if( pEntity == Address_Null ) - return; + return 0; float time = GetNativeCell(2); - StoreToAddress(pEntity + view_as
    (m_fNextShoveTime), view_as(time), NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_fNextShoveTime), view_as(time), NumberType_Int32); + + return 0; } public int Direct_GetPreIncapHealth(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_preIncapacitatedHealth, "m_preIncapacitatedHealth"); + ValidateAddress(g_iOff_m_preIncapacitatedHealth, "m_preIncapacitatedHealth"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6556,32 +6933,34 @@ public int Direct_GetPreIncapHealth(Handle plugin, int numParams) if( pEntity == Address_Null ) return -1; - return LoadFromAddress(pEntity + view_as
    (m_preIncapacitatedHealth), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_preIncapacitatedHealth), NumberType_Int32); } public int Direct_SetPreIncapHealth(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_preIncapacitatedHealth, "m_preIncapacitatedHealth"); + ValidateAddress(g_iOff_m_preIncapacitatedHealth, "m_preIncapacitatedHealth"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) - return; + return 0; Address pEntity = GetEntityAddress(client); if( pEntity == Address_Null ) - return; + return 0; int health = GetNativeCell(2); - StoreToAddress(pEntity + view_as
    (m_preIncapacitatedHealth), health, NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_preIncapacitatedHealth), health, NumberType_Int32); + + return 0; } public int Direct_GetPreIncapHealthBuffer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_preIncapacitatedHealthBuffer, "m_preIncapacitatedHealthBuffer"); + ValidateAddress(g_iOff_m_preIncapacitatedHealthBuffer, "m_preIncapacitatedHealthBuffer"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) @@ -6591,32 +6970,34 @@ public int Direct_GetPreIncapHealthBuffer(Handle plugin, int numParams) if( pEntity == Address_Null ) return -1; - return LoadFromAddress(pEntity + view_as
    (m_preIncapacitatedHealthBuffer), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_preIncapacitatedHealthBuffer), NumberType_Int32); } public int Direct_SetPreIncapHealthBuffer(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_preIncapacitatedHealthBuffer, "m_preIncapacitatedHealthBuffer"); + ValidateAddress(g_iOff_m_preIncapacitatedHealthBuffer, "m_preIncapacitatedHealthBuffer"); int client = GetNativeCell(1); if( client < 1 || client > MaxClients ) - return; + return 0; Address pEntity = GetEntityAddress(client); if( pEntity == Address_Null ) - return; + return 0; int health = GetNativeCell(2); - StoreToAddress(pEntity + view_as
    (m_preIncapacitatedHealthBuffer), health, NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_preIncapacitatedHealthBuffer), health, NumberType_Int32); + + return 0; } public int Direct_GetInfernoMaxFlames(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_maxFlames, "m_maxFlames"); + ValidateAddress(g_iOff_m_maxFlames, "m_maxFlames"); int client = GetNativeCell(1); @@ -6624,83 +7005,87 @@ public int Direct_GetInfernoMaxFlames(Handle plugin, int numParams) if( pEntity == Address_Null ) return -1; - return LoadFromAddress(pEntity + view_as
    (m_maxFlames), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_maxFlames), NumberType_Int32); } public int Direct_SetInfernoMaxFlames(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(m_maxFlames, "m_maxFlames"); + ValidateAddress(g_iOff_m_maxFlames, "m_maxFlames"); int entity = GetNativeCell(1); Address pEntity = GetEntityAddress(entity); if( pEntity == Address_Null ) - return; + return 0; int flames = GetNativeCell(2); - StoreToAddress(pEntity + view_as
    (m_maxFlames), flames, NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_maxFlames), flames, NumberType_Int32); + + return 0; } public int Direct_GetScriptedEventManager(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(ScriptedEventManagerPtr, "ScriptedEventManagerPtr"); + ValidateAddress(g_pScriptedEventManager, "ScriptedEventManagerPtr"); - return ScriptedEventManagerPtr; + return g_pScriptedEventManager; } public any Direct_GetTerrorNavArea(Handle plugin, int numParams) { ValidateAddress(g_pNavMesh, "g_pNavMesh"); - ValidateNatives(g_hSDK_Call_GetNavArea, "GetNavArea"); + ValidateNatives(g_hSDK_CNavMesh_GetNavArea, "CNavMesh::GetNavArea"); float vPos[3]; GetNativeArray(1, vPos, 3); float beneathLimit = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_GetNavArea"); - return SDKCall(g_hSDK_Call_GetNavArea, g_pNavMesh, vPos, beneathLimit); + //PrintToServer("#### CALL g_hSDK_CNavMesh_GetNavArea"); + return SDKCall(g_hSDK_CNavMesh_GetNavArea, g_pNavMesh, vPos, beneathLimit); } public any Direct_GetTerrorNavAreaFlow(Handle plugin, int numParams) { - ValidateAddress(m_flow, "m_flow"); + ValidateAddress(g_iOff_m_flow, "m_flow"); Address pTerrorNavArea = GetNativeCell(1); if( pTerrorNavArea == Address_Null ) return 0.0; - return view_as(LoadFromAddress(pTerrorNavArea + view_as
    (m_flow), NumberType_Int32)); + return view_as(LoadFromAddress(pTerrorNavArea + view_as
    (g_iOff_m_flow), NumberType_Int32)); } public int Direct_TryOfferingTankBot(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_TryOfferingTankBot, "TryOfferingTankBot"); + ValidateNatives(g_hSDK_CDirector_TryOfferingTankBot, "CDirector::TryOfferingTankBot"); int entity = GetNativeCell(1); bool bEnterStasis = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_TryOfferingTankBot"); - SDKCall(g_hSDK_Call_TryOfferingTankBot, g_pDirector, entity, bEnterStasis); + //PrintToServer("#### CALL g_hSDK_CDirector_TryOfferingTankBot"); + SDKCall(g_hSDK_CDirector_TryOfferingTankBot, g_pDirector, entity, bEnterStasis); + + return 0; } public any Direct_GetFlowDistance(Handle plugin, int numParams) { - ValidateAddress(m_flow, "m_flow"); - ValidateNatives(g_hSDK_Call_GetLastKnownArea, "GetLastKnownArea"); + ValidateAddress(g_iOff_m_flow, "m_flow"); + ValidateNatives(g_hSDK_CTerrorPlayer_GetLastKnownArea, "CTerrorPlayer::GetLastKnownArea"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_GetLastKnownArea"); - int area = SDKCall(g_hSDK_Call_GetLastKnownArea, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_GetLastKnownArea"); + int area = SDKCall(g_hSDK_CTerrorPlayer_GetLastKnownArea, client); if( area == 0 ) return 0.0; - float flow = view_as(LoadFromAddress(view_as
    (area + m_flow), NumberType_Int32)); + float flow = view_as(LoadFromAddress(view_as
    (area + g_iOff_m_flow), NumberType_Int32)); if( flow == -9999.0 ) flow = 0.0; return flow; @@ -6708,16 +7093,18 @@ public any Direct_GetFlowDistance(Handle plugin, int numParams) public int Direct_DoAnimationEvent(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_DoAnimationEvent, "DoAnimationEvent"); + ValidateNatives(g_hSDK_CTerrorPlayer_DoAnimationEvent, "CTerrorPlayer::DoAnimationEvent"); int client = GetNativeCell(1); if( client <= 0 || client > MaxClients ) - return; + return 0; int event = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_DoAnimationEvent"); - SDKCall(g_hSDK_Call_DoAnimationEvent, client, event, 0); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_DoAnimationEvent"); + SDKCall(g_hSDK_CTerrorPlayer_DoAnimationEvent, client, event, 0); + + return 0; } public int Direct_GetSurvivorHealthBonus(Handle plugin, int numParams) @@ -6730,7 +7117,7 @@ public int Direct_GetSurvivorHealthBonus(Handle plugin, int numParams) if( pEntity == Address_Null ) return -1; - return LoadFromAddress(pEntity + view_as
    (m_iSurvivorHealthBonus), NumberType_Int32); + return LoadFromAddress(pEntity + view_as
    (g_iOff_m_iSurvivorHealthBonus), NumberType_Int32); } public int Direct_SetSurvivorHealthBonus(Handle plugin, int numParams) @@ -6741,30 +7128,32 @@ public int Direct_SetSurvivorHealthBonus(Handle plugin, int numParams) Address pEntity = GetEntityAddress(client); if( pEntity == Address_Null ) - return; + return 0; int health = GetNativeCell(2); bool recompute = GetNativeCell(3); - StoreToAddress(pEntity + view_as
    (m_iSurvivorHealthBonus), health, NumberType_Int32); + StoreToAddress(pEntity + view_as
    (g_iOff_m_iSurvivorHealthBonus), health, NumberType_Int32); if( recompute ) { - ValidateNatives(g_hSDK_Call_RecomputeTeamScores, "RecomputeTeamScores"); + ValidateNatives(g_hSDK_CTerrorGameRules_RecomputeTeamScores, "CTerrorGameRules::RecomputeTeamScores"); - //PrintToServer("#### CALL g_hSDK_Call_RecomputeTeamScores"); - SDKCall(g_hSDK_Call_RecomputeTeamScores); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_RecomputeTeamScores"); + SDKCall(g_hSDK_CTerrorGameRules_RecomputeTeamScores); } + + return 0; } public int Direct_RecomputeTeamScores(Handle plugin, int numParams) { if( g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED1); - ValidateNatives(g_hSDK_Call_RecomputeTeamScores, "RecomputeTeamScores"); + ValidateNatives(g_hSDK_CTerrorGameRules_RecomputeTeamScores, "CTerrorGameRules::RecomputeTeamScores"); - //PrintToServer("#### CALL g_hSDK_Call_RecomputeTeamScores"); - SDKCall(g_hSDK_Call_RecomputeTeamScores); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_RecomputeTeamScores"); + SDKCall(g_hSDK_CTerrorGameRules_RecomputeTeamScores); return true; } @@ -6777,6 +7166,7 @@ public int Direct_CTimer_Reset(Handle plugin, int numParams) { CountdownTimer timer = GetNativeCell(1); Stock_CTimer_Reset(timer); + return 0; } public int Direct_CTimer_Start(Handle plugin, int numParams) @@ -6784,12 +7174,14 @@ public int Direct_CTimer_Start(Handle plugin, int numParams) CountdownTimer timer = GetNativeCell(1); float duration = GetNativeCell(2); Stock_CTimer_Start(timer, duration); + return 0; } public int Direct_CTimer_Invalidate(Handle plugin, int numParams) { CountdownTimer timer = GetNativeCell(1); Stock_CTimer_Invalidate(timer); + return 0; } public int Direct_CTimer_HasStarted(Handle plugin, int numParams) @@ -6826,18 +7218,21 @@ public int Direct_ITimer_Reset(Handle plugin, int numParams) { IntervalTimer timer = GetNativeCell(1); Stock_ITimer_Reset(timer); + return 0; } public int Direct_ITimer_Start(Handle plugin, int numParams) { IntervalTimer timer = GetNativeCell(1); Stock_ITimer_Start(timer); + return 0; } public int Direct_ITimer_Invalidate(Handle plugin, int numParams) { IntervalTimer timer = GetNativeCell(1); Stock_ITimer_Invalidate(timer); + return 0; } public int Direct_ITimer_HasStarted(Handle plugin, int numParams) @@ -6864,6 +7259,7 @@ public int Direct_CTimer_SetDuration(Handle plugin, int numParams) CountdownTimer timer = GetNativeCell(1); float duration = GetNativeCell(2); Stock_CTimer_SetDuration(timer, duration); + return 0; } public any Direct_CTimer_GetTimestamp(Handle plugin, int numParams) @@ -6877,6 +7273,7 @@ public int Direct_CTimer_SetTimestamp(Handle plugin, int numParams) CountdownTimer timer = GetNativeCell(1); float timestamp = GetNativeCell(2); Stock_CTimer_SetTimestamp(timer, timestamp); + return 0; } public any Direct_ITimer_GetTimestamp(Handle plugin, int numParams) @@ -6890,6 +7287,7 @@ public int Direct_ITimer_SetTimestamp(Handle plugin, int numParams) IntervalTimer timer = GetNativeCell(1); float timestamp = GetNativeCell(2); Stock_ITimer_SetTimestamp(timer, timestamp); + return 0; } // ================================================== @@ -7005,80 +7403,92 @@ void Stock_ITimer_SetTimestamp(IntervalTimer timer, float timestamp) // ================================================== public int Native_CTerrorPlayer_OnVomitedUpon(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_CTerrorPlayer_OnVomitedUpon, "CTerrorPlayer_OnVomitedUpon"); + ValidateNatives(g_hSDK_CTerrorPlayer_OnVomitedUpon, "CTerrorPlayer::OnVomitedUpon"); int client = GetNativeCell(1); int attacker = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_CTerrorPlayer_OnVomitedUpon"); - SDKCall(g_hSDK_Call_CTerrorPlayer_OnVomitedUpon, client, attacker, false); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_OnVomitedUpon"); + SDKCall(g_hSDK_CTerrorPlayer_OnVomitedUpon, client, attacker, false); + + return 0; } public int Native_CTerrorPlayer_OnHitByVomitJar(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_CTerrorPlayer_OnHitByVomitJar, "CTerrorPlayer_OnHitByVomitJar"); + ValidateNatives(g_hSDK_CTerrorPlayer_OnHitByVomitJar, "CTerrorPlayer::OnHitByVomitJar"); int client = GetNativeCell(1); int attacker = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_CTerrorPlayer_OnHitByVomitJar"); - SDKCall(g_hSDK_Call_CTerrorPlayer_OnHitByVomitJar, client, attacker, true); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_OnHitByVomitJar"); + SDKCall(g_hSDK_CTerrorPlayer_OnHitByVomitJar, client, attacker, true); + + return 0; } public int Native_Infected_OnHitByVomitJar(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_Infected_OnHitByVomitJar, "Infected_OnHitByVomitJar"); + ValidateNatives(g_hSDK_Infected_OnHitByVomitJar, "Infected::OnHitByVomitJar"); int entity = GetNativeCell(1); int attacker = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_Infected_OnHitByVomitJar"); - SDKCall(g_hSDK_Call_Infected_OnHitByVomitJar, entity, attacker, true); + //PrintToServer("#### CALL g_hSDK_Infected_OnHitByVomitJar"); + SDKCall(g_hSDK_Infected_OnHitByVomitJar, entity, attacker, true); + + return 0; } public int Native_CTerrorPlayer_Fling(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_CTerrorPlayer_Fling, "CTerrorPlayer_Fling"); + ValidateNatives(g_hSDK_CTerrorPlayer_Fling, "CTerrorPlayer::Fling"); int client = GetNativeCell(1); int attacker = GetNativeCell(2); float vDir[3]; GetNativeArray(3, vDir, 3); - //PrintToServer("#### CALL g_hSDK_Call_CTerrorPlayer_Fling"); - SDKCall(g_hSDK_Call_CTerrorPlayer_Fling, client, vDir, 76, attacker, 3.0); // 76 is the 'got bounced' animation in L4D2. 3.0 = incapTime, what's this mean? + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_Fling"); + SDKCall(g_hSDK_CTerrorPlayer_Fling, client, vDir, 76, attacker, 3.0); // 76 is the 'got bounced' animation in L4D2. 3.0 = incapTime, what's this mean? + + return 0; } -public int Native_CancelStagger(Handle plugin, int numParams) +public int Native_CTerrorPlayer_CancelStagger(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_CancelStagger, "CancelStagger"); + ValidateNatives(g_hSDK_CTerrorPlayer_CancelStagger, "CTerrorPlayer::CancelStagger"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_CancelStagger"); - SDKCall(g_hSDK_Call_CancelStagger, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_CancelStagger"); + SDKCall(g_hSDK_CTerrorPlayer_CancelStagger, client); + + return 0; } -public int Native_RespawnPlayer(Handle plugin, int numParams) +public int Native_CTerrorPlayer_RespawnPlayer(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_RoundRespawn, "RoundRespawn"); + ValidateNatives(g_hSDK_CTerrorPlayer_RoundRespawn, "CTerrorPlayer::RoundRespawn"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_RoundRespawn"); - SDKCall(g_hSDK_Call_RoundRespawn, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_RoundRespawn"); + SDKCall(g_hSDK_CTerrorPlayer_RoundRespawn, client); + + return 0; } -public int Native_CreateRescuableSurvivors(Handle plugin, int numParams) +public int Native_CDirector_CreateRescuableSurvivors(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_CreateRescuableSurvivors, "CreateRescuableSurvivors"); + ValidateNatives(g_hSDK_CDirector_CreateRescuableSurvivors, "CDirector::CreateRescuableSurvivors"); // Only spawns one per frame, so we'll call for as many dead survivors. int count; @@ -7091,6 +7501,8 @@ public int Native_CreateRescuableSurvivors(Handle plugin, int numParams) } RequestFrame(OnFrameRescue, count); + + return 0; } void OnFrameRescue(int count) @@ -7102,63 +7514,65 @@ void OnFrameRescue(int count) void RespawnRescue() { - StoreToAddress(g_pDirector + view_as
    (m_rescueCheckTimer + 8), view_as(0.0), NumberType_Int32); + StoreToAddress(g_pDirector + view_as
    (g_iOff_m_rescueCheckTimer + 8), view_as(0.0), NumberType_Int32); - int time = g_hCvarRescueDeadTime.IntValue; - g_hCvarRescueDeadTime.SetInt(0); - //PrintToServer("#### CALL g_hSDK_Call_CreateRescuableSurvivors"); - SDKCall(g_hSDK_Call_CreateRescuableSurvivors, g_pDirector); - g_hCvarRescueDeadTime.SetInt(time); + int time = g_hCvar_RescueDeadTime.IntValue; + g_hCvar_RescueDeadTime.SetInt(0); + //PrintToServer("#### CALL g_hSDK_CDirector_CreateRescuableSurvivors"); + SDKCall(g_hSDK_CDirector_CreateRescuableSurvivors, g_pDirector); + g_hCvar_RescueDeadTime.SetInt(time); } -public int Native_OnRevived(Handle plugin, int numParams) +public int Native_CTerrorPlayer_OnRevived(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_OnRevived, "OnRevived"); + ValidateNatives(g_hSDK_CTerrorPlayer_OnRevived, "CTerrorPlayer::OnRevived"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_OnRevived"); - SDKCall(g_hSDK_Call_OnRevived, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_OnRevived"); + SDKCall(g_hSDK_CTerrorPlayer_OnRevived, client); + + return 0; } -public any Native_GetVersusCompletionPlayer(Handle plugin, int numParams) +public any Native_CTerrorGameRules_GetVersusCompletion(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pGameRules, "g_pGameRules"); - ValidateNatives(g_hSDK_Call_GetVersusCompletionPlayer, "GetVersusCompletionPlayer"); + ValidateNatives(g_hSDK_CTerrorGameRules_GetVersusCompletion, "CTerrorGameRules::GetVersusCompletion"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_GetVersusCompletionPlayer"); - return SDKCall(g_hSDK_Call_GetVersusCompletionPlayer, g_pGameRules, client); + //PrintToServer("#### CALL g_hSDK_CTerrorGameRules_GetVersusCompletion"); + return SDKCall(g_hSDK_CTerrorGameRules_GetVersusCompletion, g_pGameRules, client); } -public int Native_GetHighestFlowSurvivor(Handle plugin, int numParams) +public int Native_CDirectorTacticalServices_GetHighestFlowSurvivor(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_GetHighestFlowSurvivor, "GetHighestFlowSurvivor"); + ValidateNatives(g_hSDK_CDirectorTacticalServices_GetHighestFlowSurvivor, "CDirectorTacticalServices::GetHighestFlowSurvivor"); - //PrintToServer("#### CALL g_hSDK_Call_GetHighestFlowSurvivor"); - return SDKCall(g_hSDK_Call_GetHighestFlowSurvivor, 0, 0); + //PrintToServer("#### CALL g_hSDK_CDirectorTacticalServices_GetHighestFlowSurvivor"); + return SDKCall(g_hSDK_CDirectorTacticalServices_GetHighestFlowSurvivor, 0, 0); } -public any Native_GetInfectedFlowDistance(Handle plugin, int numParams) +public any Native_Infected_GetInfectedFlowDistance(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_GetInfectedFlowDistance, "GetInfectedFlowDistance"); + ValidateNatives(g_hSDK_Infected_GetFlowDistance, "Infected::GetFlowDistance"); int entity = GetNativeCell(1); if( entity > MaxClients ) { - //PrintToServer("#### CALL g_hSDK_Call_GetInfectedFlowDistance"); - return SDKCall(g_hSDK_Call_GetInfectedFlowDistance, entity); + //PrintToServer("#### CALL g_hSDK_Infected_GetFlowDistance"); + return SDKCall(g_hSDK_Infected_GetFlowDistance, entity); } return 0.0; } -public int Native_TakeOverZombieBot(Handle plugin, int numParams) +public int Native_CTerrorPlayer_TakeOverZombieBot(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_TakeOverZombieBot, "TakeOverZombieBot"); + ValidateNatives(g_hSDK_CTerrorPlayer_TakeOverZombieBot, "CTerrorPlayer::TakeOverZombieBot"); int client = GetNativeCell(1); int target = GetNativeCell(2); @@ -7169,24 +7583,26 @@ public int Native_TakeOverZombieBot(Handle plugin, int numParams) { if( g_bLeft4Dead2 ) { - //PrintToServer("#### CALL g_hSDK_Call_TakeOverZombieBot"); - SDKCall(g_hSDK_Call_TakeOverZombieBot, client, target); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_TakeOverZombieBot"); + SDKCall(g_hSDK_CTerrorPlayer_TakeOverZombieBot, client, target); } else { // Workaround spawning wrong type, you'll hear another special infected type sound when spawning. int zombieClass = GetEntProp(target, Prop_Send, "m_zombieClass"); - //PrintToServer("#### CALL g_hSDK_Call_TakeOverZombieBot"); - SDKCall(g_hSDK_Call_TakeOverZombieBot, client, target); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_TakeOverZombieBot"); + SDKCall(g_hSDK_CTerrorPlayer_TakeOverZombieBot, client, target); SetClass(client, zombieClass); } } + + return 0; } -public int Native_ReplaceWithBot(Handle plugin, int numParams) +public int Native_CTerrorPlayer_ReplaceWithBot(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_ReplaceWithBot, "ReplaceWithBot"); + ValidateNatives(g_hSDK_CTerrorPlayer_ReplaceWithBot, "CTerrorPlayer::ReplaceWithBot"); int client = GetNativeCell(1); @@ -7194,33 +7610,39 @@ public int Native_ReplaceWithBot(Handle plugin, int numParams) GetClientAbsOrigin(client, vPos); GetClientEyeAngles(client, vAng); - //PrintToServer("#### CALL g_hSDK_Call_ReplaceWithBot"); - SDKCall(g_hSDK_Call_ReplaceWithBot, client, true); - //PrintToServer("#### CALL g_hSDK_Call_BecomeGhost"); - SDKCall(g_hSDK_Call_BecomeGhost, client, 0, 0); // Otherwise they duplicate bots and don't go into ghost mode + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_ReplaceWithBot"); + SDKCall(g_hSDK_CTerrorPlayer_ReplaceWithBot, client, true); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_BecomeGhost"); + SDKCall(g_hSDK_CTerrorPlayer_BecomeGhost, client, 0, 0); // Otherwise they duplicate bots and don't go into ghost mode TeleportEntity(client, vPos, vAng, NULL_VECTOR); + + return 0; } -public int Native_CullZombie(Handle plugin, int numParams) +public int Native_CTerrorPlayer_CullZombie(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_CullZombie, "CullZombie"); + ValidateNatives(g_hSDK_CTerrorPlayer_CullZombie, "CTerrorPlayer::CullZombie"); int client = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_CullZombie"); - SDKCall(g_hSDK_Call_CullZombie, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_CullZombie"); + SDKCall(g_hSDK_CTerrorPlayer_CullZombie, client); + + return 0; } -public int Native_SetClass(Handle plugin, int numParams) +public int Native_CTerrorPlayer_SetClass(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_SetClass, "SetClass"); - ValidateNatives(g_hSDK_Call_CreateAbility, "CreateAbility"); + ValidateNatives(g_hSDK_CTerrorPlayer_SetClass, "CTerrorPlayer::SetClass"); + ValidateNatives(g_hSDK_CBaseAbility_CreateForPlayer, "CBaseAbility::CreateForPlayer"); int client = GetNativeCell(1); int zombieClass = GetNativeCell(2); SetClass(client, zombieClass); + + return 0; } void SetClass(int client, int zombieClass) @@ -7235,157 +7657,173 @@ void SetClass(int client, int zombieClass) int ability = GetEntPropEnt(client, Prop_Send, "m_customAbility"); if( ability != -1 ) RemoveEntity(ability); - //PrintToServer("#### CALL g_hSDK_Call_SetClass"); - SDKCall(g_hSDK_Call_SetClass, client, zombieClass); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_SetClass"); + SDKCall(g_hSDK_CTerrorPlayer_SetClass, client, zombieClass); - //PrintToServer("#### CALL g_hSDK_Call_CreateAbility"); - ability = SDKCall(g_hSDK_Call_CreateAbility, client); + //PrintToServer("#### CALL g_hSDK_CBaseAbility_CreateForPlayer"); + ability = SDKCall(g_hSDK_CBaseAbility_CreateForPlayer, client); if( ability != -1 ) SetEntPropEnt(client, Prop_Send, "m_customAbility", ability); } -public int Native_MaterializeFromGhost(Handle plugin, int numParams) +public int Native_CTerrorPlayer_MaterializeFromGhost(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_MaterializeFromGhost, "MaterializeFromGhost"); + ValidateNatives(g_hSDK_CTerrorPlayer_MaterializeFromGhost, "CTerrorPlayer::MaterializeFromGhost"); int client = GetNativeCell(1); if( GetClientTeam(client) == 3 && GetEntProp(client, Prop_Send, "m_isGhost") ) { - //PrintToServer("#### CALL g_hSDK_Call_MaterializeFromGhost"); - SDKCall(g_hSDK_Call_MaterializeFromGhost, client); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_MaterializeFromGhost"); + SDKCall(g_hSDK_CTerrorPlayer_MaterializeFromGhost, client); return GetEntPropEnt(client, Prop_Send, "m_customAbility"); } return -1; } -public int Native_BecomeGhost(Handle plugin, int numParams) +public int Native_CTerrorPlayer_BecomeGhost(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_BecomeGhost, "BecomeGhost"); + ValidateNatives(g_hSDK_CTerrorPlayer_BecomeGhost, "CTerrorPlayer::BecomeGhost"); int client = GetNativeCell(1); if( GetEntProp(client, Prop_Send, "m_isGhost") == 0 ) { if( g_bLeft4Dead2 ) { - //PrintToServer("#### CALL g_hSDK_Call_BecomeGhost"); - return !!SDKCall(g_hSDK_Call_BecomeGhost, client, true); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_BecomeGhost"); + return !!SDKCall(g_hSDK_CTerrorPlayer_BecomeGhost, client, true); } else { - //PrintToServer("#### CALL g_hSDK_Call_BecomeGhost"); - return !!SDKCall(g_hSDK_Call_BecomeGhost, client, 0, 0); + //PrintToServer("#### CALL g_hSDK_CTerrorPlayer_BecomeGhost"); + return !!SDKCall(g_hSDK_CTerrorPlayer_BecomeGhost, client, 0, 0); } } return 0; } -public int Native_State_Transition(Handle plugin, int numParams) +public int Native_CCSPlayer_State_Transition(Handle plugin, int numParams) { - ValidateNatives(g_hSDK_Call_State_Transition, "State_Transition"); + ValidateNatives(g_hSDK_CCSPlayer_State_Transition, "CCSPlayer::State_Transition"); int client = GetNativeCell(1); int state = GetNativeCell(2); - //PrintToServer("#### CALL g_hSDK_Call_State_Transition"); - SDKCall(g_hSDK_Call_State_Transition, client, state); + //PrintToServer("#### CALL g_hSDK_CCSPlayer_State_Transition"); + SDKCall(g_hSDK_CCSPlayer_State_Transition, client, state); + + return 0; } -public int Native_SwapTeams(Handle plugin, int numParams) +public int Native_CDirector_SwapTeams(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_SwapTeams, "SwapTeams"); + ValidateNatives(g_hSDK_CDirector_SwapTeams, "CDirector::SwapTeams"); + + //PrintToServer("#### CALL g_hSDK_CDirector_SwapTeams"); + SDKCall(g_hSDK_CDirector_SwapTeams, g_pDirector); - //PrintToServer("#### CALL g_hSDK_Call_SwapTeams"); - SDKCall(g_hSDK_Call_SwapTeams, g_pDirector); + return 0; } -public int Native_AreTeamsFlipped(Handle plugin, int numParams) +public int Native_CDirector_AreTeamsFlipped(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_AreTeamsFlipped, "AreTeamsFlipped"); + ValidateNatives(g_hSDK_CDirector_AreTeamsFlipped, "CDirector::AreTeamsFlipped"); - //PrintToServer("#### CALL g_hSDK_Call_AreTeamsFlipped"); - return SDKCall(g_hSDK_Call_AreTeamsFlipped, g_pDirector); + //PrintToServer("#### CALL g_hSDK_CDirector_AreTeamsFlipped"); + return SDKCall(g_hSDK_CDirector_AreTeamsFlipped, g_pDirector); } -public int Native_StartRematchVote(Handle plugin, int numParams) +public int Native_CDirector_StartRematchVote(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateNatives(g_hSDK_Call_StartRematchVote, "StartRematchVote"); + ValidateNatives(g_hSDK_CDirector_StartRematchVote, "CDirector::StartRematchVote"); + + //PrintToServer("#### CALL g_hSDK_CDirector_StartRematchVote"); + SDKCall(g_hSDK_CDirector_StartRematchVote, g_pDirector); - //PrintToServer("#### CALL g_hSDK_Call_StartRematchVote"); - SDKCall(g_hSDK_Call_StartRematchVote, g_pDirector); + return 0; } -public int Native_FullRestart(Handle plugin, int numParams) +public int Native_CDirector_FullRestart(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_FullRestart, "FullRestart"); + ValidateNatives(g_hSDK_CDirector_FullRestart, "CDirector::FullRestart"); + + //PrintToServer("#### CALL g_hSDK_CDirector_FullRestart"); + SDKCall(g_hSDK_CDirector_FullRestart, g_pDirector); - //PrintToServer("#### CALL g_hSDK_Call_FullRestart"); - SDKCall(g_hSDK_Call_FullRestart, g_pDirector); + return 0; } -public int Native_HideVersusScoreboard(Handle plugin, int numParams) +public int Native_CDirectorVersusMode_HideScoreboardNonVirtual(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(VersusModePtr, "VersusModePtr"); - ValidateNatives(g_hSDK_Call_HideVersusScoreboard, "VersusScoreboard"); + ValidateAddress(g_pVersusMode, "VersusModePtr"); + ValidateNatives(g_hSDK_CDirectorVersusMode_HideScoreboardNonVirtual, "CDirectorVersusMode::HideScoreboardNonVirtual"); + + //PrintToServer("#### CALL g_hSDK_CDirectorVersusMode_HideScoreboardNonVirtual"); + SDKCall(g_hSDK_CDirectorVersusMode_HideScoreboardNonVirtual, g_pVersusMode); - //PrintToServer("#### CALL g_hSDK_Call_HideVersusScoreboard"); - SDKCall(g_hSDK_Call_HideVersusScoreboard, VersusModePtr); + return 0; } -public int Native_HideScavengeScoreboard(Handle plugin, int numParams) +public int Native_CDirectorScavengeMode_HideScoreboardNonVirtual(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); - ValidateAddress(ScavengeModePtr, "ScavengeModePtr"); - ValidateNatives(g_hSDK_Call_HideScavengeScoreboard, "HideScavengeScoreboard"); + ValidateAddress(g_pScavengeMode, "ScavengeModePtr"); + ValidateNatives(g_hSDK_CDirectorScavengeMode_HideScoreboardNonVirtual, "CDirectorScavengeMode::HideScoreboardNonVirtual"); + + //PrintToServer("#### CALL g_hSDK_CDirectorScavengeMode_HideScoreboardNonVirtual"); + SDKCall(g_hSDK_CDirectorScavengeMode_HideScoreboardNonVirtual, g_pScavengeMode); - //PrintToServer("#### CALL g_hSDK_Call_HideScavengeScoreboard"); - SDKCall(g_hSDK_Call_HideScavengeScoreboard, ScavengeModePtr); + return 0; } -public int Native_HideScoreboard(Handle plugin, int numParams) +public int Native_CDirector_HideScoreboard(Handle plugin, int numParams) { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_HideScoreboard, "HideScoreboard"); + ValidateNatives(g_hSDK_CDirector_HideScoreboard, "CDirector::HideScoreboard"); + + //PrintToServer("#### CALL g_hSDK_CDirector_HideScoreboard"); + SDKCall(g_hSDK_CDirector_HideScoreboard, g_pDirector); - //PrintToServer("#### CALL g_hSDK_Call_HideScoreboard"); - SDKCall(g_hSDK_Call_HideScoreboard, g_pDirector); + return 0; } -public int Native_RegisterForbiddenTarget(Handle plugin, int numParams) +public int Native_CDirector_RegisterForbiddenTarget(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_RegisterForbiddenTarget, "RegisterForbiddenTarget"); + ValidateNatives(g_hSDK_CDirector_RegisterForbiddenTarget, "CDirector::RegisterForbiddenTarget"); int entity = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_RegisterForbiddenTarget"); - return SDKCall(g_hSDK_Call_RegisterForbiddenTarget, g_pDirector, entity); + //PrintToServer("#### CALL g_hSDK_CDirector_RegisterForbiddenTarget"); + return SDKCall(g_hSDK_CDirector_RegisterForbiddenTarget, g_pDirector, entity); } -public int Native_UnRegisterForbiddenTarget(Handle plugin, int numParams) +public int Native_CDirector_UnregisterForbiddenTarget(Handle plugin, int numParams) { ValidateAddress(g_pDirector, "g_pDirector"); - ValidateNatives(g_hSDK_Call_UnRegisterForbiddenTarget, "UnRegisterForbiddenTarget"); + ValidateNatives(g_hSDK_CDirector_UnregisterForbiddenTarget, "CDirector::UnregisterForbiddenTarget"); int entity = GetNativeCell(1); - //PrintToServer("#### CALL g_hSDK_Call_UnRegisterForbiddenTarget"); - SDKCall(g_hSDK_Call_UnRegisterForbiddenTarget, g_pDirector, entity); + //PrintToServer("#### CALL g_hSDK_CDirector_UnregisterForbiddenTarget"); + SDKCall(g_hSDK_CDirector_UnregisterForbiddenTarget, g_pDirector, entity); + + return 0; } @@ -7402,16 +7840,16 @@ public int Native_UnRegisterForbiddenTarget(Handle plugin, int numParams) // MRES_Override, // call real function, but use my return value // MRES_Supercede // skip real function; use my return value -public MRESReturn SpawnSpecial(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnSpecial(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnSpecial"); + //PrintToServer("##### DTR_ZombieManager_SpawnSpecial"); float a1[3], a2[3]; int class = DHookGetParam(hParams, 1); DHookGetParamVector(hParams, 2, a1); DHookGetParamVector(hParams, 3, a2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SpawnSpecial); + Call_StartForward(g_hFWD_ZombieManager_SpawnSpecial); Call_PushCellRef(class); Call_PushArray(a1, sizeof(a1)); Call_PushArray(a2, sizeof(a2)); @@ -7432,23 +7870,23 @@ public MRESReturn SpawnSpecial(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn SpawnBoomer(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnBoomer(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnBoomer"); + //PrintToServer("##### DTR_ZombieManager_SpawnBoomer"); int class = 2; return Spawn_SmokerBoomerHunter(class, hReturn, hParams); } -public MRESReturn SpawnHunter(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnHunter(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnHunter"); + //PrintToServer("##### DTR_ZombieManager_SpawnHunter"); int class = 3; return Spawn_SmokerBoomerHunter(class, hReturn, hParams); } -public MRESReturn SpawnSmoker(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnSmoker(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnSmoker"); + //PrintToServer("##### DTR_ZombieManager_SpawnSmoker"); int class = 1; return Spawn_SmokerBoomerHunter(class, hReturn, hParams); } @@ -7461,7 +7899,7 @@ MRESReturn Spawn_SmokerBoomerHunter(int zombieClass, Handle hReturn, Handle hPar DHookGetParamVector(hParams, 2, a2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SpawnSpecial); + Call_StartForward(g_hFWD_ZombieManager_SpawnSpecial); Call_PushCellRef(class); Call_PushArray(a1, sizeof(a1)); Call_PushArray(a2, sizeof(a2)); @@ -7486,21 +7924,21 @@ MRESReturn Spawn_SmokerBoomerHunter(int zombieClass, Handle hReturn, Handle hPar { case 1: { - ValidateNatives(g_hSDK_Call_SpawnSmoker, "SpawnSmoker"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnSmoker"); - SDKCall(g_hSDK_Call_SpawnSmoker, g_pZombieManager, a1, a2); + ValidateNatives(g_hSDK_ZombieManager_SpawnSmoker, "ZombieManager::SpawnSmoker"); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnSmoker"); + SDKCall(g_hSDK_ZombieManager_SpawnSmoker, g_pZombieManager, a1, a2); } case 2: { - ValidateNatives(g_hSDK_Call_SpawnBoomer, "SpawnBoomer"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnBoomer"); - SDKCall(g_hSDK_Call_SpawnBoomer, g_pZombieManager, a1, a2); + ValidateNatives(g_hSDK_ZombieManager_SpawnBoomer, "ZombieManager::SpawnBoomer"); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnBoomer"); + SDKCall(g_hSDK_ZombieManager_SpawnBoomer, g_pZombieManager, a1, a2); } case 3: { - ValidateNatives(g_hSDK_Call_SpawnHunter, "SpawnHunter"); - //PrintToServer("#### CALL g_hSDK_Call_SpawnHunter"); - SDKCall(g_hSDK_Call_SpawnHunter, g_pZombieManager, a1, a2); + ValidateNatives(g_hSDK_ZombieManager_SpawnHunter, "ZombieManager::SpawnHunter"); + //PrintToServer("#### CALL g_hSDK_ZombieManager_SpawnHunter"); + SDKCall(g_hSDK_ZombieManager_SpawnHunter, g_pZombieManager, a1, a2); } } @@ -7515,22 +7953,22 @@ MRESReturn Spawn_SmokerBoomerHunter(int zombieClass, Handle hReturn, Handle hPar return MRES_Ignored; } -public MRESReturn SpawnTank(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnTank(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnTank"); - return Spawn_TankWitch(g_hForward_SpawnTank, hReturn, hParams); + //PrintToServer("##### DTR_ZombieManager_SpawnTank"); + return Spawn_TankWitch(g_hFWD_ZombieManager_SpawnTank, hReturn, hParams); } -public MRESReturn SpawnWitch(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnWitch(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnWitch"); - return Spawn_TankWitch(g_hForward_SpawnWitch, hReturn, hParams); + //PrintToServer("##### DTR_ZombieManager_SpawnWitch"); + return Spawn_TankWitch(g_hFWD_ZombieManager_SpawnWitch, hReturn, hParams); } -public MRESReturn SpawnWitchBride(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnWitchBride(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnWitchBride"); - return Spawn_TankWitch(g_hForward_SpawnWitchBride, hReturn, hParams); + //PrintToServer("##### DTR_ZombieManager_SpawnWitchBride"); + return Spawn_TankWitch(g_hFWD_ZombieManager_SpawnWitchBride, hReturn, hParams); } MRESReturn Spawn_TankWitch(Handle hForward, Handle hReturn, Handle hParams) @@ -7562,9 +8000,9 @@ public MRESReturn SpawnWitchAreaPre(Handle hReturn, Handle hParams) } */ -public MRESReturn SpawnWitchArea(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnWitch_Area(Handle hReturn, Handle hParams) { - // PrintToServer("##### DTR SpawnWitchArea"); + // PrintToServer("##### DTR_ZombieManager_SpawnWitch_Area"); // From the post hook /* int entity = DHookGetReturn(hReturn); @@ -7577,7 +8015,7 @@ public MRESReturn SpawnWitchArea(Handle hReturn, Handle hParams) float a2[3]; Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SpawnWitch); + Call_StartForward(g_hFWD_ZombieManager_SpawnWitch); Call_PushArray(NULL_VECTOR, sizeof(a2)); Call_PushArray(a2, sizeof(a2)); Call_Finish(aResult); @@ -7592,13 +8030,13 @@ public MRESReturn SpawnWitchArea(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn ClearTeamScores(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorGameRules_ClearTeamScores(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR ClearTeamScores"); + //PrintToServer("##### DTR_CTerrorGameRules_ClearTeamScores"); int value = g_bLeft4Dead2 ? DHookGetParam(hParams, 1) : 0; Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_ClearTeamScores); + Call_StartForward(g_hFWD_CTerrorGameRules_ClearTeamScores); Call_PushCell(value); Call_Finish(aResult); @@ -7611,14 +8049,14 @@ public MRESReturn ClearTeamScores(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn SetCampaignScores(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorGameRules_SetCampaignScores(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SetCampaignScores"); + //PrintToServer("##### DTR_CTerrorGameRules_SetCampaignScores"); int a1 = DHookGetParam(hParams, 1); int a2 = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SetCampaignScores); + Call_StartForward(g_hFWD_CTerrorGameRules_SetCampaignScores); Call_PushCellRef(a1); Call_PushCellRef(a2); Call_Finish(aResult); @@ -7640,12 +8078,12 @@ public MRESReturn SetCampaignScores(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn RecalculateVersusScore(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_RecalculateVersusScore(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR RecalculateVersusScore"); + //PrintToServer("##### DTR_CTerrorPlayer_RecalculateVersusScore"); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_RecalculateVersusScore); + Call_StartForward(g_hFWD_CTerrorPlayer_RecalculateVersusScore); Call_PushCell(pThis); Call_Finish(aResult); @@ -7658,15 +8096,15 @@ public MRESReturn RecalculateVersusScore(int pThis, Handle hReturn, Handle hPara return MRES_Ignored; } -public MRESReturn OnFirstSurvivorLeftSafeArea(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirector_OnFirstSurvivorLeftSafeArea(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnFirstSurvivorLeftSafeArea"); + //PrintToServer("##### DTR_CDirector_OnFirstSurvivorLeftSafeArea"); if( DHookIsNullParam(hParams, 1) ) return MRES_Ignored; int value = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnFirstSurvivorLeftSafeArea); + Call_StartForward(g_hFWD_CDirector_OnFirstSurvivorLeftSafeArea); Call_PushCell(value); Call_Finish(aResult); @@ -7677,8 +8115,8 @@ public MRESReturn OnFirstSurvivorLeftSafeArea(Handle hReturn, Handle hParams) // Remove bool that says not to check if they have left ValidateAddress(g_pDirector, "g_pDirector"); - ValidateAddress(m_bFirstSurvivorLeftStartArea, "m_bFirstSurvivorLeftStartArea"); - StoreToAddress(g_pDirector + view_as
    (m_bFirstSurvivorLeftStartArea), 0, NumberType_Int8); + ValidateAddress(g_iOff_m_bFirstSurvivorLeftStartArea, "m_bFirstSurvivorLeftStartArea"); + StoreToAddress(g_pDirector + view_as
    (g_iOff_m_bFirstSurvivorLeftStartArea), 0, NumberType_Int8); } DHookSetReturn(hReturn, 0); @@ -7688,11 +8126,11 @@ public MRESReturn OnFirstSurvivorLeftSafeArea(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn MobRushStart(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirector_MobRushStart(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR MobRushStart"); + //PrintToServer("##### DTR_CDirector_MobRushStart"); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_MobRushStart); + Call_StartForward(g_hFWD_CDirector_MobRushStart); Call_Finish(aResult); if( aResult == Plugin_Handled ) @@ -7704,13 +8142,13 @@ public MRESReturn MobRushStart(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn SpawnITMob(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnITMob(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnITMob"); + //PrintToServer("##### DTR_ZombieManager_SpawnITMob"); int a1 = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SpawnITMob); + Call_StartForward(g_hFWD_ZombieManager_SpawnITMob); Call_PushCellRef(a1); Call_Finish(aResult); @@ -7730,13 +8168,13 @@ public MRESReturn SpawnITMob(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn SpawnMob(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_SpawnMob(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SpawnMob"); + //PrintToServer("##### DTR_ZombieManager_SpawnMob"); int a1 = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SpawnMob); + Call_StartForward(g_hFWD_ZombieManager_SpawnMob); Call_PushCellRef(a1); Call_Finish(aResult); @@ -7756,11 +8194,11 @@ public MRESReturn SpawnMob(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn EnterGhostStatePre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_EnterGhostState_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR EnterGhostStatePre"); + //PrintToServer("##### DTR_CTerrorPlayer_EnterGhostState_Pre"); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_EnterGhostStatePre); + Call_StartForward(g_hFWD_CTerrorPlayer_EnterGhostStatePre); Call_PushCell(pThis); Call_Finish(aResult); @@ -7773,24 +8211,24 @@ public MRESReturn EnterGhostStatePre(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn EnterGhostState(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_EnterGhostState_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR EnterGhostState"); - Call_StartForward(g_hForward_EnterGhostState); + //PrintToServer("##### DTR_CTerrorPlayer_EnterGhostState_Post"); + Call_StartForward(g_hFWD_CTerrorPlayer_EnterGhostState); Call_PushCell(pThis); Call_Finish(); return MRES_Ignored; } -public MRESReturn IsTeamFullPre(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirector_IsTeamFull(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR IsTeamFullPre"); + //PrintToServer("##### DTR_CDirector_IsTeamFull"); int a1 = DHookGetParam(hParams, 1); bool a2 = DHookGetReturn(hReturn); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_IsTeamFull); + Call_StartForward(g_hFWD_CDirector_IsTeamFull); Call_PushCell(a1); Call_PushCellRef(a2); Call_Finish(aResult); @@ -7804,37 +8242,40 @@ public MRESReturn IsTeamFullPre(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn GetCrouchTopSpeedPre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_GetCrouchTopSpeed_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetCrouchTopSpeedPre"); + //PrintToServer("##### DTR_CTerrorPlayer_GetCrouchTopSpeed_Pre"); + return MRES_Ignored; } -public MRESReturn GetCrouchTopSpeed(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_GetCrouchTopSpeed_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetCrouchTopSpeed"); - return GetSpeed(pThis, g_hForward_GetCrouchTopSpeed, hReturn); + //PrintToServer("##### DTR_CTerrorPlayer_GetCrouchTopSpeed_Post"); + return GetSpeed(pThis, g_hFWD_CTerrorPlayer_GetCrouchTopSpeed, hReturn); } -public MRESReturn GetRunTopSpeedPre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_GetRunTopSpeed_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetRunTopSpeedPre"); + //PrintToServer("##### DTR_CTerrorPlayer_GetRunTopSpeed_Pre"); + return MRES_Ignored; } -public MRESReturn GetRunTopSpeed(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_GetRunTopSpeed_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetRunTopSpeed"); - return GetSpeed(pThis, g_hForward_GetRunTopSpeed, hReturn); + //PrintToServer("##### DTR_CTerrorPlayer_GetRunTopSpeed_Post"); + return GetSpeed(pThis, g_hFWD_CTerrorPlayer_GetRunTopSpeed, hReturn); } -public MRESReturn GetWalkTopSpeedPre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_GetWalkTopSpeed_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetWalkTopSpeedPre"); + //PrintToServer("##### DTR_CTerrorPlayer_GetWalkTopSpeed_Pre"); + return MRES_Ignored; } -public MRESReturn GetWalkTopSpeed(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_GetWalkTopSpeed_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetWalkTopSpeed"); - return GetSpeed(pThis, g_hForward_GetWalkTopSpeed, hReturn); + //PrintToServer("##### DTR_CTerrorPlayer_GetWalkTopSpeed_Post"); + return GetSpeed(pThis, g_hFWD_CTerrorPlayer_GetWalkTopSpeed, hReturn); } MRESReturn GetSpeed(int pThis, Handle hForward, Handle hReturn) @@ -7856,15 +8297,15 @@ MRESReturn GetSpeed(int pThis, Handle hForward, Handle hReturn) return MRES_Ignored; } -public MRESReturn GetScriptValueInt(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirector_GetScriptValueInt(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetScriptValueInt"); + //PrintToServer("##### DTR_CDirector_GetScriptValueInt"); static char key[64]; DHookGetParamString(hParams, 1, key, sizeof(key)); int a2 = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_GetScriptValueInt); + Call_StartForward(g_hFWD_CDirector_GetScriptValueInt); Call_PushString(key); Call_PushCellRef(a2); Call_Finish(aResult); @@ -7879,15 +8320,15 @@ public MRESReturn GetScriptValueInt(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn GetScriptValueFloat(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirector_GetScriptValueFloat(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetScriptValueFloat"); + //PrintToServer("##### DTR_CDirector_GetScriptValueFloat"); static char key[64]; DHookGetParamString(hParams, 1, key, sizeof(key)); float a2 = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_GetScriptValueFloat); + Call_StartForward(g_hFWD_CDirector_GetScriptValueFloat); Call_PushString(key); Call_PushFloatRef(a2); Call_Finish(aResult); @@ -7902,9 +8343,9 @@ public MRESReturn GetScriptValueFloat(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn GetScriptValueString(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirector_GetScriptValueString(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetScriptValueString"); + //PrintToServer("##### DTR_CDirector_GetScriptValueString"); static char a1[128], a2[128], a3[128]; // Don't know how long they should be DHookGetParamString(hParams, 1, a1, sizeof(a1)); @@ -7916,7 +8357,7 @@ public MRESReturn GetScriptValueString(Handle hReturn, Handle hParams) DHookGetParamString(hParams, 3, a3, sizeof(a3)); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_GetScriptValueString); + Call_StartForward(g_hFWD_CDirector_GetScriptValueString); Call_PushString(a1); Call_PushString(a2); Call_PushString(a3); @@ -7933,13 +8374,13 @@ public MRESReturn GetScriptValueString(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn HasConfigurableDifficulty(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorGameRules_HasConfigurableDifficultySetting(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR HasConfigurableDifficulty"); + //PrintToServer("##### DTR_CTerrorGameRules_HasConfigurableDifficultySetting"); int a1 = DHookGetReturn(hReturn); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_HasConfigurableDifficulty); + Call_StartForward(g_hFWD_CTerrorGameRules_HasConfigurableDifficultySetting); Call_PushCellRef(a1); Call_Finish(aResult); @@ -7952,16 +8393,16 @@ public MRESReturn HasConfigurableDifficulty(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn GetSurvivorSet(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorGameRules_GetSurvivorSet(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetSurvivorSet"); - return SurvivorSet(g_hForward_GetSurvivorSet, hReturn); + //PrintToServer("##### DTR_CTerrorGameRules_GetSurvivorSet"); + return SurvivorSet(g_hFWD_CTerrorGameRules_GetSurvivorSet, hReturn); } -public MRESReturn FastGetSurvivorSet(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorGameRules_FastGetSurvivorSet(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR FastGetSurvivorSet"); - return SurvivorSet(g_hForward_FastGetSurvivorSet, hReturn); + //PrintToServer("##### DTR_CTerrorGameRules_FastGetSurvivorSet"); + return SurvivorSet(g_hFWD_CTerrorGameRules_FastGetSurvivorSet, hReturn); } MRESReturn SurvivorSet(Handle hForward, Handle hReturn) @@ -7982,9 +8423,9 @@ MRESReturn SurvivorSet(Handle hForward, Handle hReturn) return MRES_Ignored; } -public MRESReturn GetMissionVSBoss(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirectorVersusMode_GetMissionVersusBossSpawning(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetMissionVSBoss"); + //PrintToServer("##### DTR_CDirectorVersusMode_GetMissionVersusBossSpawning"); int plus = !g_bLeft4Dead2; float a1 = DHookGetParamObjectPtrVar(hParams, plus + 1, 0, ObjectValueType_Float); @@ -7993,7 +8434,7 @@ public MRESReturn GetMissionVSBoss(Handle hReturn, Handle hParams) float a4 = DHookGetParamObjectPtrVar(hParams, plus + 4, 0, ObjectValueType_Float); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_GetMissionVSBossSpawning); + Call_StartForward(g_hFWD_GetMissionVSBossSpawning); Call_PushFloatRef(a1); Call_PushFloatRef(a2); Call_PushFloatRef(a3); @@ -8023,101 +8464,269 @@ public MRESReturn GetMissionVSBoss(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn OnReplaceTank(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_ReplaceTank(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnReplaceTank"); + //PrintToServer("##### DTR_ZombieManager_ReplaceTank"); int a1 = DHookGetParam(hParams, 1); int a2 = DHookGetParam(hParams, 2); - Call_StartForward(g_hForward_OnReplaceTank); + Call_StartForward(g_hFWD_ZombieManager_ReplaceTank); Call_PushCell(a1); Call_PushCell(a2); Call_Finish(); + + return MRES_Ignored; } -public MRESReturn TryOfferingTankBot(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTankClaw_DoSwing_Pre(int pThis) { - // PrintToServer("##### DTR TryOfferingTankBot"); - int a1 = -1, a2; + // PrintToServer("##### DTR_CTankClaw_DoSwing_Pre"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hOwner"); - if( !g_bLeft4Dead2 && g_bLinuxOS ) - { - // L4D1 - if( !DHookIsNullParam(hParams, 2) ) - a1 = DHookGetParam(hParams, 2); + Call_StartForward(g_hFWD_CTankClaw_DoSwing_Pre); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_Finish(); - a2 = DHookGetParam(hParams, 3); - } - else - { - if( !DHookIsNullParam(hParams, 1) ) - a1 = DHookGetParam(hParams, 1); + return MRES_Ignored; +} - a2 = DHookGetParam(hParams, 2); - } +public MRESReturn DTR_CTankClaw_DoSwing_Post(int pThis) +{ + // PrintToServer("##### DTR_CTankClaw_DoSwing_Post"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hOwner"); - Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_TryOfferingTankBot); - Call_PushCell(a1); - Call_PushCellRef(a2); - Call_Finish(aResult); + Call_StartForward(g_hFWD_CTankClaw_DoSwing_Post); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_Finish(); - if( aResult == Plugin_Handled ) - { - DHookSetReturn(hReturn, 0); - return MRES_Supercede; - } + return MRES_Ignored; +} - // UNKNOWN - PROBABLY WORKING - if( aResult == Plugin_Changed ) - { - if( g_bLeft4Dead2 || !g_bLinuxOS ) - { - DHookSetParam(hParams, 2, a2); - DHookSetReturn(hReturn, a2); - } - else - { - // L4D1 - DHookSetParam(hParams, 3, a2); - } +public MRESReturn DTR_CTankClaw_GroundPound_Pre(int pThis) +{ + // PrintToServer("##### DTR_CTankClaw_GroundPound_Pre"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hOwner"); - return MRES_ChangedOverride; - } + Call_StartForward(g_hFWD_CTankClaw_GroundPound_Pre); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_Finish(); + + return MRES_Ignored; +} + +public MRESReturn DTR_CTankClaw_GroundPound_Post(int pThis) +{ + // PrintToServer("##### DTR_CTankClaw_GroundPound_Post"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hOwner"); + + Call_StartForward(g_hFWD_CTankClaw_GroundPound_Post); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_Finish(); return MRES_Ignored; } -public MRESReturn CThrowActivate(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTankClaw_OnPlayerHit_Pre(int pThis, Handle hParams) { - //PrintToServer("##### DTR CThrowActivate"); + //PrintToServer("##### DTR_CTankClaw_OnPlayerHit_Pre"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hOwner"); + int target = DHookGetParam(hParams, 1); + // bool incap = DHookGetParam(hParams, 2); // Unknown usage, always returns "1" + Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_CThrowActivate); + Call_StartForward(g_hFWD_CTankClaw_OnPlayerHit_Pre); + Call_PushCell(tank); Call_PushCell(pThis); + Call_PushCell(target); Call_Finish(aResult); + // WORKS - Blocks target player being flung if( aResult == Plugin_Handled ) { - DHookSetReturn(hReturn, 0); return MRES_Supercede; } return MRES_Ignored; } -public MRESReturn SelectTankAttackPre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTankClaw_OnPlayerHit_Post(int pThis, Handle hParams) { - //PrintToServer("##### DTR SelectTankAttackPre"); - if( pThis < 1 || pThis > MaxClients || !IsClientInGame(pThis) ) return MRES_Ignored; // Ignore weapons etc + //PrintToServer("##### DTR_CTankClaw_OnPlayerHit_Post"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hOwner"); + int target = DHookGetParam(hParams, 1); + // bool incap = DHookGetParam(hParams, 2); - int a1 = DHookGetParam(hParams, 1); - Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTankClaw_OnPlayerHit_Post); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_PushCell(target); + Call_Finish(); + return MRES_Ignored; +} +public MRESReturn DTR_CTankRock_Detonate(int pThis, Handle hParams) +{ + //PrintToServer("##### DTR_CTankRock_Detonate"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hThrower"); - // ANIMATION HOOK - int index = g_iHookedClients.FindValue(GetClientUserId(pThis)); - if( index != -1 ) + Call_StartForward(g_hFWD_CTankRock_Detonate); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_Finish(); + + // Freezes tank rock on hit, causes constant severe shake + // return MRES_Supercede; + + return MRES_Ignored; +} + +public MRESReturn DTR_CTankRock_OnRelease(int pThis, Handle hParams) +{ + //PrintToServer("##### DTR_CTankRock_OnRelease"); + int tank = GetEntPropEnt(pThis, Prop_Data, "m_hThrower"); + + float v1[3]; + float v2[3]; + float v3[3]; + float v4[3]; + + DHookGetParamVector(hParams, 1, v1); // vPos + DHookGetParamVector(hParams, 2, v2); // vAng + DHookGetParamVector(hParams, 3, v3); // vVel + DHookGetParamVector(hParams, 4, v4); // vRot + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTankRock_OnRelease); + Call_PushCell(tank); + Call_PushCell(pThis); + Call_PushArrayEx(v1, sizeof(v1), SM_PARAM_COPYBACK); + Call_PushArrayEx(v2, sizeof(v2), SM_PARAM_COPYBACK); + Call_PushArrayEx(v3, sizeof(v3), SM_PARAM_COPYBACK); + Call_PushArrayEx(v4, sizeof(v4), SM_PARAM_COPYBACK); + Call_Finish(aResult); + + /* + if( aResult == Plugin_Handled ) + { + // Causes the rock to not be thrown, but stuck to the Tanks hand + return MRES_Supercede; + } + // */ + + if( aResult == Plugin_Changed ) + { + DHookSetParamVector(hParams, 1, v1); + DHookSetParamVector(hParams, 2, v2); + DHookSetParamVector(hParams, 3, v3); + DHookSetParamVector(hParams, 4, v4); + return MRES_ChangedHandled; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CDirector_TryOfferingTankBot(Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CDirector_TryOfferingTankBot"); + int a1 = -1, a2; + + if( !DHookIsNullParam(hParams, 1) ) + a1 = DHookGetParam(hParams, 1); + + a2 = DHookGetParam(hParams, 2); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CDirector_TryOfferingTankBot); + Call_PushCell(a1); + Call_PushCellRef(a2); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + // UNKNOWN - PROBABLY WORKING + if( aResult == Plugin_Changed ) + { + DHookSetParam(hParams, 2, a2); + DHookSetReturn(hReturn, a2); + + return MRES_ChangedOverride; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CDirector_TryOfferingTankBot_Clone(Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CDirector_TryOfferingTankBot_Clone"); + int a1 = -1, a2; + + if( !DHookIsNullParam(hParams, 2) ) + a1 = DHookGetParam(hParams, 2); + + a2 = DHookGetParam(hParams, 3); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CDirector_TryOfferingTankBot); + Call_PushCell(a1); + Call_PushCellRef(a2); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + // UNKNOWN - PROBABLY WORKING + if( aResult == Plugin_Changed ) + { + DHookSetParam(hParams, 3, a2); + + return MRES_ChangedOverride; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CThrow_ActivateAbililty(int pThis, Handle hReturn, Handle hParams) +{ + //PrintToServer("##### DTR_CThrow_ActivateAbililty"); + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CThrow_ActivateAbililty); + Call_PushCell(pThis); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CBaseAnimating_SelectWeightedSequence_Pre(int pThis, Handle hReturn, Handle hParams) +{ + //PrintToServer("##### DTR_CBaseAnimating_SelectWeightedSequence_Pre"); + if( pThis < 1 || pThis > MaxClients || !IsClientInGame(pThis) ) return MRES_Ignored; // Ignore weapons etc + + int a1 = DHookGetParam(hParams, 1); + Action aResult = Plugin_Continue; + + + + // ANIMATION HOOK + int index = g_iAnimationHookedClients.FindValue(GetClientUserId(pThis)); + if( index != -1 ) { Call_StartForward(g_hAnimationCallbackPre); Call_PushCell(pThis); @@ -8143,7 +8752,7 @@ public MRESReturn SelectTankAttackPre(int pThis, Handle hReturn, Handle hParams) if( GetClientTeam(pThis) != 3 || GetEntProp(pThis, Prop_Send, "m_zombieClass") != g_iClassTank ) return MRES_Ignored; - Call_StartForward(g_hForward_SelectTankAttackPre); + Call_StartForward(g_hFWD_CBaseAnimating_SelectWeightedSequence_Pre); Call_PushCell(pThis); Call_PushCellRef(a1); Call_Finish(aResult); @@ -8157,9 +8766,9 @@ public MRESReturn SelectTankAttackPre(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn SelectTankAttack(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CBaseAnimating_SelectWeightedSequence_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SelectTankAttack"); + //PrintToServer("##### DTR_CBaseAnimating_SelectWeightedSequence_Post"); if( pThis < 1 || pThis > MaxClients || !IsClientInGame(pThis) ) return MRES_Ignored; // Ignore weapons etc int a1 = DHookGetReturn(hReturn); @@ -8168,10 +8777,10 @@ public MRESReturn SelectTankAttack(int pThis, Handle hReturn, Handle hParams) // ANIMATION HOOK - int index = g_iHookedClients.FindValue(GetClientUserId(pThis)); + int index = g_iAnimationHookedClients.FindValue(GetClientUserId(pThis)); if( index != -1 ) { - Call_StartForward(g_hAnimationCallback); + Call_StartForward(g_hAnimationCallbackPost); Call_PushCell(pThis); Call_PushCellRef(a1); Call_Finish(aResult); @@ -8197,7 +8806,7 @@ public MRESReturn SelectTankAttack(int pThis, Handle hReturn, Handle hParams) if( GetClientTeam(pThis) != 3 || GetEntProp(pThis, Prop_Send, "m_zombieClass") != g_iClassTank ) return MRES_Ignored; - Call_StartForward(g_hForward_SelectTankAttack); + Call_StartForward(g_hFWD_CBaseAnimating_SelectWeightedSequence_Post); Call_PushCell(pThis); Call_PushCellRef(a1); Call_Finish(aResult); @@ -8211,14 +8820,14 @@ public MRESReturn SelectTankAttack(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn StartMeleeSwing(Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorMeleeWeapon_StartMeleeSwing(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR StartMeleeSwing"); + //PrintToServer("##### DTR_CTerrorMeleeWeapon_StartMeleeSwing"); int a1 = DHookGetParam(hParams, 1); int a2 = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_StartMeleeSwing); + Call_StartForward(g_hFWD_StartMeleeSwing); Call_PushCell(a1); Call_PushCell(a2); Call_Finish(aResult); @@ -8232,12 +8841,51 @@ public MRESReturn StartMeleeSwing(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn SendInRescueVehicle(Handle hReturn) -// public MRESReturn SendInRescueVehicle(Handle hParams) +public MRESReturn DTR_CTerrorMeleeWeapon_GetDamageForVictim_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR SendInRescueVehicle"); + //PrintToServer("##### DTR_CTerrorMeleeWeapon_GetDamageForVictim_Pre"); + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorMeleeWeapon_GetDamageForVictim_Post(int pThis, Handle hReturn, Handle hParams) +{ + //PrintToServer("##### DTR_CTerrorMeleeWeapon_GetDamageForVictim_Post"); + int victim = DHookGetParam(hParams, 1); + if(! IsValidEdict(victim) ) + return MRES_Ignored; + + int client = GetEntPropEnt(pThis, Prop_Send, "m_hOwnerEntity"); + float damage = DHookGetReturn(hReturn); + Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_SendInRescueVehicle); + Call_StartForward(g_hFWD_GetDamageForVictim); + Call_PushCell(client); + Call_PushCell(pThis); + Call_PushCell(victim); + Call_PushFloatRef(damage); + Call_Finish(aResult); + + if( aResult == Plugin_Changed ) + { + DHookSetReturn(hReturn, damage); + return MRES_Override; + } + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0.0); + return MRES_Override; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CDirectorScriptedEventManager_SendInRescueVehicle(Handle hReturn) +// public MRESReturn DTR_CDirectorScriptedEventManager_SendInRescueVehicle(Handle hParams) +{ + //PrintToServer("##### DTR_CDirectorScriptedEventManager_SendInRescueVehicle"); + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CDirectorScriptedEventManager_SendInRescueVehicle); Call_Finish(aResult); if( aResult == Plugin_Handled ) @@ -8251,9 +8899,9 @@ public MRESReturn SendInRescueVehicle(Handle hReturn) return MRES_Ignored; } -public MRESReturn ChangeFinaleStage(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirectorScriptedEventManager_ChangeFinaleStage(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR ChangeFinaleStage"); + //PrintToServer("##### DTR_CDirectorScriptedEventManager_ChangeFinaleStage"); int a1 = DHookGetParam(hParams, 1); static char a2[64]; @@ -8261,7 +8909,7 @@ public MRESReturn ChangeFinaleStage(Handle hReturn, Handle hParams) DHookGetParamString(hParams, 2, a2, sizeof(a2)); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_ChangeFinaleStage); + Call_StartForward(g_hFWD_CDirectorScriptedEventManager_ChangeFinaleStage); Call_PushCellRef(a1); Call_PushString(a2); Call_Finish(aResult); @@ -8282,15 +8930,15 @@ public MRESReturn ChangeFinaleStage(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn EndVersusModeRoundPre(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirectorVersusMode_EndVersusModeRound_Pre(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR EndVersusModeRoundPre"); + //PrintToServer("##### DTR_CDirectorVersusMode_EndVersusModeRound_Pre"); if( g_bRoundEnded ) return MRES_Ignored; int a1 = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_EndVersusModeRound); + Call_StartForward(g_hFWD_CDirectorVersusMode_EndVersusModeRound_Pre); Call_PushCell(a1); Call_Finish(aResult); @@ -8303,23 +8951,23 @@ public MRESReturn EndVersusModeRoundPre(Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn EndVersusModeRound(Handle hReturn, Handle hParams) +public MRESReturn DTR_CDirectorVersusMode_EndVersusModeRound_Post(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR EndVersusModeRound"); + //PrintToServer("##### DTR_CDirectorVersusMode_EndVersusModeRound_Post"); if( g_bRoundEnded ) return MRES_Ignored; g_bRoundEnded = true; - Call_StartForward(g_hForward_EndVersusModeRoundPost); + Call_StartForward(g_hFWD_CDirectorVersusMode_EndVersusModeRound_Post); Call_Finish(); return MRES_Ignored; } -public MRESReturn LedgeGrabbed(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnLedgeGrabbed(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR LedgeGrabbed"); + //PrintToServer("##### DTR_CTerrorPlayer_OnLedgeGrabbed"); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_LedgeGrabbed); + Call_StartForward(g_hFWD_CTerrorPlayer_OnLedgeGrabbed); Call_PushCell(pThis); Call_Finish(aResult); @@ -8327,30 +8975,33 @@ public MRESReturn LedgeGrabbed(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn OnRevivedPre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnRevived_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnRevivedPre"); + //PrintToServer("##### DTR_CTerrorPlayer_OnRevived_Pre"); + return MRES_Ignored; } -public MRESReturn OnRevived(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnRevived_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnRevived"); + //PrintToServer("##### DTR_CTerrorPlayer_OnRevived_Post"); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnRevived); + Call_StartForward(g_hFWD_CTerrorPlayer_OnRevived_Post); Call_PushCell(pThis); Call_Finish(aResult); + + return MRES_Ignored; } -public MRESReturn OnPlayerStagger(int pThis, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnStaggered(int pThis, Handle hParams) { - //PrintToServer("##### DTR OnPlayerStagger"); + //PrintToServer("##### DTR_CTerrorPlayer_OnStaggered"); int source = -1; if( !DHookIsNullParam(hParams, 1) ) source = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnPlayerStagger); + Call_StartForward(g_hFWD_CTerrorPlayer_OnStaggered); Call_PushCell(pThis); Call_PushCell(source); Call_Finish(aResult); @@ -8359,15 +9010,35 @@ public MRESReturn OnPlayerStagger(int pThis, Handle hParams) return MRES_Ignored; } -public MRESReturn ShovedBySurvivor(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnStaggered_Clone(Handle hParams) { - //PrintToServer("##### DTR ShovedBySurvivor"); + //PrintToServer("##### DTR_CTerrorPlayer_OnStaggered_Clone"); + int target = DHookGetParam(hParams, 1); + + int source = -1; + + if( !DHookIsNullParam(hParams, 2) ) + source = DHookGetParam(hParams, 2); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_OnStaggered); + Call_PushCell(target); + Call_PushCell(source); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) return MRES_Supercede; + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_OnShovedBySurvivor(int pThis, Handle hReturn, Handle hParams) +{ + //PrintToServer("##### DTR_CTerrorPlayer_OnShovedBySurvivor"); float a2[3]; int a1 = DHookGetParam(hParams, 1); DHookGetParamVector(hParams, 2, a2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_ShovedBySurvivor); + Call_StartForward(g_hFWD_CTerrorPlayer_OnShovedBySurvivor); Call_PushCell(a1); Call_PushCell(pThis); Call_PushArray(a2, sizeof(a2)); @@ -8382,9 +9053,33 @@ public MRESReturn ShovedBySurvivor(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn CTerrorWeapon_OnHit(int weapon, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnShovedBySurvivor_Clone(Handle hReturn, Handle hParams) +{ + //PrintToServer("##### DTR_CTerrorPlayer_OnShovedBySurvivor_Clone"); + float a3[3]; + int a1 = DHookGetParam(hParams, 1); + int a2 = DHookGetParam(hParams, 2); + DHookGetParamVector(hParams, 3, a3); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_OnShovedBySurvivor); + Call_PushCell(a2); + Call_PushCell(a1); + Call_PushArray(a3, sizeof(a3)); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorWeapon_OnHit(int weapon, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR CTerrorWeapon_OnHit"); + //PrintToServer("##### DTR_CTerrorWeapon_OnHit"); bool userCall = DHookGetParam(hParams, 3); if( userCall ) { @@ -8415,7 +9110,7 @@ public MRESReturn CTerrorWeapon_OnHit(int weapon, Handle hReturn, Handle hParams DHookGetParamVector(hParams, 2, vec); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_CTerrorWeapon_OnHit); + Call_StartForward(g_hFWD_CTerrorWeapon_OnHit); Call_PushCell(client); Call_PushCell(target); Call_PushCell(weapon); @@ -8433,13 +9128,13 @@ public MRESReturn CTerrorWeapon_OnHit(int weapon, Handle hReturn, Handle hParams return MRES_Ignored; } -public MRESReturn OnShovedByPounceLanding(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnShovedByPounceLanding"); + //PrintToServer("##### DTR_CTerrorPlayer_OnShovedByPounceLanding"); int a1 = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnShovedByPounceLanding); + Call_StartForward(g_hFWD_CTerrorPlayer_OnShovedByPounceLanding); Call_PushCell(pThis); Call_PushCell(a1); Call_Finish(aResult); @@ -8453,14 +9148,15 @@ public MRESReturn OnShovedByPounceLanding(int pThis, Handle hReturn, Handle hPar return MRES_Ignored; } -public MRESReturn OnPlayerFling(int pThis, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_Fling(int pThis, Handle hParams) { + //PrintToServer("##### DTR_CTerrorPlayer_Fling"); float vPos[3]; int attacker = DHookGetParam(hParams, 3); DHookGetParamVector(hParams, 1, vPos); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_PlayerFling); + Call_StartForward(g_hFWD_CTerrorPlayer_Fling); Call_PushCell(pThis); Call_PushCell(attacker); Call_PushArray(vPos, sizeof(vPos)); @@ -8474,12 +9170,13 @@ public MRESReturn OnPlayerFling(int pThis, Handle hParams) return MRES_Ignored; } -public MRESReturn OnFatalFalling(int pThis, Handle hParams) +public MRESReturn DTR_CDeathFallCamera_Enable(int pThis, Handle hParams) { + //PrintToServer("##### DTR_CDeathFallCamera_Enable"); int client = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_FatalFalling); + Call_StartForward(g_hFWD_CDeathFallCamera_Enable); Call_PushCell(client); Call_PushCell(pThis); Call_Finish(aResult); @@ -8492,58 +9189,64 @@ public MRESReturn OnFatalFalling(int pThis, Handle hParams) return MRES_Ignored; } -public MRESReturn OnFallingPre(int pThis, Handle hReturn) +public MRESReturn DTR_CTerrorPlayer_OnFalling_Pre(int pThis, Handle hReturn) { + //PrintToServer("##### DTR_CTerrorPlayer_OnFalling_Pre"); return MRES_Ignored; } -public MRESReturn OnFalling(int pThis, Handle hReturn) +public MRESReturn DTR_CTerrorPlayer_OnFalling_Post(int pThis, Handle hReturn) { - Call_StartForward(g_hForward_Falling); + //PrintToServer("##### DTR_CTerrorPlayer_OnFalling_Post"); + Call_StartForward(g_hFWD_CTerrorPlayer_OnFalling_Post); Call_PushCell(pThis); Call_Finish(); return MRES_Ignored; } -public MRESReturn OnEnterStasisPre(int pThis, Handle hReturn) +public MRESReturn DTR_Tank_EnterStasis_Pre(int pThis, Handle hReturn) { + //PrintToServer("##### DTR_Tank_EnterStasis_Pre"); return MRES_Ignored; } -public MRESReturn OnEnterStasis(int pThis, Handle hReturn) +public MRESReturn DTR_Tank_EnterStasis_Post(int pThis, Handle hReturn) { - Call_StartForward(g_hForward_EnterStasis); + //PrintToServer("##### DTR_Tank_EnterStasis_Post"); + Call_StartForward(g_hFWD_Tank_EnterStasis_Post); Call_PushCell(pThis); Call_Finish(); return MRES_Ignored; } -public MRESReturn OnLeaveStasisPre(int pThis, Handle hReturn) +public MRESReturn DTR_Tank_LeaveStasis_Pre(int pThis, Handle hReturn) { + //PrintToServer("##### DTR_Tank_LeaveStasis_Pre"); return MRES_Ignored; } -public MRESReturn OnLeaveStasis(int pThis, Handle hReturn) +public MRESReturn DTR_Tank_LeaveStasis_Post(int pThis, Handle hReturn) { - Call_StartForward(g_hForward_LeaveStasis); + //PrintToServer("##### DTR_Tank_LeaveStasis_Post"); + Call_StartForward(g_hFWD_Tank_LeaveStasis_Post); Call_PushCell(pThis); Call_Finish(); return MRES_Ignored; } -public MRESReturn InfernoSpread(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CInferno_Spread(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR InfernoSpread"); + //PrintToServer("##### DTR_CInferno_Spread"); float vPos[3]; DHookGetParamVector(hParams, 1, vPos); int client = GetEntPropEnt(pThis, Prop_Send, "m_hOwnerEntity"); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_InfernoSpread); + Call_StartForward(g_hFWD_CInferno_Spread); Call_PushCell(client); Call_PushCell(pThis); Call_PushFloatRef(vPos[0]); @@ -8567,13 +9270,13 @@ public MRESReturn InfernoSpread(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn OnUseHealingItems(int pThis, Handle hReturn, Handle hParams) -// public MRESReturn OnUseHealingItems(Handle hParams) +public MRESReturn DTR_SurvivorBot_UseHealingItems(int pThis, Handle hReturn, Handle hParams) +// public MRESReturn DTR_SurvivorBot_UseHealingItems(Handle hParams) { - //PrintToServer("##### DTR OnUseHealingItems"); + //PrintToServer("##### DTR_SurvivorBot_UseHealingItems"); // int pThis = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnUseHealingItems); + Call_StartForward(g_hFWD_SurvivorBot_UseHealingItems); Call_PushCell(pThis); Call_Finish(aResult); @@ -8588,14 +9291,15 @@ public MRESReturn OnUseHealingItems(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn OnFindScavengeItemPre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_SurvivorBot_FindScavengeItem_Pre(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnFindScavengeItemPre"); + //PrintToServer("##### DTR_SurvivorBot_FindScavengeItem_Pre"); + return MRES_Ignored; } -public MRESReturn OnFindScavengeItem(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_SurvivorBot_FindScavengeItem_Post(int pThis, Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnFindScavengeItem"); + //PrintToServer("##### DTR_SurvivorBot_FindScavengeItem_Post"); int a1 = DHookGetReturn(hReturn); if( a1 == -1 ) a1 = 0; @@ -8603,7 +9307,7 @@ public MRESReturn OnFindScavengeItem(int pThis, Handle hReturn, Handle hParams) // float a2 = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnFindScavengeItem); + Call_StartForward(g_hFWD_SurvivorBot_FindScavengeItem_Post); Call_PushCell(pThis); Call_PushCellRef(a1); Call_Finish(aResult); @@ -8626,19 +9330,20 @@ public MRESReturn OnFindScavengeItem(int pThis, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn OnChooseVictimPre(int client, Handle hReturn) +public MRESReturn DTR_BossZombiePlayerBot_ChooseVictim_Pre(int client, Handle hReturn) { - //PrintToServer("##### DTR OnChooseVictimPre"); + //PrintToServer("##### DTR_BossZombiePlayerBot_ChooseVictim_Pre"); + return MRES_Ignored; } -public MRESReturn OnChooseVictim(int client, Handle hReturn) +public MRESReturn DTR_BossZombiePlayerBot_ChooseVictim_Post(int client, Handle hReturn) { - //PrintToServer("##### DTR OnChooseVictim"); + //PrintToServer("##### DTR_BossZombiePlayerBot_ChooseVictim_Post"); int a1 = DHookGetReturn(hReturn); if( a1 == -1 ) a1 = 0; Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnChooseVictim); + Call_StartForward(g_hFWD_BossZombiePlayerBot_ChooseVictim_Post); Call_PushCell(client); Call_PushCellRef(a1); Call_Finish(aResult); @@ -8658,37 +9363,313 @@ public MRESReturn OnChooseVictim(int client, Handle hReturn) return MRES_Ignored; } -public MRESReturn OnMaterializeFromGhostPre(int client) +public MRESReturn DTR_CTerrorPlayer_MaterializeFromGhost_Pre(int client) +{ + //PrintToServer("##### DTR_CTerrorPlayer_MaterializeFromGhost_Pre"); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_MaterializeFromGhost_Pre); + Call_PushCell(client); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_MaterializeFromGhost_Post(int client) +{ + //PrintToServer("##### DTR_CTerrorPlayer_MaterializeFromGhost_Post"); + + Call_StartForward(g_hFWD_CTerrorPlayer_MaterializeFromGhost_Post); + Call_PushCell(client); + Call_Finish(); + + return MRES_Ignored; +} + +public MRESReturn DTR_CPipeBombProjectile_Create_Pre(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnMaterializeFromGhostPre"); + // PrintToServer("##### DTR_CPipeBombProjectile_Create_Pre"); + + int client; + if( !DHookIsNullParam(hParams, 5) ) + client = DHookGetParam(hParams, 5); + + float v1[3]; + float v2[3]; + float v3[3]; + float v4[3]; + + DHookGetParamVector(hParams, 1, v1); // vPos + DHookGetParamVector(hParams, 2, v2); // vAng + DHookGetParamVector(hParams, 3, v3); // vVel + DHookGetParamVector(hParams, 4, v4); // vRot Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnMaterializeFromGhostPre); + Call_StartForward(g_hFWD_CPipeBombProjectile_Create_Pre); Call_PushCell(client); + Call_PushArrayEx(v1, sizeof(v1), SM_PARAM_COPYBACK); + Call_PushArrayEx(v2, sizeof(v2), SM_PARAM_COPYBACK); + Call_PushArrayEx(v3, sizeof(v3), SM_PARAM_COPYBACK); + Call_PushArrayEx(v4, sizeof(v4), SM_PARAM_COPYBACK); Call_Finish(aResult); + if( aResult == Plugin_Changed ) + { + DHookSetParamVector(hParams, 1, v1); + DHookSetParamVector(hParams, 2, v2); + DHookSetParamVector(hParams, 3, v3); + DHookSetParamVector(hParams, 4, v4); + return MRES_ChangedHandled; + } + if( aResult == Plugin_Handled ) { + DHookSetReturn(hReturn, 0); return MRES_Supercede; } return MRES_Ignored; } -public MRESReturn OnMaterialize(int client) +public MRESReturn DTR_CPipeBombProjectile_Create_Post(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR OnMaterializeFromGhost"); + // PrintToServer("##### DTR_CPipeBombProjectile_Create_Post"); + + int client; + if( !DHookIsNullParam(hParams, 5) ) + client = DHookGetParam(hParams, 5); - Call_StartForward(g_hForward_OnMaterializeFromGhost); + int entity = DHookGetReturn(hReturn); + + float v1[3]; + float v2[3]; + float v3[3]; + float v4[3]; + + DHookGetParamVector(hParams, 1, v1); // vPos + DHookGetParamVector(hParams, 2, v2); // vAng + DHookGetParamVector(hParams, 3, v3); // vVel + DHookGetParamVector(hParams, 4, v4); // vRot + + Call_StartForward(g_hFWD_CPipeBombProjectile_Create_Post); Call_PushCell(client); + Call_PushCell(entity); + Call_PushArray(v1, sizeof(v1)); + Call_PushArray(v2, sizeof(v2)); + Call_PushArray(v3, sizeof(v3)); + Call_PushArray(v4, sizeof(v4)); Call_Finish(); return MRES_Ignored; } -public MRESReturn OnVomitedUpon(int client, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_Extinguish(int client) +{ + // PrintToServer("##### DTR_CTerrorPlayer_Extinguish"); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_Extinguish); + Call_PushCell(client); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CBreakableProp_Break_Pre(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CBreakableProp_Break_Pre"); + return MRES_Ignored; +} + +public MRESReturn DTR_CBreakableProp_Break_Post(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CBreakableProp_Break_Post"); + + int entity; + if( !DHookIsNullParam(hParams, 1) ) + entity = DHookGetParam(hParams, 1); + + Call_StartForward(g_hFWD_CBreakableProp_Break_Post); + Call_PushCell(pThis); + Call_PushCell(entity); + Call_Finish(); + + return MRES_Ignored; +} + +public MRESReturn DTR_CGasCanEvent_Killed(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CGasCanEvent_Killed"); + + int a1 = DHookGetParamObjectPtrVar(hParams, 1, 48, ObjectValueType_EhandlePtr); + int a2 = DHookGetParamObjectPtrVar(hParams, 1, 52, ObjectValueType_EhandlePtr); + + Call_StartForward(g_hFWD_CGasCanEvent_Killed); + Call_PushCell(pThis); + Call_PushCell(a1); + Call_PushCell(a2); + Call_Finish(); + + return MRES_Ignored; +} + +public MRESReturn DTR_CGasCan_OnActionComplete(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CGasCan_OnActionComplete"); + + int client; + if( !DHookIsNullParam(hParams, 1) ) + client = DHookGetParam(hParams, 1); + + int nozzle = DHookGetParam(hParams, 2); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CGasCan_OnActionComplete); + Call_PushCell(client); + Call_PushCell(pThis); + Call_PushCell(nozzle); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_OnPouncedOnSurvivor(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CTerrorPlayer_OnPouncedOnSurvivor"); + + int target; + if( !DHookIsNullParam(hParams, 1) ) + target = DHookGetParam(hParams, 1); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_OnPouncedOnSurvivor); + Call_PushCell(target); + Call_PushCell(pThis); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_GrabVictimWithTongue(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CTerrorPlayer_GrabVictimWithTongue"); + + int target; + if( !DHookIsNullParam(hParams, 1) ) + target = DHookGetParam(hParams, 1); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_GrabVictimWithTongue); + Call_PushCell(target); + Call_PushCell(pThis); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_OnLeptOnSurvivor(int pThis, Handle hReturn, Handle hParams) { - // PrintToServer("##### DTR OnVomitedUpon"); + // PrintToServer("##### DTR_CTerrorPlayer_OnLeptOnSurvivor"); + + int target; + if( !DHookIsNullParam(hParams, 1) ) + target = DHookGetParam(hParams, 1); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_OnLeptOnSurvivor); + Call_PushCell(target); + Call_PushCell(pThis); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_OnStartCarryingVictim(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CTerrorPlayer_OnStartCarryingVictim"); + + int target; + if( !DHookIsNullParam(hParams, 1) ) + target = DHookGetParam(hParams, 1); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CTerrorPlayer_OnStartCarryingVictim); + Call_PushCell(target); + Call_PushCell(pThis); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CInsectSwarm_CanHarm(int pThis, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CInsectSwarm_CanHarm"); + + int spitter = GetEntPropEnt(pThis, Prop_Data, "m_hOwnerEntity"); + + int entity; + if( !DHookIsNullParam(hParams, 1) ) + entity = DHookGetParam(hParams, 1); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CInsectSwarm_CanHarm); + Call_PushCell(pThis); + Call_PushCell(spitter); + Call_PushCell(entity); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + DHookSetReturn(hReturn, 0); + return MRES_Supercede; + } + + return MRES_Ignored; +} + +public MRESReturn DTR_CTerrorPlayer_OnVomitedUpon(int client, Handle hReturn, Handle hParams) +{ + // PrintToServer("##### DTR_CTerrorPlayer_OnVomitedUpon"); if( DHookIsNullParam(hParams, 1) ) return MRES_Ignored; @@ -8696,7 +9677,7 @@ public MRESReturn OnVomitedUpon(int client, Handle hReturn, Handle hParams) int a2 = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnVomitedUpon); + Call_StartForward(g_hFWD_CTerrorPlayer_OnVomitedUpon); Call_PushCell(client); Call_PushCellRef(a1); Call_PushCellRef(a2); @@ -8718,14 +9699,14 @@ public MRESReturn OnVomitedUpon(int client, Handle hReturn, Handle hParams) return MRES_Ignored; } -public MRESReturn OnHitByVomitJar(int client, Handle hReturn, Handle hParams) +public MRESReturn DTR_CTerrorPlayer_OnHitByVomitJar(int client, Handle hReturn, Handle hParams) { - // PrintToServer("##### DTR OnHitByVomitJar"); + // PrintToServer("##### DTR_CTerrorPlayer_OnHitByVomitJar"); int a1 = DHookGetParam(hParams, 1); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnHitByVomitJar); + Call_StartForward(g_hFWD_CTerrorPlayer_OnHitByVomitJar); Call_PushCell(client); Call_PushCellRef(a1); Call_Finish(aResult); @@ -8747,9 +9728,9 @@ public MRESReturn OnHitByVomitJar(int client, Handle hReturn, Handle hParams) /* // Removed because it spawns specials at 0,0,0 when modifying any value. -public MRESReturn GetRandomPZSpawnPos(Handle hReturn, Handle hParams) +public MRESReturn DTR_ZombieManager_GetRandomPZSpawnPosition(Handle hReturn, Handle hParams) { - //PrintToServer("##### DTR GetRandomPZSpawnPos"); + //PrintToServer("##### DTR_ZombieManager_GetRandomPZSpawnPosition"); int zombieClass = DHookGetParam(hParams, 1); int attempts = DHookGetParam(hParams, 2); @@ -8761,7 +9742,7 @@ public MRESReturn GetRandomPZSpawnPos(Handle hReturn, Handle hParams) DHookGetParamVector(hParams, 4, vecPos); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_GetRandomPZSpawnPos); + Call_StartForward(g_hFWD_GetRandomPZSpawnPos); Call_PushCellRef(client); Call_PushCellRef(zombieClass); Call_PushCellRef(attempts); @@ -8779,9 +9760,9 @@ public MRESReturn GetRandomPZSpawnPos(Handle hReturn, Handle hParams) if( vecPos[0] != 0.0 ) { // DHookSetParamVector(hParams, 4, vecPos); - DHookSetParamVector(hParams, 4, view_as({ 0.0, 0.0, 0.0})); + DHookSetParamVector(hParams, 4, view_as({0.0, 0.0, 0.0})); } else { - DHookSetParamVector(hParams, 4, view_as({ 0.0, 0.0, 0.0})); + DHookSetParamVector(hParams, 4, view_as({0.0, 0.0, 0.0})); } return MRES_ChangedHandled; @@ -8792,13 +9773,13 @@ public MRESReturn GetRandomPZSpawnPos(Handle hReturn, Handle hParams) // */ /* -public MRESReturn InfectedShoved(Handle hReturn, Handle hParams) +public MRESReturn DTR_InfectedShoved_OnShoved(Handle hReturn, Handle hParams) { int a1 = DHookGetParam(hParams, 1); int a2 = DHookGetParam(hParams, 2); Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_InfectedShoved); + Call_StartForward(g_hFWD_InfectedShoved); Call_PushCell(a1); Call_PushCell(a2); Call_Finish(aResult); @@ -8809,17 +9790,17 @@ public MRESReturn InfectedShoved(Handle hReturn, Handle hParams) // */ /* -public MRESReturn OnWaterMovePre(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CBasePlayer_WaterMove_Pre(int pThis, Handle hReturn, Handle hParams) { } -public MRESReturn OnWaterMove(int pThis, Handle hReturn, Handle hParams) +public MRESReturn DTR_CBasePlayer_WaterMove_Post(int pThis, Handle hReturn, Handle hParams) { int a1 = DHookGetReturn(hReturn); if( a1 ) { Action aResult = Plugin_Continue; - Call_StartForward(g_hForward_OnWaterMove); + Call_StartForward(g_hFWD_OnWaterMove); Call_PushCell(pThis); Call_Finish(aResult); @@ -8850,7 +9831,7 @@ public int Native_VS_GetMapNumber(Handle plugin, int numParams) if( GetVScriptOutput(code, buffer, sizeof(buffer)) ) return StringToInt(buffer); else - return false; + return 0; } public int Native_VS_HasEverBeenInjured(Handle plugin, int numParams) @@ -8893,7 +9874,7 @@ public any Native_VS_GetAliveDuration(Handle plugin, int numParams) if( GetVScriptOutput(code, buffer, sizeof(buffer)) ) return StringToFloat(buffer); else - return false; + return 0.0; } public int Native_VS_IsDead(Handle plugin, int numParams) @@ -9008,7 +9989,7 @@ public int Native_VS_GetSenseFlags(Handle plugin, int numParams) if( GetVScriptOutput(code, buffer, sizeof(buffer)) ) return StringToInt(buffer); else - return false; + return 0; } public int Native_VS_NavAreaBuildPath(Handle plugin, int numParams) @@ -9142,7 +10123,7 @@ bool GetVScriptOutput(char[] code, char[] ret, int maxlength) } else { - Format(buffer, length, "Convars.SetValue(\"l4d2_vscript_return\", \"\" + %s + \"\");", code); + FormatEx(buffer, length, "Convars.SetValue(\"l4d2_vscript_return\", \"\" + %s + \"\");", code); } // Run code @@ -9154,8 +10135,8 @@ bool GetVScriptOutput(char[] code, char[] ret, int maxlength) #endif // Retrieve value and return to buffer - g_hCvarVScriptBuffer.GetString(ret, maxlength); - g_hCvarVScriptBuffer.SetString(""); + g_hCvar_VScriptBuffer.GetString(ret, maxlength); + g_hCvar_VScriptBuffer.SetString(""); if( ret[0] == '\x0') return false; @@ -9164,6 +10145,26 @@ bool GetVScriptOutput(char[] code, char[] ret, int maxlength) +// ==================================================================================================== +// STOCKS - HEALTH +// ==================================================================================================== +float GetTempHealth(int client) +{ + float fGameTime = GetGameTime(); + float fHealthTime = GetEntPropFloat(client, Prop_Send, "m_healthBufferTime"); + float fHealth = GetEntPropFloat(client, Prop_Send, "m_healthBuffer"); + fHealth -= (fGameTime - fHealthTime) * g_hCvar_PillsDecay.FloatValue; + return fHealth < 0.0 ? 0.0 : fHealth; +} + +void SetTempHealth(int client, float fHealth) +{ + SetEntPropFloat(client, Prop_Send, "m_healthBuffer", fHealth < 0.0 ? 0.0 : fHealth); + SetEntPropFloat(client, Prop_Send, "m_healthBufferTime", GetGameTime()); +} + + + // ==================================================================================================== // MEMORY HELPERS // ==================================================================================================== @@ -9221,24 +10222,4 @@ stock void ReadMemoryString(int addr, char[] temp, int size) return; } } -} - - - -// ==================================================================================================== -// STOCKS - HEALTH -// ==================================================================================================== -float GetTempHealth(int client) -{ - float fGameTime = GetGameTime(); - float fHealthTime = GetEntPropFloat(client, Prop_Send, "m_healthBufferTime"); - float fHealth = GetEntPropFloat(client, Prop_Send, "m_healthBuffer"); - fHealth -= (fGameTime - fHealthTime) * g_hDecayDecay.FloatValue; - return fHealth < 0.0 ? 0.0 : fHealth; -} - -void SetTempHealth(int client, float fHealth) -{ - SetEntPropFloat(client, Prop_Send, "m_healthBuffer", fHealth < 0.0 ? 0.0 : fHealth); - SetEntPropFloat(client, Prop_Send, "m_healthBufferTime", GetGameTime()); } \ No newline at end of file diff --git a/addons/sourcemod/scripting/left4dhooks_test.sp b/addons/sourcemod/scripting/left4dhooks_test.sp index e51a5327f..a553933ab 100644 --- a/addons/sourcemod/scripting/left4dhooks_test.sp +++ b/addons/sourcemod/scripting/left4dhooks_test.sp @@ -18,7 +18,7 @@ -#define PLUGIN_VERSION "1.36" +#define PLUGIN_VERSION "1.69" /*======================================================================================= Plugin Info: @@ -32,6 +32,157 @@ ======================================================================================== Change Log: +1.69 (03-Nov-2021) + - Added forward "L4D_OnPouncedOnSurvivor" to notify when a Survivor is being pounced on by a Hunter. + - Added forward "L4D2_OnStartCarryingVictim" to L4D2 to notify when a Survivor is being grabbed by a Charger. + - Fixed some natives disabling the plugin if their signatures broke. Only their functionality will break. + + - GameData files, include file and plugins updated. + +1.68 (02-Nov-2021) + - Added new forward "L4D_OnGrabWithTongue" to L4D2 to notify when someone is about to be grabbed by a Smoker Tongue. Requested by "Alexmy". + - Added new forward "L4D2_OnJockeyRide" to notify when someone is about to be ridden by a Jockey. Requested by "Alexmy". + - Cleaned and consolidated the code: standardized gamedata names, function names and variable names. + - Compatibility support for SourceMod 1.11. Fixed various warnings. + +1.64 (20-Oct-2021) + - Added 1 new forward to L4D1 and L4D2: + - "L4D_CBreakableProp_Break" - When a physics prop is broken. + + - Added 3 new forwards to L4D2: + - "L4D2_CGasCan_EventKilled" - When a GasCan is destroyed. + - "L4D2_CGasCan_ActionComplete" - When a Survivor has finished pouring gas. + - "L4D2_CInsectSwarm_CanHarm" - When Spitter Acid is checking if a player or entity can be damaged. + + - Added 1 new native to L4D1 and L4D2: + - "L4D_GetWeaponID" - to get the Weapon ID by classname + + - Added and unlocked all the weapon attribute modification natives to L4D1: + - Thanks to "Psyk0tik" for the suggestion and information about offsets. + - "L4D2_IsValidWeapon" + - "L4D2_GetFloatWeaponAttribute" and "L4D2_SetFloatWeaponAttribute" + - "L4D2_GetIntWeaponAttribute" and "L4D2_SetIntWeaponAttribute" + - "L4D2IntWeaponAttributes" enums - ("L4D2IWA_Bullets", "L4D2IWA_Damage", "L4D2IWA_ClipSize") + - "L4D2FloatWeaponAttributes" enums - ("L4D2FWA_MaxPlayerSpeed", "L4D2FWA_SpreadPerShot", "L4D2FWA_MaxSpread", "L4D2FWA_Range", etc) + + - Added new target filters: + "@deads" - Dead Survivors (all, bots) + "@deadsi" - Dead Special Infected (all, bots) + "@deadsp" - Dead Survivors players (no bots) + "@deadsip" - Dead Special Infected players (no bots)- + "@deadsb" - Dead Survivors bots (no players) + "@deadsib" - Dead Special Infected bots (no players)- + "@sp" - Survivors players (no bots) + "@isp" - Special Infected players (no bots) + "@isb" - Incapped Survivor Only Bots + "@isp" - Incapped Survivor Only Players + + - Changed target filter names: + "@incappedsurvivorbot" to "@rincappedsurvivorbot" + "@isb" to "@risb" + "@survivorbot" to "@rsurvivorbot" + "@sb" to "@rsb" + "@infectedbot" to "@rinfectedbot" + "@ib" to "@rib" + "@tankbot" to "@rtankbot" + "@tb" to "@rtb" + + - Added "FINALE_*" enums to the include file for use with the "L4D2_ChangeFinaleStage" and "L4D2_GetCurrentFinaleStage" natives and "L4D2_OnChangeFinaleStage" forward. + - Thanks to "Dragokas" for suggesting. + + - GameData files, include file and plugins updated. + +1.63 (15-Oct-2021) + - Changed all projectile natives to allow passing 0 (world) instead of a client index. Thanks to "BHaType" for reporting. + - Changed forward "L4D_OnGameModeChange" from "Action" type to "Void". Thanks to "Psyk0tik" for reporting. + - Fixed commands "sm_l4dd_detours" and "sm_l4dhooks_detours" not showing all forwards when they have pre and post hooks. + + - Added 11 new forwards to L4D1 and L4D2. Thanks to "Psyk0tik" for the suggestions, signatures and detour functions. + - "L4D_TankClaw_DoSwing_Pre" - When a tank is swinging to punch. + - "L4D_TankClaw_DoSwing_Post" - When a tank is swinging to punch. + - "L4D_TankClaw_GroundPound_Pre" - When an tank punches the ground. + - "L4D_TankClaw_GroundPound_Post" - When an tank punches the ground. + - "L4D_TankClaw_OnPlayerHit_Pre" - When a tank swings and punches a player. + - "L4D_TankClaw_OnPlayerHit_Post" - When a tank swings and punches a player. + - "L4D_TankRock_OnDetonate" - When a tank rock hits something. + - "L4D_TankRock_OnRelease" - When a tank rock is thrown. + - "L4D_PlayerExtinguish" - When a player is about to be extinguished. + - "L4D_PipeBombProjectile_Pre" - When a PipeBomb projectile is being created. + - "L4D_PipeBombProjectile_Post" - After a PipeBomb projectile is created. + + - Added 1 new forward to L4D2. Thanks to "Lux" for the suggestion, signature and detour functions. + - "L4D2_MeleeGetDamageForVictim" - When calculating melee damage to inflict on something. + +1.61 (05-Oct-2021) + - Added natives "L4D_GetTempHealth" and "L4D_SetTempHealth" to handle Survivors temporary health buffer. + - Added natives "L4D_PlayMusic" to play a specified music string to a client. Thanks to "DeathChaos25" and "Shadowysn" for "Dynamic Soundtrack Sets" plugin. + - Added natives "L4D_StopMusic" to stop playing a specified music string to a client. Thanks to "DeathChaos25" and "Shadowysn" for "Dynamic Soundtrack Sets" plugin. + - Moved the animation ACT_* enums from "include/left4dhooks.inc" to "include/left4dhooks_anim.inc". Suggested by "Accelerator". No plugin changes required. + + - Thanks to "Psyk0tik" for requesting the following forwards and natives and their signatures found here: https://github.com/Psykotikism/L4D1-2_Signatures + + - Added natives: + - "L4D2_HasConfigurableDifficultySetting" - Returns if there is a configurable difficulty setting. + - "L4D2_IsGenericCooperativeMode" - Returns if the current game mode is Coop/Realism mode. + - "L4D_IsCoopMode" - Returns if the current game mode is Coop mode. + - "L4D2_IsRealismMode" - Returns if the current game mode is Realism mode. + - "L4D2_IsScavengeMode" - Returns if the current game mode is Scavenge mode. + - "L4D_IsSurvivalMode" - Returns if the current game mode is Survival mode. + - "L4D_IsVersusMode" - Returns if the current game mode is Versus mode. + + - Added forwards: + - "L4D_OnFalling" - Called when a player is falling. + - "L4D_OnFatalFalling" - Called when a player is falling in a fatal zone. + - "L4D2_OnPlayerFling" - Called when a player is flung to the ground. + - "L4D_OnEnterStasis" - Called when a Tank enters stasis mode in Versus mode. + - "L4D_OnLeaveStasis" - Called when a Tank leaves stasis mode in Versus mode. + + - GameData files, include file and plugins updated. + +1.60 (29-Sep-2021) + - Added native "L4D2_GrenadeLauncherPrj" to create an activated Grenade Launcher projectile which detonates on impact. L4D2 only. + - Fixed L4D1 Linux "MolotovProjectile_Create" signature. Thanks to "Ja-Forces" for reporting. + +1.58 (29-Sep-2021) + - Added native "L4D_MolotovPrj" to create an activated Molotov projectile which detonates on impact. + - Added native "L4D2_VomitJarPrj" to create an activated VomitJar projectile which detonates on impact. L4D2 only. + - Added "STATE_*" enums to the include file for use with the "L4D_State_Transition" native. Thanks to "BHaType" for providing. + - Fixed some incorrect information in the include file. Thanks to "jackz" for reporting. + +1.54 (12-Sep-2021) + - Big thanks to "Forgetest" and "HarryPotter" for helping fix and test this release. + + - Added forward "L4D_OnGameModeChange" to notify plugins when the mode has changed to Coop, Versus, Survival and Scavenge (L4D2). + - Added native "L4D_GetGameModeType" to return if the current game mode is Coop, Versus, Survival or Scavenge (L4D2). + + - Update for L4D1: + + - Fixed on Linux forward "L4D_OnSpawnWitch" from not triggering for some Witch spawns. Thanks to "Forgetest" for fixing. + - Fixed on Linux forward "L4D_OnTryOfferingTankBot" from not triggering on the first tank. Thanks to "Forgetest" for fixing. + - Unlocked native "L4D2Direct_GetMobSpawnTimer" for usage in L4D1. Thanks to "HarryPotter" for reporting functionality. + - Unlocked native "L4D2Direct_GetTankCount" for usage in L4D1. Missed this from the last update. + +1.53 (07-Sep-2021) + - Update for L4D1: + + - Added forward "L4D_OnRecalculateVersusScore" from "raziEiL"'s port of "L4D Direct". + - Added natives "L4DDirect_GetSurvivorHealthBonus", "L4DDirect_SetSurvivorHealthBonus" and "L4DDirect_RecomputeTeamScores" from "raziEiL"'s port of "L4D Direct". + - Unblocked native "L4D_GetTeamScore" for usage. + - Fixed forward "L4D_OnFirstSurvivorLeftSafeArea" not blocking correctly. Thanks to "Forgetest" for the solution. + - Various fixes and additions thanks to "HarryPotter" for requesting. + +1.52 (31-Aug-2021) + - Added L4D1 and L4D2 specific "ACT_*" animation activity constants to the include file for usage in animation pre-hooks. See the include file for details. + +1.51 (10-Aug-2021) + - Added natives "L4D_GetCurrentChapter" and "L4D_GetMaxChapters" to get the current and max chapters count. Thanks to "Psyk0tik" for help. + - L4D1: added natives "L4D_GetVersusMaxCompletionScore" and "L4D_SetVersusMaxCompletionScore" to get/set Versus max score. Thanks to "BHaType" for offsets. + - L4D1: Fixed broken "CThrowActivate" signature due to the 1.0.4.0 update. Thank to "matrixmark" for reporting. + +1.50 (22-Jul-2021) + - Fixed "Native was not found" errors in L4D1. Thanks to "xerox8521" for reporting. + - Test plugin: Fixed "L4D_OnMaterializeFromGhostPre" and "L4D_OnMaterializeFromGhost" throwing "String formatted incorrectly" errors. + 1.46 (09-Jul-2021) - L4D2: Added native "L4D2_ExecVScriptCode" to exec VScript code instead of having to create an entity to fire code. - L4D2: Fixed GameData file from the "2.2.2.0" game update. @@ -107,7 +258,7 @@ - New natives added. 1.13 (05-May-2020) - - Made all natives optional from the include file. Thanks to "Crasher_3637" for requesting. + - Made all natives optional from the include file. Thanks to "Psyk0tik" for requesting. 1.10 (14-Mar-2020) - New natives added. @@ -156,6 +307,7 @@ #define REQUIRE_PLUGIN #define MAX_CALLS 1 // How many times to print each forward +#define DEMO_ANIM 0 // Demonstate "Incapped Crawling" animation hooks bool g_bLeft4Dead2; bool g_bLibraryActive; @@ -188,11 +340,10 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max return APLRes_SilentFailure; } - // (+2 for "L4D2_OnEndVersusModeRound_Post" and "L4D2_OnSelectTankAttackPre") if( g_bLeft4Dead2 ) - g_iForwardsMax = 48; + g_iForwardsMax = 74; else - g_iForwardsMax = 37; + g_iForwardsMax = 57; return APLRes_Success; } @@ -220,11 +371,13 @@ public void OnPluginStart() RegAdminCmd("sm_l4df", sm_l4df, ADMFLAG_ROOT); RegAdminCmd("sm_l4dd", sm_l4dd, ADMFLAG_ROOT); + #if DEMO_ANIM HookEvent("player_incapacitated", player_incapacitated); HookEvent("revive_success", revive_success); HookEvent("player_death", player_death); HookEvent("round_end", round_end); HookEvent("player_spawn", player_spawn); + #endif } @@ -285,49 +438,51 @@ stock void PrecacheParticle(const char[] sEffectName) // ==================================================================================================== // CRAWLING TEST - Remove "INCAPPED CRAWLING WITH ANIMATION" plugin to test. // ==================================================================================================== +#if DEMO_ANIM bool g_bCrawling; public void player_spawn(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); if( client && IsClientInGame(client) ) - AnimHookEnable(client, OnAnim, OnAnimPost); + AnimHookEnable(client, OnAnimPre, OnAnimPost); } public void player_incapacitated(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); if( GetClientTeam(client) == 2 ) - AnimHookEnable(client, OnAnim, OnAnimPost); + AnimHookEnable(client, OnAnimPre, OnAnimPost); } public void revive_success(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("subject")); - AnimHookDisable(client, OnAnim, OnAnimPost); + AnimHookDisable(client, OnAnimPre, OnAnimPost); } public void player_death(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("subject")); - AnimHookDisable(client, OnAnim, OnAnimPost); + AnimHookDisable(client, OnAnimPre, OnAnimPost); } public void round_end(Event event, const char[] name, bool dontBroadcast) { for( int i = 1; i <= MaxClients; i++ ) { - AnimHookDisable(i, OnAnim, OnAnimPost); + AnimHookDisable(i, OnAnimPre, OnAnimPost); } } // Uses "Activity" numbers, which means 1 animation number is the same for all Survivors. -Action OnAnim(int client, int &anim) +Action OnAnimPre(int client, int &anim) { // /* if( g_bCrawling ) { - anim = g_bLeft4Dead2 ? 696 : 1197; + // anim = g_bLeft4Dead2 ? 696 : 1197; + anim = g_bLeft4Dead2 ? L4D2_ACT_TERROR_INCAP_CRAWL : L4D1_ACT_TERROR_INCAP_CRAWL; // Include file now has *_ACT_* constants from version 1.52 return Plugin_Changed; } // */ @@ -335,7 +490,7 @@ Action OnAnim(int client, int &anim) return Plugin_Continue; } -// Uses "m_nSequence" animation numbers, which are different for each model. +// Uses "m_nSequence" animation numbers, which are different for each character model. Action OnAnimPost(int client, int &anim) { /* @@ -387,7 +542,10 @@ public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3 g_bCrawling = true; } } + + return Plugin_Continue; } +#endif // ==================================================================================================== @@ -410,11 +568,28 @@ public Action sm_l4dd(int client, int args) + + // ========================= // NATIVES - Mine // ========================= - /* + // WORKS + if( g_bLeft4Dead2 ) + { + PrintToServer("L4D2_HasConfigurableDifficultySetting %d", L4D2_HasConfigurableDifficultySetting()); + PrintToServer("L4D2_IsGenericCooperativeMode %d", L4D2_IsGenericCooperativeMode()); + PrintToServer("L4D2_IsRealismMode %d", L4D2_IsRealismMode()); + PrintToServer("L4D2_IsScavengeMode %d", L4D2_IsScavengeMode()); + } + PrintToServer("L4D_IsCoopMode %d", L4D_IsCoopMode()); + PrintToServer("L4D_IsSurvivalMode %d", L4D_IsSurvivalMode()); + PrintToServer("L4D_IsVersusMode %d", L4D_IsVersusMode()); + + // WORKS + // int iCurrentMode = L4D_GetGameModeType(); + // PrintToServer("GameMode %d", iCurrentMode); + // WORKS // When a Survivor is taking over another Survivor, should change team to 0 otherwise the players old character will disappear. ChangeClientTeam(client, 0); @@ -597,6 +772,25 @@ public Action sm_l4dd(int client, int args) PrintToServer("L4D_Deafen %d", L4D_Deafen(client)); // WORKING + // WORKS + float health = L4D_GetTempHealth(client); + PrintToServer("L4D_GetTempHealth %N %f", client, health); + health += 10.0; + L4D_SetTempHealth(client, health); + + + + // WORKS + // Starts and stops incapacitated music + // L4D_PlayMusic(client, "Event.Down", 0, 0.0, false, false); + // L4D_StopMusic(client, "Event.Down"); + + // Starts and stops the Portal Jukebox song + // L4D_PlayMusic(client, "Jukebox.still_alive", 0, 0.0, false, false); + // L4D_StopMusic(client, "Jukebox.still_alive"); + + + PrintToServer("L4D_OnITExpired %d", L4D_OnITExpired(client)); // WORKING @@ -651,17 +845,36 @@ public Action sm_l4dd(int client, int args) // WORKING // The "Fuse" + "Light" particles must be manually added in your plugin. // I intentionally did not include this in left4dhooks in case you wanted to create an activated PipeBomb projectile without the particles. - int pipe = L4D_PipeBombPrj(client, vPos, vAng); + int projectile = L4D_PipeBombPrj(client, vPos, vAng); // Create particles - CreateParticle(pipe, 0); - CreateParticle(pipe, 1); + CreateParticle(projectile, 0); + CreateParticle(projectile, 1); // Might work, from "PipeBomb Shove" plugin - SetEntPropFloat(pipe, Prop_Data, "m_DmgRadius", 400.0); - SetEntPropFloat(pipe, Prop_Data, "m_flDamage", 25.0); + SetEntPropFloat(projectile, Prop_Data, "m_DmgRadius", 400.0); + SetEntPropFloat(projectile, Prop_Data, "m_flDamage", 25.0); + + PrintToServer("L4D2_PipeBombPrj %d", projectile); + + + + // WORKING + projectile = L4D_MolotovPrj(client, vPos, vAng); + PrintToServer("L4D_MolotovPrj %d", projectile); + + + + // WORKING + if( g_bLeft4Dead2 ) + { + projectile = L4D2_VomitJarPrj(client, vPos, vAng); + PrintToServer("L4D2_VomitJarPrj %d", projectile); - PrintToServer("L4D2_PipeBombPrj %d", pipe); + projectile = L4D2_GrenadeLauncherPrj(client, vPos, vAng); + SetEntProp(projectile, Prop_Data, "m_iHammerID", 2467737); // Avoid conflict with "Flare Gun" plugin. + PrintToServer("L4D2_GrenadeLauncherPrj %d", projectile); + } @@ -671,7 +884,7 @@ public Action sm_l4dd(int client, int args) vDir = view_as({ -1.0, 0.0, 0.0}); // Spin sideways NormalizeVector(vDir, vDir); ScaleVector(vDir, 10000.0); - PrintToServer("L4D_AngularVelocity %d", L4D_AngularVelocity(pipe, vDir)); + PrintToServer("L4D_AngularVelocity %d", L4D_AngularVelocity(projectile, vDir)); @@ -785,7 +998,14 @@ public Action sm_l4dd(int client, int args) PrintToServer("L4D2_IsValidWeapon weapon_rifle: %d", L4D2_IsValidWeapon("weapon_rifle")); PrintToServer("L4D2_IsValidWeapon weapon_autoshotgun: %d", L4D2_IsValidWeapon("weapon_autoshotgun")); PrintToServer("L4D2_IsValidWeapon weapon_smg: %d", L4D2_IsValidWeapon("weapon_smg")); - PrintToServer("L4D2_IsValidWeaponF: %d", L4D2_IsValidWeapon("smg")); // Changed to support this without "weapon_" required + PrintToServer("L4D2_IsValidWeapon smg: %d", L4D2_IsValidWeapon("smg")); // Changed to support this without "weapon_" required + PrintToServer(""); + PrintToServer(""); + + PrintToServer("L4D_GetWeaponID weapon_rifle: %d", L4D_GetWeaponID("weapon_rifle")); + PrintToServer("L4D_GetWeaponID weapon_tank_claw: %d", L4D_GetWeaponID("weapon_tank_claw")); + PrintToServer("L4D_GetWeaponID weapon_smg: %d", L4D_GetWeaponID("weapon_smg")); + PrintToServer("L4D_GetWeaponID smg: %d", L4D_GetWeaponID("smg")); PrintToServer(""); PrintToServer(""); @@ -894,9 +1114,6 @@ public Action sm_l4dd(int client, int args) PrintToServer("L4D_GetTeamScore A Camp: %d", L4D_GetTeamScore(1, true)); //WORKING PrintToServer("L4D_GetTeamScore B Camp: %d", L4D_GetTeamScore(2, true)); //WORKING - PrintToServer("L4D_GetVersusMaxCompletionScore %d", L4D_GetVersusMaxCompletionScore()); //WORKING - L4D_SetVersusMaxCompletionScore(314); //WORKING - PrintToServer("L4D_SetVersusMaxCompletionScore %d", L4D_GetVersusMaxCompletionScore()); //WORKING PrintToServer(""); PrintToServer(""); PrintToServer("L4D_ScavengeBeginRoundSetupTime %f", L4D_ScavengeBeginRoundSetupTime()); @@ -906,6 +1123,12 @@ public Action sm_l4dd(int client, int args) PrintToServer(""); } + PrintToServer("L4D_GetVersusMaxCompletionScore %d", L4D_GetVersusMaxCompletionScore()); //WORKING + L4D_SetVersusMaxCompletionScore(314); //WORKING + + PrintToServer("L4D_GetMaxChapters %d", L4D_GetMaxChapters()); //WORKING + PrintToServer("L4D_GetCurrentChapter %d", L4D_GetCurrentChapter()); //WORKING + PrintToServer("L4D_NotifyNetworkStateChanged %d", L4D_NotifyNetworkStateChanged()); //SEEMS WORKING, UNKNOWN PrintToServer(""); @@ -1071,6 +1294,14 @@ public Action sm_l4dd(int client, int args) + if( !g_bLeft4Dead2 ) + { + // UNTESTED: + L4DDirect_GetSurvivorHealthBonus(client); + L4DDirect_SetSurvivorHealthBonus(client, 2); + L4DDirect_RecomputeTeamScores(); + } + PrintToServer(""); @@ -1247,8 +1478,8 @@ public Action L4D_OnSpawnSpecial(int &zombieClass, const float vector[3], const static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnSpawnSpecial\" %d. (%f %f %f). (%f %f %f)", zombieClass, vector[0], vector[1], vector[2], qangle[0], qangle[1], qangle[2]); } @@ -1257,6 +1488,8 @@ public Action L4D_OnSpawnSpecial(int &zombieClass, const float vector[3], const // return Plugin_Changed; // WORKS // return Plugin_Handled; // WORKS + + return Plugin_Continue; } public Action L4D_OnSpawnTank(const float vector[3], const float qangle[3]) @@ -1264,12 +1497,15 @@ public Action L4D_OnSpawnTank(const float vector[3], const float qangle[3]) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnSpawnTank\" (%f %f %f). (%f %f %f)", vector[0], vector[1], vector[2], qangle[0], qangle[1], qangle[2]); } + // return Plugin_Handled; // WORKS + + return Plugin_Continue; } public Action L4D_OnSpawnWitch(const float vector[3], const float qangle[3]) @@ -1277,12 +1513,15 @@ public Action L4D_OnSpawnWitch(const float vector[3], const float qangle[3]) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnSpawnWitch\" (%f %f %f). (%f %f %f)", vector[0], vector[1], vector[2], qangle[0], qangle[1], qangle[2]); } + // return Plugin_Handled; // WORKS + + return Plugin_Continue; } public Action L4D2_OnSpawnWitchBride(const float vector[3], const float qangle[3]) @@ -1290,12 +1529,15 @@ public Action L4D2_OnSpawnWitchBride(const float vector[3], const float qangle[3 static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnSpawnWitchBride\" (%f %f %f). (%f %f %f)", vector[0], vector[1], vector[2], qangle[0], qangle[1], qangle[2]); } + // return Plugin_Handled; // WORKS + + return Plugin_Continue; } public Action L4D_OnMobRushStart() @@ -1303,12 +1545,14 @@ public Action L4D_OnMobRushStart() static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnMobRushStart\""); } // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnSpawnITMob(int &amount) @@ -1316,8 +1560,8 @@ public Action L4D_OnSpawnITMob(int &amount) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnSpawnITMob\" %d", amount); } @@ -1328,6 +1572,8 @@ public Action L4D_OnSpawnITMob(int &amount) // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnSpawnMob(int &amount) @@ -1335,8 +1581,8 @@ public Action L4D_OnSpawnMob(int &amount) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnSpawnMob\" %d", amount); } @@ -1347,6 +1593,8 @@ public Action L4D_OnSpawnMob(int &amount) // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnEnterGhostStatePre(int client) @@ -1354,14 +1602,16 @@ public Action L4D_OnEnterGhostStatePre(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnEnterGhostStatePre\" %d", client); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public void L4D_OnEnterGhostState(int client) @@ -1369,8 +1619,8 @@ public void L4D_OnEnterGhostState(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnEnterGhostState\" %d", client); } @@ -1381,8 +1631,8 @@ public Action L4D_OnIsTeamFull(int team, bool &full) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_IsTeamFull\" %d %d", team, full); } @@ -1398,7 +1648,7 @@ public Action L4D_OnIsTeamFull(int team, bool &full) // full = true; // return Plugin_Changed; - // return Plugin_Continue; + return Plugin_Continue; } public Action L4D_OnClearTeamScores(bool newCampaign) @@ -1406,14 +1656,16 @@ public Action L4D_OnClearTeamScores(bool newCampaign) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnClearTeamScores\" %d", newCampaign); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnSetCampaignScores(int &scoreA, int &scoreB) @@ -1421,8 +1673,8 @@ public Action L4D_OnSetCampaignScores(int &scoreA, int &scoreB) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnSetCampaignScores\" %d. %d", scoreA, scoreB); } @@ -1434,6 +1686,8 @@ public Action L4D_OnSetCampaignScores(int &scoreA, int &scoreB) // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnFirstSurvivorLeftSafeArea(int client) @@ -1441,14 +1695,16 @@ public Action L4D_OnFirstSurvivorLeftSafeArea(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnFirstSurvivorLeftSafeArea\" %d", client); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnGetCrouchTopSpeed(int target, float &retVal) @@ -1456,8 +1712,8 @@ public Action L4D_OnGetCrouchTopSpeed(int target, float &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetCrouchTopSpeed\" %d. %f", target, retVal); } @@ -1465,6 +1721,8 @@ public Action L4D_OnGetCrouchTopSpeed(int target, float &retVal) // WORKS // retVal = 500.0; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnGetRunTopSpeed(int target, float &retVal) @@ -1472,8 +1730,8 @@ public Action L4D_OnGetRunTopSpeed(int target, float &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetRunTopSpeed\" %d. %f", target, retVal); } @@ -1481,6 +1739,8 @@ public Action L4D_OnGetRunTopSpeed(int target, float &retVal) // WORKS // retVal = 500.0; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnGetWalkTopSpeed(int target, float &retVal) @@ -1488,8 +1748,8 @@ public Action L4D_OnGetWalkTopSpeed(int target, float &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetWalkTopSpeed\" %d. %f", target, retVal); } @@ -1497,6 +1757,8 @@ public Action L4D_OnGetWalkTopSpeed(int target, float &retVal) // WORKS // retVal = 500.0; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnGetMissionVSBossSpawning(float &spawn_pos_min, float &spawn_pos_max, float &tank_chance, float &witch_chance) @@ -1504,8 +1766,8 @@ public Action L4D_OnGetMissionVSBossSpawning(float &spawn_pos_min, float &spawn_ static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetMissionVSBossSpawning\" %f. %f. %f. %f", spawn_pos_min, spawn_pos_max, tank_chance, witch_chance); } @@ -1516,6 +1778,8 @@ public Action L4D_OnGetMissionVSBossSpawning(float &spawn_pos_min, float &spawn_ // tank_chance = 1.0; // witch_chance = 1.0; // return Plugin_Changed; + + return Plugin_Continue; } public void L4D_OnReplaceTank(int tank, int newtank) @@ -1523,26 +1787,155 @@ public void L4D_OnReplaceTank(int tank, int newtank) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnReplaceTank\" %d %d", tank, newtank); } } +public void L4D_TankClaw_DoSwing_Pre(int tank, int claw) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankClaw_DoSwing_Pre\" %d (Claw = %d)", tank, claw); + } +} + +public void L4D_TankClaw_DoSwing_Post(int tank, int claw) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankClaw_DoSwing_Post\" %d (Claw = %d)", tank, claw); + } +} + +public void L4D_TankClaw_GroundPound_Pre(int tank, int claw) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankClaw_GroundPound_Pre\" %d (Claw = %d)", tank, claw); + } +} + +public void L4D_TankClaw_GroundPound_Post(int tank, int claw) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankClaw_GroundPound_Post\" %d (Claw = %d)", tank, claw); + } +} + +public Action L4D_TankClaw_OnPlayerHit_Pre(int tank, int claw, int player) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankClaw_OnPlayerHit_Pre\" %d (Claw = %d) (Target = %d)", tank, claw, player); + } + + // WORKS - Blocks target player being flung + // return Plugin_Handled; + + return Plugin_Continue; +} + +public void L4D_TankClaw_OnPlayerHit_Post(int tank, int claw, int player) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankClaw_OnPlayerHit_Post\" %d (Claw = %d) (Target = %d)", tank, claw, player); + } +} + +public void L4D_TankRock_OnDetonate(int tank, int rock) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankRock_OnDetonate\" %d (Rock = %d)", tank, rock); + } +} + +public Action L4D_TankRock_OnRelease(int tank, int rock, float vecPos[3], float vecAng[3], float vecVel[3], float vecRot[3]) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_TankRock_OnRelease\" %d (Rock = %d) pos(%0.1f %0.1f %0.1f) ang(%0.1f %0.1f %0.1f) vel(%0.1f %0.1f %0.1f) rot(%0.1f %0.1f %0.1f)", tank, rock, vecPos[0], vecPos[1], vecPos[2], vecAng[0], vecAng[1], vecAng[2], vecVel[0], vecVel[1], vecVel[2], vecRot[0], vecRot[1], vecRot[2]); + } + + // WORKS + + // Change position of rock + // vecPos[0] += 50.0; + // vecPos[1] += 50.0; + // vecPos[2] += 50.0; + + // Change angle of rock + // vecAng[0] += 90.0; + // vecAng[1] += 90.0; + // vecAng[2] += 90.0; + + // Increase velocity of rock + // vecVel[0] *= 5.0; + // vecVel[1] *= 5.0; + // vecVel[2] *= 5.0; + + // Increase rotation of rock + // vecRot[0] *= 5.0; + // vecRot[1] *= 5.0; + // vecRot[2] *= 5.0; + + // return Plugin_Changed; + + return Plugin_Continue; +} + public Action L4D_OnTryOfferingTankBot(int tank_index, bool &enterStasis) { static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnTryOfferingTankBot\" %d. %d", tank_index, enterStasis); } // WORKING // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnCThrowActivate(int ability) @@ -1550,14 +1943,16 @@ public Action L4D_OnCThrowActivate(int ability) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnCThrowActivate\" %d", ability); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnSelectTankAttackPre(int client, int &sequence) @@ -1565,8 +1960,8 @@ public Action L4D2_OnSelectTankAttackPre(int client, int &sequence) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnSelectTankAttack\" %d. %d", client, sequence); } @@ -1574,6 +1969,8 @@ public Action L4D2_OnSelectTankAttackPre(int client, int &sequence) // WORKS // sequence = 761; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnSelectTankAttack(int client, int &sequence) @@ -1581,8 +1978,8 @@ public Action L4D2_OnSelectTankAttack(int client, int &sequence) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnSelectTankAttack\" %d. %d", client, sequence); } @@ -1590,6 +1987,8 @@ public Action L4D2_OnSelectTankAttack(int client, int &sequence) // WORKS // sequence = 48; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnSendInRescueVehicle() @@ -1597,14 +1996,16 @@ public Action L4D2_OnSendInRescueVehicle() static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnSendInRescueVehicle\""); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnEndVersusModeRound(bool countSurvivors) @@ -1612,14 +2013,16 @@ public Action L4D2_OnEndVersusModeRound(bool countSurvivors) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnEndVersusModeRound\" %d", countSurvivors); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public void L4D2_OnEndVersusModeRound_Post() @@ -1627,26 +2030,45 @@ public void L4D2_OnEndVersusModeRound_Post() static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnEndVersusModeRound_Post\""); } } +public Action L4D_OnRecalculateVersusScore(int client) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnRecalculateVersusScore\""); + } + + // UNTESTED + // return Plugin_Handled; + + return Plugin_Continue; +} + public Action L4D_OnLedgeGrabbed(int client) { static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnLedgeGrabbed\" %d", client); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public void L4D2_OnRevived(int client) @@ -1654,8 +2076,8 @@ public void L4D2_OnRevived(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnRevived\" %d", client); } @@ -1666,14 +2088,16 @@ public Action L4D2_OnStagger(int target, int source) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnStagger\" %d %d", target, source); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnShovedBySurvivor(int client, int victim, const float vector[3]) @@ -1681,14 +2105,16 @@ public Action L4D_OnShovedBySurvivor(int client, int victim, const float vector[ static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnShovedBySurvivor\" %d %d. (%f %f %f)", client, victim, vector[0], vector[1], vector[2]); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnEntityShoved(int client, int entity, int weapon, float vector[3], bool bIsHighPounce) @@ -1696,14 +2122,16 @@ public Action L4D2_OnEntityShoved(int client, int entity, int weapon, float vect static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnEntityShoved\" %d %d %d (%f %f %f) IsHighPounce=%d", client, entity, weapon, vector[0], vector[1], vector[2], bIsHighPounce); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnPounceOrLeapStumble(int victim, int attacker) @@ -1711,14 +2139,16 @@ public Action L4D2_OnPounceOrLeapStumble(int victim, int attacker) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnPounceOrLeapStumble\" %d %d", victim, attacker); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnSpitSpread(int spitter, int projectile, float &x, float &y, float &z) @@ -1726,8 +2156,8 @@ public Action L4D2_OnSpitSpread(int spitter, int projectile, float &x, float &y, static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnSpitSpread\" %d %d (%f %f %f)", spitter, projectile, x, y, z); } @@ -1740,6 +2170,8 @@ public Action L4D2_OnSpitSpread(int spitter, int projectile, float &x, float &y, // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnUseHealingItems(int client) @@ -1747,14 +2179,16 @@ public Action L4D2_OnUseHealingItems(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnUseHealingItems\" %d", client); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnFindScavengeItem(int client, int &item) @@ -1762,8 +2196,8 @@ public Action L4D2_OnFindScavengeItem(int client, int &item) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnFindScavengeItem\" %d %d", client, item); } @@ -1771,12 +2205,96 @@ public Action L4D2_OnFindScavengeItem(int client, int &item) // WORKS // if( item == -1 ) // { - // item = 440; + // item = 440; // 440 being an entity index (must set a valid "weapon_*" entity) // return Plugin_Changed; // } // WORKS // return Plugin_Handled; + + return Plugin_Continue; +} + +public Action L4D_OnPouncedOnSurvivor(int victim, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnPouncedOnSurvivor\" %d (%N) pouncing %d (%N)", attacker, attacker, victim, victim); + } + + // WORKS + // return Plugin_Handled; + + return Plugin_Continue; +} + +public Action L4D_OnGrabWithTongue(int victim, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnGrabWithTongue\" %d (%N) grabbing %d (%N)", attacker, attacker, victim, victim); + } + + /* WORKS + // Remove and re-create the custom ability. + // This allows the player to keep moving and not frozen in place for a few seconds. + // Tried setting "m_flMaxspeed", movement type and remove FL_FROZEN "m_fFlags" but only this method worked. + int ability = GetEntPropEnt(attacker, Prop_Send, "m_customAbility"); + RemoveEntity(ability); + + // Create ability again + L4D_SetClass(attacker, 1); + + // Set next attack time. Otherwise they can shoot again instantly. Remove if that's what you want. Doesn't show cooldown circle for next attack time. + ability = GetEntPropEnt(attacker, Prop_Send, "m_customAbility"); + if( ability > 0 ) SetEntPropFloat(ability, Prop_Send, "m_nextActivationTimer", GetGameTime() + 2.0, 1); + + return Plugin_Handled; + // */ + + return Plugin_Continue; +} + +public Action L4D2_OnJockeyRide(int victim, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_OnJockeyRide\" %d (%N) grabbing %d (%N)", attacker, attacker, victim, victim); + } + + // WORKS + // return Plugin_Handled; + + return Plugin_Continue; +} + +public Action L4D2_OnStartCarryingVictim(int victim, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_OnStartCarryingVictim\" %d (%N) grabbing %d (%N)", attacker, attacker, victim, victim); + } + + // WORKS + // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnVomitedUpon(int victim, int &attacker, bool &boomerExplosion) @@ -1784,8 +2302,8 @@ public Action L4D_OnVomitedUpon(int victim, int &attacker, bool &boomerExplosion static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnVomitedUpon\" %d > %d (%d)", victim, attacker, boomerExplosion); } @@ -1794,6 +2312,8 @@ public Action L4D_OnVomitedUpon(int victim, int &attacker, bool &boomerExplosion // return Plugin_Changed; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnHitByVomitJar(int victim, int &attacker) @@ -1801,8 +2321,8 @@ public Action L4D2_OnHitByVomitJar(int victim, int &attacker) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnHitByVomitJar\" %d > %d)", victim, attacker); } @@ -1812,6 +2332,8 @@ public Action L4D2_OnHitByVomitJar(int victim, int &attacker) // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnMaterializeFromGhostPre(int client) @@ -1819,14 +2341,16 @@ public Action L4D_OnMaterializeFromGhostPre(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; - ForwardCalled("\"L4D_OnMaterializeFromGhostPre\" %d > %d)", client); + ForwardCalled("\"L4D_OnMaterializeFromGhostPre\" %d (%N)", client, client); } // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnMaterializeFromGhost(int client) @@ -1834,11 +2358,163 @@ public Action L4D_OnMaterializeFromGhost(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnMaterializeFromGhost\" %d (%N)", client, client); + } + + return Plugin_Continue; +} + +public Action L4D_PipeBombProjectile_Pre(int client, float vecPos[3], float vecAng[3], float vecVel[3], float vecRot[3]) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_PipeBombProjectile_Pre\" %d", client); + } + + + + // WORKS + + // Change position of grenade + // vecPos[0] += 30.0; + // vecPos[1] += 30.0; + // vecPos[2] += 30.0; + + // Change angle of grenade + // vecAng[0] += 90.0; + // vecAng[1] += 90.0; + // vecAng[2] += 90.0; + + // Increase velocity of grenade + // vecVel[0] *= 2.0; + // vecVel[1] *= 2.0; + // vecVel[2] *= 2.0; + + // Increase rotation of grenade + // vecRot[0] *= 5.0; + // vecRot[1] *= 5.0; + // vecRot[2] *= 5.0; + + // return Plugin_Changed; + + + + // WORKS - Blocks grenade creation + // return Plugin_Handled; + + return Plugin_Continue; +} + +public void L4D_PipeBombProjectile_Post(int client, int projectile, float vecPos[3], float vecAng[3], float vecVel[3], float vecRot[3]) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_PipeBombProjectile_Post\" %d (Grenade = %d) pos(%0.1f %0.1f %0.1f) ang(%0.1f %0.1f %0.1f) vel(%0.1f %0.1f %0.1f) rot(%0.1f %0.1f %0.1f)", client, projectile, vecPos[0], vecPos[1], vecPos[2], vecAng[0], vecAng[1], vecAng[2], vecVel[0], vecVel[1], vecVel[2], vecRot[0], vecRot[1], vecRot[2]); + } +} + +public Action L4D_PlayerExtinguish(int client) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_PlayerExtinguish\" %d (%N)", client, client); + } + + // WORKS - Block extinguish + // return Plugin_Handled; + + return Plugin_Continue; +} + +public void L4D_CBreakableProp_Break(int prop, int entity) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_CBreakableProp_Break\" %d (%d)", prop, entity); + } +} + +public void L4D2_CGasCan_EventKilled(int gascan, int inflictor, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_CGasCan_EventKilled\" %d (Inf=%d) (Att=%d)", gascan, inflictor, attacker); + } +} + +public Action L4D2_CGasCan_ActionComplete(int client, int gascan, int nozzle) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_CGasCan_ActionComplete\" %d (%N) - GasCan: %d > Nozzle: %d", client, client, gascan, nozzle); + } + + // WORKS + + /* + // Probably want to fire the event and output for other plugins, whilst blocking the call itself to prevent adding to the Scavenge Score pour gas count. + // See the "Scavenge Score Fix - Gascan Pouring" plugin for more details. + + // Fire event + Event hEvent = CreateEvent("gascan_pour_completed", true); + if( hEvent != null ) + { + hEvent.SetInt("userid", GetClientUserId(client)); + hEvent.Fire(); + } + + // Fire output + FireEntityOutput(entity, "OnUseFinished", client); + + // Block call + return Plugin_Handled; + // */ + + return Plugin_Continue; +} + +public Action L4D2_CInsectSwarm_CanHarm(int acid, int spitter, int entity) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; - ForwardCalled("\"L4D_OnMaterializeFromGhost\" %d > %d)", client); + ForwardCalled("\"L4D2_CInsectSwarm_CanHarm\" %d %N > %d > %d", spitter, spitter, acid, entity); } + + // WORKS + // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnChooseVictim(int specialInfected, int &curTarget) @@ -1846,8 +2522,8 @@ public Action L4D2_OnChooseVictim(int specialInfected, int &curTarget) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnChooseVictim\" %d > %d", specialInfected, curTarget); } @@ -1858,6 +2534,8 @@ public Action L4D2_OnChooseVictim(int specialInfected, int &curTarget) // ATTACK THEMSELVES (no target) - the special will stand still. // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnGetScriptValueInt(const char[] key, int &retVal) @@ -1865,8 +2543,8 @@ public Action L4D_OnGetScriptValueInt(const char[] key, int &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetScriptValueInt\" %s. %d", key, retVal); } @@ -1877,7 +2555,8 @@ public Action L4D_OnGetScriptValueInt(const char[] key, int &retVal) // retVal = 1; // return Plugin_Handled; // } - // return Plugin_Continue; + + return Plugin_Continue; } public Action L4D_OnGetScriptValueFloat(const char[] key, float &retVal) @@ -1885,8 +2564,8 @@ public Action L4D_OnGetScriptValueFloat(const char[] key, float &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetScriptValueFloat\" %s. %f", key, retVal); } @@ -1900,7 +2579,8 @@ public Action L4D_OnGetScriptValueFloat(const char[] key, float &retVal) // retVal = 2.0; // return Plugin_Handled; // } - // return Plugin_Continue; + + return Plugin_Continue; } public Action L4D_OnGetScriptValueString(const char[] key, const char[] defaultVal, char retVal[128]) @@ -1908,8 +2588,8 @@ public Action L4D_OnGetScriptValueString(const char[] key, const char[] defaultV static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; // ForwardCalled("\"L4D_OnGetScriptValueString\" [%s]. [%s]. [%s].", key, defaultVal, retVal); // Because printing random chars can break console printing text or possibly cause a crash? ForwardCalled("\"L4D_OnGetScriptValueString\""); @@ -1922,6 +2602,8 @@ public Action L4D_OnGetScriptValueString(const char[] key, const char[] defaultV // retVal = ""; // return Plugin_Handled; // } + + return Plugin_Continue; } public Action L4D_OnHasConfigurableDifficulty(int &retVal) @@ -1929,8 +2611,8 @@ public Action L4D_OnHasConfigurableDifficulty(int &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnHasConfigurableDifficulty\" %d", retVal); } @@ -1938,6 +2620,8 @@ public Action L4D_OnHasConfigurableDifficulty(int &retVal) // WORKS // retVal = 0; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnGetSurvivorSet(int &retVal) @@ -1945,8 +2629,8 @@ public Action L4D_OnGetSurvivorSet(int &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetSurvivorSet\" %d", retVal); } @@ -1954,6 +2638,8 @@ public Action L4D_OnGetSurvivorSet(int &retVal) // WORKS // retVal = 1; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnFastGetSurvivorSet(int &retVal) @@ -1961,8 +2647,8 @@ public Action L4D_OnFastGetSurvivorSet(int &retVal) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnFastGetSurvivorSet\" %d", retVal); } @@ -1970,6 +2656,8 @@ public Action L4D_OnFastGetSurvivorSet(int &retVal) // WORKS // retVal = 1; // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D_OnStartMeleeSwing(int client, bool boolean) @@ -1977,14 +2665,37 @@ public Action L4D_OnStartMeleeSwing(int client, bool boolean) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnStartMeleeSwing\" %d. %d", client, boolean); } // WORKS - PREDICTION ISSUES - Hear and partially see swing in first person // return Plugin_Handled; + + return Plugin_Continue; +} + +public Action L4D2_MeleeGetDamageForVictim(int client, int weapon, int victim, float &damage) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_MeleeGetDamageForVictim\" %d %d > %d (%f)", client, weapon, victim, damage); + } + + // WORKS + // damage = 10.0; + // return Plugin_Changed; + + // WORKS + // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnChangeFinaleStage(int &finaleType, const char[] arg) @@ -1992,8 +2703,8 @@ public Action L4D2_OnChangeFinaleStage(int &finaleType, const char[] arg) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnChangeFinaleStage\" %d. %s", finaleType, arg); } @@ -2004,26 +2715,110 @@ public Action L4D2_OnChangeFinaleStage(int &finaleType, const char[] arg) // WORKS // return Plugin_Handled; + + return Plugin_Continue; } public Action L4D2_OnClientDisableAddons(const char[] SteamID) { - PrintToServer("#### FWD L4D2_OnClientDisableAddons %s", SteamID); - static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnClientDisableAddons\" %s", SteamID); } // Requires l4d2_addons_eclipse 1 to be used. // return Plugin_Continue; // Block addons. - // return Plugin_Handled; // Allow addons. + return Plugin_Handled; // Allow addons. +} + +public void L4D_OnGameModeChange(int gamemode) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnGameModeChange\" %d", gamemode); + } +} + +public Action L4D2_OnPlayerFling(int client, int attacker, float vecDir[3]) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_OnPlayerFling\" %d (%N) flung %d (%N). vecDir: (%0.1f %0.1f %0.1f)", attacker, attacker, client, client, vecDir[0], vecDir[1], vecDir[2]); + } + + // WORKS - Block being flung + // return Plugin_Handled; + + return Plugin_Continue; } +public Action L4D_OnFatalFalling(int client, int camera) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnFatalFalling\" %d %N (cam: %d)", client, client, camera); + } + + // WORKS - Block block death fall camera + // return Plugin_Handled; + + return Plugin_Continue; +} + +public void L4D_OnFalling(int client) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnFalling\" %d %N", client, client); + } +} + +public void L4D_OnEnterStasis(int tank) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnEnterStasis\" %d %N", tank, tank); + } +} + +public void L4D_OnLeaveStasis(int tank) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D_OnLeaveStasis\" %d %N", tank, tank); + } +} + + + /* // Can trigger with: "z_spawn_old hunter auto" in console. // BROKEN, SPAWNS SPECIALS AT 0,0,0 WHEN MODIFYING VALUES @@ -2032,8 +2827,8 @@ public Action L4D_OnGetRandomPZSpawnPosition(int &client, int &zombieClass, int static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnGetRandomPZSpawnPosition\" Client(%d). Class(%d). Attempts(%d). (%f %f %f)", client, zombieClass, attempts, vecPos[0], vecPos[1], vecPos[2]); } @@ -2050,8 +2845,8 @@ public Action L4D_OnInfectedShoved(int infected, int entity) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D_OnInfectedShoved\" %d. %d", infected, entity); } @@ -2062,8 +2857,8 @@ public void L4D2_OnWaterMove(int client) static int called; if( called < MAX_CALLS ) { + if( called == 0 ) g_iForwards++; called++; - g_iForwards++; ForwardCalled("\"L4D2_OnWaterMove\" %d", client); } @@ -2074,6 +2869,9 @@ public void L4D2_OnWaterMove(int client) +// ==================================================================================================== +// HELPERS +// ==================================================================================================== void ForwardCalled(const char[] format, any ...) { if( g_bTestForwards == false ) return; diff --git a/addons/sourcemod/scripting/lerpmonitor.sp b/addons/sourcemod/scripting/lerpmonitor.sp index 02e73da0b..2f27d7830 100644 --- a/addons/sourcemod/scripting/lerpmonitor.sp +++ b/addons/sourcemod/scripting/lerpmonitor.sp @@ -132,6 +132,8 @@ public Action Process(Handle hTimer, int userid) if (client > 0 && GetClientTeam(client) > L4D_TEAM_SPECTATE) { ProcessPlayerLerp(client); } + + return Plugin_Stop; } public void OnMapStart() @@ -206,8 +208,10 @@ public Action Timer_RoundEndDelay(Handle hTimer) isFirstHalf = false; isTransfer = true; isMatchLife = false; - + ArrLerpsCountChanges.Clear(); + + return Plugin_Stop; } public Action Lerps_Cmd(int client, int args) diff --git a/addons/sourcemod/scripting/noteam_nudging.sp b/addons/sourcemod/scripting/noteam_nudging.sp index 6f89e57bf..aaded92a3 100644 --- a/addons/sourcemod/scripting/noteam_nudging.sp +++ b/addons/sourcemod/scripting/noteam_nudging.sp @@ -18,7 +18,6 @@ public Plugin myinfo = url = "-" }; - public void OnPluginStart() { CreateConVar("noteam_nudging_version", PLUGIN_VERSION, "", FCVAR_NOTIFY|FCVAR_DONTRECORD); @@ -40,4 +39,6 @@ public Action UpdateAvoid(Handle timer) SetEntPropFloat(i, Prop_Send, "m_noAvoidanceTimer", flTime + NOAVOID_ADDTIME, 1); } + + return Plugin_Continue; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/pause.sp b/addons/sourcemod/scripting/pause.sp index 7214906b2..df111506a 100644 --- a/addons/sourcemod/scripting/pause.sp +++ b/addons/sourcemod/scripting/pause.sp @@ -25,7 +25,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #undef REQUIRE_PLUGIN #include @@ -75,13 +75,13 @@ int initiatorId; bool adminPause, - teamReady[view_as(L4D2Team_Size)], + teamReady[L4D2Team_Size], initiatorReady; char initiatorName[MAX_NAME_LENGTH]; float pauseTime; -L4D2_Team +int pauseTeam; // Pause Panel @@ -100,7 +100,9 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("IsInPause", Native_IsInPause); pauseForward = CreateGlobalForward("OnPause", ET_Ignore); unpauseForward = CreateGlobalForward("OnUnpause", ET_Ignore); + RegPluginLibrary("pause"); + return APLRes_Success; } public void OnPluginStart() @@ -237,7 +239,7 @@ public Action Pause_Cmd(int client, int args) return Plugin_Continue; initiatorId = GetClientUserId(client); - pauseTeam = view_as(GetClientTeam(client)); + pauseTeam = GetClientTeam(client); GetClientName(client, initiatorName, sizeof(initiatorName)); CPrintToChatAll("{default}[{green}!{default}] {olive}%N {blue}Paused{default}.", client); @@ -282,13 +284,15 @@ public Action ForcePause_Cmd(int client, int args) CPrintToChatAll("{default}[{green}!{default}] A {green}force pause {default}is issued by {blue}Admin {default}({olive}%N{default})", client); Pause(); } + + return Plugin_Handled; } public Action Unpause_Cmd(int client, int args) { if (isPaused && IsPlayer(client)) { - L4D2_Team clientTeam = view_as(GetClientTeam(client)); + int clientTeam = GetClientTeam(client); int initiator = GetClientOfUserId(initiatorId); if (!teamReady[clientTeam]) { @@ -328,6 +332,7 @@ public Action Unpause_Cmd(int client, int args) } } } + return Plugin_Handled; } @@ -336,7 +341,7 @@ public Action Unready_Cmd(int client, int args) if (isPaused && IsPlayer(client)) { int initiator = GetClientOfUserId(initiatorId); - L4D2_Team clientTeam = view_as(GetClientTeam(client)); + int clientTeam = GetClientTeam(client); if (teamReady[clientTeam]) { switch (clientTeam) @@ -369,6 +374,7 @@ public Action Unready_Cmd(int client, int args) CancelFullReady(client); } } + return Plugin_Handled; } @@ -380,12 +386,16 @@ public Action ForceUnpause_Cmd(int client, int args) CPrintToChatAll("{default}[{green}!{default}] A {green}force unpause {default}is issued by {blue}Admin {default}({olive}%N{default})", client); InitiateLiveCountdown(); } + + return Plugin_Handled; } public Action ToggleReady_Cmd(int client, int args) { - L4D2_Team clientTeam = view_as(GetClientTeam(client)); + int clientTeam = GetClientTeam(client); teamReady[clientTeam] ? Unready_Cmd(client, 0) : Unpause_Cmd(client, 0); + + return Plugin_Handled; } // ====================================== @@ -440,7 +450,7 @@ public Action DeferredPause_Timer(Handle timer) void Pause() { - for (int team; team < view_as(L4D2Team_Size); team++) + for (int team; team < L4D2Team_Size; team++) { teamReady[team] = false; } @@ -465,7 +475,7 @@ void Pause() { if (IsClientInGame(client) && !IsFakeClient(client)) { - L4D2_Team team = view_as(GetClientTeam(client)); + int team = GetClientTeam(client); if (team == L4D2Team_Infected && IsInfectedGhost(client)) { @@ -527,7 +537,7 @@ void Unpause(bool real = true) unpauseProcessed = true; } - if (view_as(GetClientTeam(client)) == L4D2Team_Spectator) + if (GetClientTeam(client) == L4D2Team_Spectator) { sv_noclipduringpause.ReplicateToClient(client, "0"); } @@ -550,6 +560,8 @@ public Action Show_Cmd(int client, int args) hiddenPanel[client] = false; CPrintToChat(client, "[{olive}Pause{default}] Panel is now {blue}on{default}."); } + + return Plugin_Handled; } public Action Hide_Cmd(int client, int args) @@ -559,6 +571,8 @@ public Action Hide_Cmd(int client, int args) hiddenPanel[client] = true; CPrintToChat(client, "[{olive}Pause{default}] Panel is now {red}off{default}."); } + + return Plugin_Handled; } public Action MenuRefresh_Timer(Handle timer) @@ -571,7 +585,7 @@ public Action MenuRefresh_Timer(Handle timer) return Plugin_Stop; } -public int DummyHandler(Menu menu, MenuAction action, int param1, int param2) { } +public int DummyHandler(Menu menu, MenuAction action, int param1, int param2) { return 1; } void UpdatePanel() { @@ -706,6 +720,8 @@ public Action Spectate_Cmd(int client, int args) } SpecTimer[client] = CreateTimer(3.0, SecureSpec, client); + + return Plugin_Handled; } public Action SecureSpec(Handle timer, any client) @@ -740,7 +756,7 @@ void ToggleCommandListeners(bool enable) public Action Callvote_Callback(int client, char[] command, int argc) { - if (view_as(GetClientTeam(client)) == L4D2Team_Spectator) + if (GetClientTeam(client) == L4D2Team_Spectator) { CPrintToChat(client, "{blue}[{green}!{blue}] {default}You're unable to call votes as a spectator."); return Plugin_Handled; @@ -838,7 +854,7 @@ public Action TeamSay_Callback(int client, char[] command, int argc) { return Plugin_Handled; } - PrintToTeam(client, view_as(GetClientTeam(client)), buffer); + PrintToTeam(client, GetClientTeam(client), buffer); return Plugin_Handled; } return Plugin_Continue; @@ -866,15 +882,15 @@ stock bool IsPlayer(int client) { if (!client) return false; - L4D2_Team team = view_as(GetClientTeam(client)); + int team = GetClientTeam(client); return !SpecTimer[client] && (team == L4D2Team_Survivor || team == L4D2Team_Infected); } -stock void PrintToTeam(int author, L4D2_Team team, const char[] buffer) +stock void PrintToTeam(int author, int team, const char[] buffer) { for (int client = 1; client <= MaxClients; client++) { - if (IsClientInGame(client) && view_as(GetClientTeam(client)) == team) + if (IsClientInGame(client) && GetClientTeam(client) == team) { CPrintToChatEx(client, author, "(%s) {teamcolor}%N{default} : %s", L4D2_TeamName[GetClientTeam(author)], author, buffer); } @@ -896,13 +912,13 @@ stock int GetSeriousClientCount() return clients; } -stock int GetTeamHumanCount(L4D2_Team team) +stock int GetTeamHumanCount(int team) { int humans = 0; for (int client = 1; client <= MaxClients; client++) { - if (IsClientInGame(client) && !IsFakeClient(client) && view_as(GetClientTeam(client)) == team) + if (IsClientInGame(client) && !IsFakeClient(client) && GetClientTeam(client) == team) { humans++; } @@ -915,7 +931,7 @@ stock bool IsSurvivorReviving() { for (int client = 1; client <= MaxClients; client++) { - if (IsClientInGame(client) && view_as(GetClientTeam(client)) == L4D2Team_Survivor && IsPlayerAlive(client)) + if (IsClientInGame(client) && GetClientTeam(client) == L4D2Team_Survivor && IsPlayerAlive(client)) { if (GetEntProp(client, Prop_Send, "m_reviveTarget") > 0) { diff --git a/addons/sourcemod/scripting/pill_passer.sp b/addons/sourcemod/scripting/pill_passer.sp index 49499edda..1d44d8a1b 100644 --- a/addons/sourcemod/scripting/pill_passer.sp +++ b/addons/sourcemod/scripting/pill_passer.sp @@ -3,7 +3,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #define ENTITY_MAX_NAME_LENGTH 64 @@ -26,12 +26,12 @@ public Action OnPlayerRunCmd(int iClient, int &iButtons, int &iImpulse, float fV char sWeaponName[ENTITY_MAX_NAME_LENGTH]; GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - WeaponId iWeapId = WeaponNameToId(sWeaponName); + int iWeapId = WeaponNameToId(sWeaponName); if (iWeapId == WEPID_PAIN_PILLS || iWeapId == WEPID_ADRENALINE) { int iTarget = GetClientAimTarget(iClient, true); - if (iTarget > 0 && GetClientTeam(iTarget) == view_as(L4D2Team_Survivor) && !IsPlayerIncap(iTarget)) { - int iTargetWeaponIndex = GetPlayerWeaponSlot(iTarget, view_as(L4D2WeaponSlot_LightHealthItem)); + if (iTarget > 0 && GetClientTeam(iTarget) == L4D2Team_Survivor && !IsPlayerIncap(iTarget)) { + int iTargetWeaponIndex = GetPlayerWeaponSlot(iTarget, L4D2WeaponSlot_LightHealthItem); if (iTargetWeaponIndex == -1) { float fClientOrigin[3], fTargetOrigin[3]; @@ -40,7 +40,7 @@ public Action OnPlayerRunCmd(int iClient, int &iButtons, int &iImpulse, float fV if (GetVectorDistance(fClientOrigin, fTargetOrigin, true) < MAX_DIST_SQUARED) { // Remove item - int iGiverWeaponIndex = GetPlayerWeaponSlot(iClient, view_as(L4D2WeaponSlot_LightHealthItem)); + int iGiverWeaponIndex = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_LightHealthItem); RemovePlayerItem(iClient, iGiverWeaponIndex); #if (SOURCEMOD_V_MINOR == 11) || USE_GIVEPLAYERITEM @@ -59,7 +59,7 @@ public Action OnPlayerRunCmd(int iClient, int &iButtons, int &iImpulse, float fV Handle hFakeEvent = CreateEvent("weapon_given"); SetEventInt(hFakeEvent, "userid", GetClientUserId(iTarget)); SetEventInt(hFakeEvent, "giver", GetClientUserId(iClient)); - SetEventInt(hFakeEvent, "weapon", view_as(iWeapId)); + SetEventInt(hFakeEvent, "weapon", iWeapId); SetEventInt(hFakeEvent, "weaponentid", iGiverWeaponIndex); FireEvent(hFakeEvent); diff --git a/addons/sourcemod/scripting/playermanagement.sp b/addons/sourcemod/scripting/playermanagement.sp index fdd56c813..a117ea0f1 100644 --- a/addons/sourcemod/scripting/playermanagement.sp +++ b/addons/sourcemod/scripting/playermanagement.sp @@ -195,6 +195,8 @@ public Action SecureSpec(Handle timer, any client) { KillTimer(SpecTimer[client]); SpecTimer[client] = INVALID_HANDLE; + + return Plugin_Stop; } public Action RespecDelay_Timer(Handle timer, any client) @@ -204,6 +206,8 @@ public Action RespecDelay_Timer(Handle timer, any client) ChangeClientTeamEx(client, L4D2Team_Spectator, true); blockVotes[client] = false; } + + return Plugin_Stop; } public Action Vote_Listener(int client, const char[] command, int argc) @@ -242,7 +246,7 @@ public Action SwapTeams_Cmd(int client, int args) bool IsGhost(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isGhost")); + return view_as(GetEntProp(client, Prop_Send, "m_isGhost", 1)); } public Action Swap_Cmd(int client, int args) diff --git a/addons/sourcemod/scripting/predictable_unloader.sp b/addons/sourcemod/scripting/predictable_unloader.sp index 177e6b5cc..1291c58d4 100644 --- a/addons/sourcemod/scripting/predictable_unloader.sp +++ b/addons/sourcemod/scripting/predictable_unloader.sp @@ -109,17 +109,20 @@ public Action UnloadPlugins(int args) // Using Timers because these are time crucial and ServerCommands aren't a 100% reliable in terms of execution order. CreateTimer(0.1, RefreshPlugins); CreateTimer(0.5, UnloadSelf); + + return Plugin_Handled; } public Action RefreshPlugins(Handle timer) { ServerCommand("sm plugins refresh"); + + return Plugin_Stop; } public Action UnloadSelf(Handle timer) { - ServerCommand("sm plugins unload %s", sPlugin) -} - - + ServerCommand("sm plugins unload %s", sPlugin); + return Plugin_Stop; +} diff --git a/addons/sourcemod/scripting/ratemonitor.sp b/addons/sourcemod/scripting/ratemonitor.sp index 0fbdf1376..0d3f91832 100644 --- a/addons/sourcemod/scripting/ratemonitor.sp +++ b/addons/sourcemod/scripting/ratemonitor.sp @@ -3,7 +3,7 @@ #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #include @@ -155,7 +155,7 @@ public void OnMapEnd() public void OnTeamChange(Event hEvent, const char[] name, bool dontBroadcast) { - if (hEvent.GetInt("team") != view_as(L4D2Team_Spectator)) { + if (hEvent.GetInt("team") != L4D2Team_Spectator) { int userid = hEvent.GetInt("userid"); int client = GetClientOfUserId(userid); if (client > 0 && !IsFakeClient(client)) { @@ -170,6 +170,8 @@ public Action OnTeamChangeDelay(Handle hTimer, any userid) if (client > 0) { RegisterSettings(client); } + + return Plugin_Stop; } public void OnClientSettingsChanged(int client) @@ -191,7 +193,7 @@ public Action ListRates(int client, int args) hClientSettingsArray.GetArray(i, player, sizeof(NetsettingsStruct)); int iClient = GetClientBySteamId(player.Client_SteamId); - if (iClient > 0 && GetClientTeam(client) > view_as(L4D2Team_Spectator)) { + if (iClient > 0 && GetClientTeam(client) > L4D2Team_Spectator) { ReplyToCommand(client, "\x03%N\x01 : %d/%d/%d", iClient, player.Client_Cmdrate, player.Client_Updaterate, player.Client_Rate); } } @@ -201,7 +203,7 @@ public Action ListRates(int client, int args) hClientSettingsArray.GetArray(i, player[0], view_as(NetsettingsStruct)); int iClient = GetClientBySteamId(player[Client_SteamId]); - if (iClient > 0 && GetClientTeam(iClient) > view_as(L4D2Team_Spectator)) { + if (iClient > 0 && GetClientTeam(iClient) > L4D2Team_Spectator) { ReplyToCommand(client, "\x03%N\x01 : %d/%d/%d", iClient, player[Client_Cmdrate], player[Client_Updaterate], player[Client_Rate]); } } @@ -212,7 +214,7 @@ public Action ListRates(int client, int args) void RegisterSettings(int client) { - if (GetClientTeam(client) < view_as(L4D2Team_Survivor)) { + if (GetClientTeam(client) < L4D2Team_Survivor) { return; } @@ -378,7 +380,7 @@ void PunishPlayer(int client, const char[] sCmdRate, const char[] sUpdateRate, c } } case 2: {// Move to spec - ChangeClientTeam(client, view_as(L4D2Team_Spectator)); + ChangeClientTeam(client, L4D2Team_Spectator); if (bInitialRegister) { if (bPublic) { diff --git a/addons/sourcemod/scripting/readyup.sp b/addons/sourcemod/scripting/readyup.sp index daf1646b8..5c90466f9 100644 --- a/addons/sourcemod/scripting/readyup.sp +++ b/addons/sourcemod/scripting/readyup.sp @@ -51,6 +51,14 @@ public Plugin myinfo = #define DEBUG 0 +enum +{ + WL_NotInWater = 0, + WL_Feet, + WL_Waist, + WL_Eyes +}; + // ======================== // Plugin Variables // ======================== @@ -442,9 +450,9 @@ public Action Timer_PlayerTeam(Handle timer, DataPack dp) } g_hChangeTeamTimer[client] = null; -} - + return Plugin_Stop; +} // ======================== // Forwards @@ -548,20 +556,15 @@ public Action OnPlayerRunCmd(int client, int& buttons, int& impulse, float vel[3 } else { - /* Check how much the player is submerged - - Possible states: - WL_NotInWater=0, - WL_Feet, - WL_Waist, - WL_Eyes - */ - if (GetEntProp(client, Prop_Send, "m_nWaterLevel") == 3) + if (GetEntProp(client, Prop_Send, "m_nWaterLevel") == WL_Eyes) { ReturnPlayerToSaferoom(client, false); } } } } + + return Plugin_Continue; } public Action L4D_OnFirstSurvivorLeftSafeArea(int client) @@ -579,6 +582,8 @@ public Action L4D_OnFirstSurvivorLeftSafeArea(int client) public Action Timer_RestartMob(Handle timer) { if (inReadyUp) RestartMobCountdown(false); + + return Plugin_Stop; } @@ -590,20 +595,22 @@ public Action Timer_RestartMob(Handle timer) public Action Say_Callback(int client, const char[] command, int argc) { SetEngineTime(client); + + return Plugin_Continue; } public Action Vote_Callback(int client, const char[] command, int argc) { // Fast ready / unready through default keybinds for voting - if (!client) return; - if (BuiltinVote_IsVoteInProgress() && IsClientInBuiltinVotePool(client)) return; + if (!client) return Plugin_Continue; + if (BuiltinVote_IsVoteInProgress() && IsClientInBuiltinVotePool(client)) return Plugin_Continue; if (Game_IsVoteInProgress()) { int voteteam = Game_GetVoteTeam(); if (voteteam == -1 || voteteam == GetClientTeam(client)) { - return; + return Plugin_Continue; } } @@ -613,6 +620,8 @@ public Action Vote_Callback(int client, const char[] command, int argc) Ready_Cmd(client, 0); else if (strcmp(sArg, "No", false) == 0) Unready_Cmd(client, 0); + + return Plugin_Continue; } @@ -781,7 +790,7 @@ void ToggleCommandListeners(bool hook) } } -public int DummyHandler(Handle menu, MenuAction action, int param1, int param2) { } +public int DummyHandler(Handle menu, MenuAction action, int param1, int param2) { return 1; } public Action MenuRefresh_Timer(Handle timer) { @@ -1107,6 +1116,8 @@ public Action Timer_AutoStartHelper(Handle timer) public Action Timer_InitiateAutoStart(Handle timer) { InitiateAutoStart(); + + return Plugin_Stop; } void InitiateAutoStart(bool real = true) @@ -1253,7 +1264,9 @@ void CancelFullReady(int client, disruptType type) public Action Timer_RestartCountdowns(Handle timer, bool startOn) { - if (!inReadyUp && !startOn) return; + if (!inReadyUp && !startOn) { + return Plugin_Stop; + } if (IsScavenge()) { @@ -1265,6 +1278,8 @@ public Action Timer_RestartCountdowns(Handle timer, bool startOn) } RestartMobCountdown(startOn); + + return Plugin_Stop; } void RestartVersusStartCountdown(bool startOn) @@ -1379,6 +1394,7 @@ void DoSecrets(int client) public Action SecretSpamDelay(Handle timer, int client) { blockSecretSpam[client] = null; + return Plugin_Stop; } public Action killParticle(Handle timer, int entRef) @@ -1388,13 +1404,16 @@ public Action killParticle(Handle timer, int entRef) { AcceptEntityInput(entity, "Kill"); } + return Plugin_Stop; } public Action killSound(Handle timer) { for (int i = 1; i <= MaxClients; i++) - if (IsClientInGame(i) && !IsFakeClient(i)) - StopSound(i, SNDCHAN_AUTO, SECRET_SOUND); + if (IsClientInGame(i) && !IsFakeClient(i)) + StopSound(i, SNDCHAN_AUTO, SECRET_SOUND); + + return Plugin_Stop; } @@ -1473,7 +1492,10 @@ public int Native_GetFooterStringAtIndex(Handle plugin, int numParams) } SetNativeString(2, buffer, maxlen, true); + return true; } + + return false; } public int Native_IsInReady(Handle plugin, int numParams) @@ -1655,7 +1677,7 @@ stock void SetTeamFrozen(int team, bool freezeStatus) } } -stock int SetClientFrozen(int client, bool freeze) +stock void SetClientFrozen(int client, bool freeze) { SetEntityMoveType(client, freeze ? MOVETYPE_NONE : (GetClientTeam(client) == L4D2Team_Spectator ? MOVETYPE_NOCLIP : MOVETYPE_WALK)); } diff --git a/addons/sourcemod/scripting/rock_stumble_block.sp b/addons/sourcemod/scripting/rock_stumble_block.sp index 989b63fc9..bb75e5ab0 100644 --- a/addons/sourcemod/scripting/rock_stumble_block.sp +++ b/addons/sourcemod/scripting/rock_stumble_block.sp @@ -1,5 +1,5 @@ #pragma semicolon 1 -#pragma newdecls required; +#pragma newdecls required #include #include @@ -7,27 +7,30 @@ #define TEAM_INFECTED 3 #define Z_TANK 8 -bool - g_bBlockStumble = false; +bool g_bBlockStumble = false; public Plugin myinfo = { name = "Tank Rock Stumble Block", author = "Jacob", description = "Fixes rocks disappearing if tank gets stumbled while throwing.", - version = "0.2", + version = "0.3", url = "https://github.com/SirPlease/L4D2-Competitive-Rework" }; -public Action L4D_OnCThrowActivate() +public Action L4D_OnCThrowActivate(int iAbility) { g_bBlockStumble = true; CreateTimer(2.0, UnblockStumble); + + return Plugin_Continue; } public Action UnblockStumble(Handle hTimer) { g_bBlockStumble = false; + + return Plugin_Stop; } public Action L4D2_OnStagger(int iTarget) diff --git a/addons/sourcemod/scripting/si_class_announce.sp b/addons/sourcemod/scripting/si_class_announce.sp index 85a405288..3cbdef947 100644 --- a/addons/sourcemod/scripting/si_class_announce.sp +++ b/addons/sourcemod/scripting/si_class_announce.sp @@ -38,15 +38,15 @@ public Plugin myinfo = static const char g_csSIClassName[][] = { - "", - "Smoker", - "(Boomer)", - "Hunter", - "(Spitter)", - "Jockey", - "Charger", - "", - "" + "", + "Smoker", + "(Boomer)", + "Hunter", + "(Spitter)", + "Jockey", + "Charger", + "", + "" }; Handle @@ -135,11 +135,13 @@ public Action UpdateReadyUpFooter(Handle timer) g_hAddFooterTimer = null; if (!IsInfectedTeamFullAlive() || !g_bAllowFooter) - return; + return Plugin_Stop; char msg[65]; if (ProcessSIString(msg, sizeof(msg), true)) g_bAllowFooter = !(AddStringToReadyFooter(msg) != -1); + + return Plugin_Stop; } public void OnRoundIsLive() @@ -191,7 +193,7 @@ bool ProcessSIString(char[] msg, int maxlength, bool footer = false) if (!iSpawns) { return false; } - + strcopy(msg, maxlength, footer ? "SI: " : "Special Infected: "); int printFlags = g_hCvarPrint.IntValue; @@ -228,7 +230,7 @@ void AnnounceSIClasses(const char[] Message) if (printFlags & CHAT_FLAG) CPrintToChat(i, Message); if (printFlags & HINT_FLAG) PrintHintText(i, temp); - } + } } stock bool IsInfectedTeamFullAlive() diff --git a/addons/sourcemod/scripting/si_fire_immunity.sp b/addons/sourcemod/scripting/si_fire_immunity.sp index b8533959d..d70b2fc2d 100644 --- a/addons/sourcemod/scripting/si_fire_immunity.sp +++ b/addons/sourcemod/scripting/si_fire_immunity.sp @@ -196,6 +196,8 @@ public Action ExtinguishDelay(Handle hTimer, any iUserID) if (iClient > 0 && IsLiveInfected(iClient)) { ExtinguishFire(iClient); } + + return Plugin_Stop; } bool IsLiveInfected(int iClient) diff --git a/addons/sourcemod/scripting/spechud.sp b/addons/sourcemod/scripting/spechud.sp index e2a17833b..a767b3e4f 100644 --- a/addons/sourcemod/scripting/spechud.sp +++ b/addons/sourcemod/scripting/spechud.sp @@ -6,7 +6,7 @@ #include #include #include -#define L4D2UTIL_STOCKS_ONLY +#define L4D2UTIL_STOCKS_ONLY 1 #include #undef REQUIRE_PLUGIN #include @@ -46,7 +46,7 @@ enum L4D2Gamemode }; L4D2Gamemode g_Gamemode; -//L4D2_Infected storedClass[MAXPLAYERS+1]; +//int storedClass[MAXPLAYERS+1]; // Game Var ConVar survivor_limit, z_max_player_zombies, versus_boss_buffer, mp_gamemode, mp_roundlimit, sv_maxplayers, tank_burn_duration; @@ -303,6 +303,8 @@ public Action SetMapFirstTankSpawningScheme(int args) char mapname[64]; GetCmdArg(1, mapname, sizeof(mapname)); hFirstTankSpawningScheme.SetValue(mapname, true); + + return Plugin_Handled; } public Action SetMapSecondTankSpawningScheme(int args) @@ -310,6 +312,7 @@ public Action SetMapSecondTankSpawningScheme(int args) char mapname[64]; GetCmdArg(1, mapname, sizeof(mapname)); hSecondTankSpawningScheme.SetValue(mapname, true); + return Plugin_Handled; } public Action SetFinaleExceptionMap(int args) @@ -317,6 +320,7 @@ public Action SetFinaleExceptionMap(int args) char mapname[64]; GetCmdArg(1, mapname, sizeof(mapname)); hFinaleExceptionMaps.SetValue(mapname, true); + return Plugin_Handled; } /**********************************************************************************************/ @@ -423,7 +427,7 @@ public void Event_PlayerTeam(Event event, const char[] name, bool dontBroadcast) int client = GetClientOfUserId(event.GetInt("userid")); if (!client) return; - L4D2_Team team = view_as(event.GetInt("team")); + int team = event.GetInt("team"); if (team == L4D2Team_None) // Player disconnecting { @@ -451,7 +455,7 @@ stock void BuildPlayerArrays() { if (!IsClientInGame(client)) continue; - switch (view_as(GetClientTeam(client))) + switch (GetClientTeam(client)) { case L4D2Team_Spectator: { @@ -488,8 +492,8 @@ stock void BuildPlayerArrays() public int SortSurvArray(int elem1, int elem2, const int[] array, Handle hndl) { - SurvivorCharacter sc1 = IdentifySurvivor(elem1); - SurvivorCharacter sc2 = IdentifySurvivor(elem2); + int sc1 = IdentifySurvivor(elem1); + int sc2 = IdentifySurvivor(elem2); if (sc1 > sc2) { return 1; } else if (sc1 < sc2) { return -1; } @@ -501,8 +505,8 @@ public int SortSurvArray(int elem1, int elem2, const int[] array, Handle hndl) // ====================================================================== public Action ToggleSpecHudCmd(int client, int args) { - if (view_as(GetClientTeam(client)) != L4D2Team_Spectator) - return; + if (GetClientTeam(client) != L4D2Team_Spectator) + return Plugin_Handled; if (bSpecHudActive[client]) { @@ -536,13 +540,14 @@ public Action ToggleSpecHudCmd(int client, int args) } CPrintToChat(client, "<{olive}HUD{default}> Spectator HUD is now %s.", (bSpecHudActive[client] ? "{blue}on{default}" : "{red}off{default}")); + return Plugin_Handled; } public Action ToggleTankHudCmd(int client, int args) { - L4D2_Team team = view_as(GetClientTeam(client)); + int team = GetClientTeam(client); if (team == L4D2Team_Survivor) - return; + return Plugin_Handled; if (bTankHudActive[client]) { @@ -565,6 +570,8 @@ public Action ToggleTankHudCmd(int client, int args) } CPrintToChat(client, "<{olive}HUD{default}> Tank HUD is now %s.", (bTankHudActive[client] ? "{blue}on{default}" : "{red}off{default}")); + + return Plugin_Handled; } /**********************************************************************************************/ @@ -630,8 +637,8 @@ public Action HudDrawTimer(Handle hTimer) return Plugin_Continue; } -public int DummySpecHudHandler(Menu hMenu, MenuAction action, int param1, int param2) {} -public int DummyTankHudHandler(Menu hMenu, MenuAction action, int param1, int param2) {} +public int DummySpecHudHandler(Menu hMenu, MenuAction action, int param1, int param2) { return 1; } +public int DummyTankHudHandler(Menu hMenu, MenuAction action, int param1, int param2) { return 1; } /**********************************************************************************************/ @@ -651,8 +658,8 @@ void FillHeaderInfo(Panel &hSpecHud) void GetMeleePrefix(int client, char[] prefix, int length) { - int secondary = GetPlayerWeaponSlot(client, view_as(L4D2WeaponSlot_Secondary)); - WeaponId secondaryWep = IdentifyWeapon(secondary); + int secondary = GetPlayerWeaponSlot(client, L4D2WeaponSlot_Secondary); + int secondaryWep = IdentifyWeapon(secondary); static char buf[4]; switch (secondaryWep) @@ -672,9 +679,9 @@ void GetWeaponInfo(int client, char[] info, int length) static char buffer[32]; int activeWep = GetEntPropEnt(client, Prop_Send, "m_hActiveWeapon"); - int primaryWep = GetPlayerWeaponSlot(client, view_as(L4D2WeaponSlot_Primary)); - WeaponId activeWepId = IdentifyWeapon(activeWep); - WeaponId primaryWepId = IdentifyWeapon(primaryWep); + int primaryWep = GetPlayerWeaponSlot(client, L4D2WeaponSlot_Primary); + int activeWepId = IdentifyWeapon(activeWep); + int primaryWepId = IdentifyWeapon(primaryWep); // Let's begin with what player is holding, // but cares only pistols if holding secondary. @@ -706,7 +713,7 @@ void GetWeaponInfo(int client, char[] info, int length) // show the melee full name. if (activeWepId == WEPID_MELEE || activeWepId == WEPID_CHAINSAW) { - MeleeWeaponId meleeWepId = IdentifyMeleeWeapon(activeWep); + int meleeWepId = IdentifyMeleeWeapon(activeWep); GetLongMeleeWeaponName(meleeWepId, info, length); } } @@ -715,7 +722,7 @@ void GetWeaponInfo(int client, char[] info, int length) // Default display -> [Primary | Secondary ] // Holding melee included in this way // i.e. [Chrome 8/56 | M] - if (GetSlotFromWeaponId(activeWepId) != view_as(L4D2WeaponSlot_Secondary) || activeWepId == WEPID_MELEE || activeWepId == WEPID_CHAINSAW) + if (GetSlotFromWeaponId(activeWepId) != L4D2WeaponSlot_Secondary || activeWepId == WEPID_MELEE || activeWepId == WEPID_CHAINSAW) { GetMeleePrefix(client, buffer, sizeof(buffer)); Format(info, length, "%s | %s", info, buffer); @@ -992,7 +999,7 @@ void FillInfectedInfo(Panel &hSpecHud) } else { - L4D2_Infected zClass = GetInfectedClass(client); + int zClass = GetInfectedClass(client); if (zClass == L4D2Infected_Tank) continue; @@ -1261,7 +1268,7 @@ void FillGameInfo(Panel &hSpecHud) #define MILITARY_SNIPER_OFFSET_IAMMO 40; #define GRENADE_LAUNCHER_OFFSET_IAMMO 68; -stock int GetWeaponExtraAmmo(int client, WeaponId wepid) +stock int GetWeaponExtraAmmo(int client, int wepid) { static int ammoOffset; if (!ammoOffset) ammoOffset = FindSendPropInfo("CCSPlayer", "m_iAmmo"); diff --git a/addons/sourcemod/scripting/starting_items.sp b/addons/sourcemod/scripting/starting_items.sp index ff6fffc1e..aa6fbb9b8 100644 --- a/addons/sourcemod/scripting/starting_items.sp +++ b/addons/sourcemod/scripting/starting_items.sp @@ -99,23 +99,23 @@ void DetermineItems() StringMap hItemsStringMap = new StringMap(); if (iItemFlags & HEALTH_FIRST_AID_KIT) { - hItemsStringMap.SetValue("weapon_first_aid_kit", view_as(L4D2WeaponSlot_HeavyHealthItem)); + hItemsStringMap.SetValue("weapon_first_aid_kit", L4D2WeaponSlot_HeavyHealthItem); } else if (iItemFlags & HEALTH_DEFIBRILLATOR) { - hItemsStringMap.SetValue("weapon_defibrillator", view_as(L4D2WeaponSlot_HeavyHealthItem)); + hItemsStringMap.SetValue("weapon_defibrillator", L4D2WeaponSlot_HeavyHealthItem); } if (iItemFlags & HEALTH_PAIN_PILLS) { - hItemsStringMap.SetValue("weapon_pain_pills", view_as(L4D2WeaponSlot_LightHealthItem)); + hItemsStringMap.SetValue("weapon_pain_pills", L4D2WeaponSlot_LightHealthItem); } else if (iItemFlags & HEALTH_ADRENALINE) { - hItemsStringMap.SetValue("weapon_adrenaline", view_as(L4D2WeaponSlot_LightHealthItem)); + hItemsStringMap.SetValue("weapon_adrenaline", L4D2WeaponSlot_LightHealthItem); } if (iItemFlags & THROWABLE_PIPE_BOMB) { - hItemsStringMap.SetValue("weapon_pipe_bomb", view_as(L4D2WeaponSlot_Throwable)); + hItemsStringMap.SetValue("weapon_pipe_bomb", L4D2WeaponSlot_Throwable); } else if (iItemFlags & THROWABLE_MOLOTOV) { - hItemsStringMap.SetValue("weapon_molotov", view_as(L4D2WeaponSlot_Throwable)); + hItemsStringMap.SetValue("weapon_molotov", L4D2WeaponSlot_Throwable); } else if (iItemFlags & THROWABLE_VOMITJAR) { - hItemsStringMap.SetValue("weapon_vomitjar", view_as(L4D2WeaponSlot_Throwable)); + hItemsStringMap.SetValue("weapon_vomitjar", L4D2WeaponSlot_Throwable); } GiveStartingItems(hItemsStringMap); @@ -135,7 +135,7 @@ void GiveStartingItems(StringMap &hItemsStringMap) int iSlotIndex, iSize = hItemsSnapshot.Length; for (int i = 1; i <= MaxClients; i++) { - if (IsClientInGame(i) && GetClientTeam(i) == view_as(L4D2Team_Survivor) && IsPlayerAlive(i)) { + if (IsClientInGame(i) && GetClientTeam(i) == L4D2Team_Survivor && IsPlayerAlive(i)) { for (int j = 0; j < iSize; j++) { hItemsSnapshot.GetKey(j, sEntName, sizeof(sEntName)); hItemsStringMap.GetValue(sEntName, iSlotIndex); diff --git a/addons/sourcemod/scripting/survivor_mvp.sp b/addons/sourcemod/scripting/survivor_mvp.sp index 5d386af19..46bad48db 100644 --- a/addons/sourcemod/scripting/survivor_mvp.sp +++ b/addons/sourcemod/scripting/survivor_mvp.sp @@ -140,9 +140,9 @@ new ttlPinnedDuringTank[MAXPLAYERS + 1]; // The total tim new iTotalKills; // prolly more efficient to store than to recalculate new iTotalCommon; -new iTotalDamage; -new iTotalDamageTank; -new iTotalDamageWitch; +//new iTotalDamage; +//new iTotalDamageTank; +//new iTotalDamageWitch; new iTotalDamageAll; new iTotalFF; @@ -238,8 +238,8 @@ public OnPluginStart() HookEvent("round_start", RoundStart_Event, EventHookMode_PostNoCopy); HookEvent("round_end", RoundEnd_Event, EventHookMode_PostNoCopy); HookEvent("map_transition", RoundEnd_Event, EventHookMode_PostNoCopy); - HookEvent("scavenge_round_start", EventHook:ScavRoundStart); - HookEvent("player_left_start_area", PlayerLeftStartArea); + HookEvent("scavenge_round_start", ScavRoundStart, EventHookMode_PostNoCopy); + HookEvent("player_left_start_area", PlayerLeftStartArea, EventHookMode_PostNoCopy); HookEvent("pills_used", pillsUsedEvent); HookEvent("boomer_exploded", boomerExploded); HookEvent("charger_carry_end", chargerCarryEnd); @@ -272,8 +272,6 @@ public OnPluginStart() bTrackFF = GetConVarBool(hTrackFF); iBrevityFlags = GetConVarInt(hBrevityFlags); - - // for now, force FF tracking on: bTrackFF = true; @@ -398,7 +396,7 @@ public OnMapEnd() bInRound = false; } -public ScavRoundStart(Handle:event) +public void ScavRoundStart(Handle:event, const String:name[], bool:dontBroadcast) { // clear mvp stats new i, maxplayers = MaxClients; @@ -428,9 +426,9 @@ public ScavRoundStart(Handle:event) } iTotalKills = 0; iTotalCommon = 0; - iTotalDamage = 0; - iTotalDamageTank = 0; - iTotalDamageWitch = 0; + //iTotalDamage = 0; + //iTotalDamageTank = 0; + //iTotalDamageWitch = 0; iTotalDamageAll = 0; iTotalFF = 0; ttlSiDmgDuringTank = 0; @@ -479,12 +477,12 @@ public RoundStart_Event(Handle:event, const String:name[], bool:dontBroadcast) } iTotalKills = 0; iTotalCommon = 0; - iTotalDamage = 0; + //iTotalDamage = 0; iTotalDamageAll = 0; iTotalFF = 0; ttlSiDmgDuringTank = 0; ttlCommonKilledDuringTank = 0; - iTotalDamageTank = 0; + //iTotalDamageTank = 0; tankThrow = false; tankSpawned = false; @@ -539,7 +537,7 @@ public Action:SurvivorMVP_Cmd(client, args) decl String:printBuffer[4096]; new String:strLines[8][192]; - printBuffer = GetMVPString(); + GetMVPString(printBuffer, sizeof(printBuffer)); // PrintToChat has a max length. Split it in to individual lines to output separately new intPieces = ExplodeString(printBuffer, "\n", strLines, sizeof(strLines), sizeof(strLines[])); @@ -564,7 +562,7 @@ public Action:delayedMVPPrint(Handle:timer) decl String:printBuffer[4096]; new String:strLines[8][192]; - printBuffer = GetMVPString(); + GetMVPString(printBuffer, sizeof(printBuffer)); // PrintToChatAll has a max length. Split it in to individual lines to output separately new intPieces = ExplodeString(printBuffer, "\n", strLines, sizeof(strLines), sizeof(strLines[])); @@ -879,14 +877,14 @@ public PlayerHurt_Event(Handle:event, const String:name[], bool:dontBroadcast) iDidDamage[attacker] += damageDone; iDidDamageAll[attacker] += damageDone; - iTotalDamage += damageDone; + // iTotalDamage += damageDone; iTotalDamageAll += damageDone; } else if (zombieClass == ZC_TANK && damageDone != 5000) // For some reason the last attacker does 5k damage? { // We want to track tank damage even if we're not factoring it in to our mvp result iDidDamageTank[attacker] += damageDone; - iTotalDamageTank += damageDone; + //iTotalDamageTank += damageDone; // If we're factoring it in, include it in our overall damage if (bCountTankDamage) @@ -941,7 +939,7 @@ public InfectedHurt_Event(Handle:event, const String:name[], bool:dontBroadcast) { // We want to track the witch damage regardless of whether we're counting it in our mvp stat iDidDamageWitch[attacker] += damageDone; - iTotalDamageWitch += damageDone; + //iTotalDamageWitch += damageDone; // If we're counting witch damage in our mvp stat, lets add the amount of damage done to the witch if (bCountWitchDamage) @@ -1016,24 +1014,20 @@ public InfectedDeath_Event(Handle:event, const String:name[], bool:dontBroadcast } } - - /* * MVP string & 'sorting' * ====================== */ - -String: GetMVPString() +void GetMVPString(char[] printBuffer, const int iSize) { - decl String:printBuffer[4096]; decl String:tmpBuffer[1024]; - + printBuffer[0] = '\0'; + decl String:tmpName[64]; decl String:mvp_SI_name[64]; decl String:mvp_Common_name[64]; decl String:mvp_FF_name[64]; - printBuffer = ""; new mvp_SI = 0; new mvp_Common = 0; new mvp_FF = 0; @@ -1116,7 +1110,7 @@ String: GetMVPString() if (mvp_SI == 0 && mvp_Common == 0 && !(iBrevityFlags & BREV_SI && iBrevityFlags & BREV_CI)) { Format(tmpBuffer, sizeof(tmpBuffer), "{blue}[{default}MVP{blue}]{default} {blue}({default}not enough action yet{blue}){default}\n"); - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iSize, tmpBuffer); } else { @@ -1131,11 +1125,11 @@ String: GetMVPString() } else { Format(tmpBuffer, sizeof(tmpBuffer), "{blue}[{default}MVP{blue}] SI: {olive}%s {blue}({default}%d {green}dmg {blue}[{default}%.0f%%{blue}]{olive}, {default}%d {green}kills {blue}[{default}%.0f%%{blue}])\n", mvp_SI_name, iDidDamageAll[mvp_SI], (float(iDidDamageAll[mvp_SI]) / float(iTotalDamageAll)) * 100, iGotKills[mvp_SI], (float(iGotKills[mvp_SI]) / float(iTotalKills)) * 100); } - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iSize, tmpBuffer); } else { - StrCat(printBuffer, sizeof(printBuffer), "{blue}[{default}MVP{blue}] SI: {blue}({default}nobody{blue}){default}\n"); + StrCat(printBuffer, iSize, "{blue}[{default}MVP{blue}] SI: {blue}({default}nobody{blue}){default}\n"); } } @@ -1150,7 +1144,7 @@ String: GetMVPString() } else { Format(tmpBuffer, sizeof(tmpBuffer), "{blue}[{default}MVP{blue}] CI: {olive}%s {blue}({default}%d {green}common {blue}[{default}%.0f%%{blue}])\n", mvp_Common_name, iGotCommon[mvp_Common], (float(iGotCommon[mvp_Common]) / float(iTotalCommon)) * 100); } - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iSize, tmpBuffer); } } } @@ -1161,7 +1155,7 @@ String: GetMVPString() if (mvp_FF == 0) { Format(tmpBuffer, sizeof(tmpBuffer), "{blue}[{default}LVP{blue}] FF{default}: {green}no friendly fire at all!{default}\n"); - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iSize, tmpBuffer); } else { @@ -1172,11 +1166,9 @@ String: GetMVPString() } else { Format(tmpBuffer, sizeof(tmpBuffer), "{blue}[{default}LVP{blue}] FF{default}: {olive}%s {blue}({default}%d {green}friendly fire {blue}[{default}%.0f%%{blue}]){default}\n", mvp_FF_name, iDidFF[mvp_FF], (float(iDidFF[mvp_FF]) / float(iTotalFF)) * 100); } - StrCat(printBuffer, sizeof(printBuffer), tmpBuffer); + StrCat(printBuffer, iSize, tmpBuffer); } } - - return printBuffer; } diff --git a/addons/sourcemod/scripting/sv_consistency_fix.sp b/addons/sourcemod/scripting/sv_consistency_fix.sp index b041f7689..69646a286 100644 --- a/addons/sourcemod/scripting/sv_consistency_fix.sp +++ b/addons/sourcemod/scripting/sv_consistency_fix.sp @@ -108,6 +108,7 @@ public Action PrintWhitelist(Handle hTimer, any iUserId) PrintToConsole(iClient, " "); PrintToConsole(iClient, " "); } + return Plugin_Stop; } public Action Cmd_ConsistencyCheck(int iClient, int iArgs) diff --git a/addons/sourcemod/scripting/tankdoorfix.sp b/addons/sourcemod/scripting/tankdoorfix.sp index 7ff8de201..302b9329b 100644 --- a/addons/sourcemod/scripting/tankdoorfix.sp +++ b/addons/sourcemod/scripting/tankdoorfix.sp @@ -101,7 +101,7 @@ public Action Timer_DoorCheck(Handle timer, int clientUserID) { int client = GetClientOfUserId(clientUserID); - if(client > 0 && IsClientInGame(client)) + if (client > 0 && IsClientInGame(client)) { float direction[3]; @@ -112,6 +112,8 @@ public Action Timer_DoorCheck(Handle timer, int clientUserID) SDKHooks_TakeDamage(result, client, client, 1200.0, DMG_CLUB, _, direction); } } + + return Plugin_Stop; } public void Event_RoundStart(Event event, const char[] name, bool dontBroadcast) diff --git a/addons/sourcemod/scripting/temphealthfix.sp b/addons/sourcemod/scripting/temphealthfix.sp index 48aec30e7..e2cac933f 100644 --- a/addons/sourcemod/scripting/temphealthfix.sp +++ b/addons/sourcemod/scripting/temphealthfix.sp @@ -25,7 +25,7 @@ public void OnPluginStart() HookEvent("bot_player_replace", PlayerChange_Event); } -public Action Incap_Event(Event event, const char[] name, bool dontBroadcast) +public void Incap_Event(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); @@ -41,7 +41,7 @@ public Action Incap_Event(Event event, const char[] name, bool dontBroadcast) SetEntPropFloat(client, Prop_Send, "m_healthBuffer", 0.0); } -public Action Revive_Event(Event event, const char[] name, bool dontBroadcast) +public void Revive_Event(Event event, const char[] name, bool dontBroadcast) { if (event.GetBool("ledge_hang")) { @@ -53,7 +53,7 @@ public Action Revive_Event(Event event, const char[] name, bool dontBroadcast) } } -public Action PlayerChange_Event(Event event, const char[] name, bool dontBroadcast) +public void PlayerChange_Event(Event event, const char[] name, bool dontBroadcast) { int bot = GetClientOfUserId(event.GetInt("bot")) int player = GetClientOfUserId(event.GetInt("player")) @@ -78,5 +78,5 @@ public Action PlayerChange_Event(Event event, const char[] name, bool dontBroadc bool isLedged(int client) { - return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge")); + return view_as(GetEntProp(client, Prop_Send, "m_isHangingFromLedge", 1)); } diff --git a/addons/sourcemod/scripting/visualise_impacts.sp b/addons/sourcemod/scripting/visualise_impacts.sp index f551f62d2..fd2ea0d6d 100644 --- a/addons/sourcemod/scripting/visualise_impacts.sp +++ b/addons/sourcemod/scripting/visualise_impacts.sp @@ -87,6 +87,8 @@ public Action TimerDelayShowDecal(Handle hTimer, ArrayStack hStack) SendDecal(client, pos); } } + + return Plugin_Stop; } void SendDecal(int client, float pos[3]) diff --git a/addons/sourcemod/scripting/weapon_loadout_vote.sp b/addons/sourcemod/scripting/weapon_loadout_vote.sp index 2dd14c7a1..2a1ef3afe 100644 --- a/addons/sourcemod/scripting/weapon_loadout_vote.sp +++ b/addons/sourcemod/scripting/weapon_loadout_vote.sp @@ -117,7 +117,7 @@ public void Event_PlayerTeam(Event hEvent, char[] sEventName , bool bDontBroadca int iTeam = hEvent.GetInt("team"); // Only care about Survivors (Team 2) - if (iTeam != view_as(L4D2Team_Survivor)) { + if (iTeam != L4D2Team_Survivor) { return; } @@ -128,9 +128,11 @@ public void Event_PlayerTeam(Event hEvent, char[] sEventName , bool bDontBroadca public Action Timer_ChangeTeamDelay(Handle hTimer, any iUserId) { int iPlayer = GetClientOfUserId(iUserId); - if (iPlayer > 0 && GetClientTeam(iPlayer) == view_as(L4D2Team_Survivor)) { + if (iPlayer > 0 && GetClientTeam(iPlayer) == L4D2Team_Survivor) { GiveSurvivorsWeapons(iPlayer, true); } + + return Plugin_Stop; } public void Event_RoundStart(Event hEvent, char[] sEventName, bool bDontBroadcast) @@ -149,7 +151,7 @@ public void Event_RoundStart(Event hEvent, char[] sEventName, bool bDontBroadcas public Action Cmd_VoteMode(int iClient, int iArgs) { // Don't care about non-loaded players or Spectators. - if (iClient == 0 || GetClientTeam(iClient) < view_as(L4D2Team_Survivor)) { + if (iClient == 0 || GetClientTeam(iClient) < L4D2Team_Survivor) { return Plugin_Handled; } @@ -228,7 +230,7 @@ public int Menu_VoteMenuHandler(Menu hMenu, MenuAction iAction, int iClient, int int[] iPlayers = new int[MaxClients]; for (int i = 1; i <= MaxClients; i++) { - if (!IsClientInGame(i) || IsFakeClient(i) || (GetClientTeam(i) == view_as(L4D2Team_Spectator))) { + if (!IsClientInGame(i) || IsFakeClient(i) || (GetClientTeam(i) == L4D2Team_Spectator)) { continue; } @@ -327,6 +329,7 @@ public Action Timer_ClearMap(Handle hTimer) } } } + return Plugin_Stop; } public void OnRoundIsLive() @@ -338,7 +341,7 @@ int ReadyPlayers() { int iPlayersCount = 0; for (int i = 1; i <= MaxClients; i++) { - if (IsClientInGame(i) && GetClientTeam(i) > view_as(L4D2Team_Spectator)) { + if (IsClientInGame(i) && GetClientTeam(i) > L4D2Team_Spectator) { iPlayersCount++; } } @@ -371,12 +374,12 @@ void GiveSurvivorsWeapons(int iClient = 0, bool bOnlyIfSurvivorEmpty = false) void GiveAndRemovePlayerWeapon(int iClient, const char[] sWeaponName, bool bOnlyIfSurvivorEmpty = false) { - if (!IsClientInGame(iClient) || GetClientTeam(iClient) != view_as(L4D2Team_Survivor) || !IsPlayerAlive(iClient)) { + if (!IsClientInGame(iClient) || GetClientTeam(iClient) != L4D2Team_Survivor || !IsPlayerAlive(iClient)) { return; } - int iCurrMainWeapon = GetPlayerWeaponSlot(iClient, view_as(L4D2WeaponSlot_Primary)); - int iCurrSecondaryWeapon = GetPlayerWeaponSlot(iClient, view_as(L4D2WeaponSlot_Secondary)); + int iCurrMainWeapon = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_Primary); + int iCurrSecondaryWeapon = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_Secondary); // Does the player already have an item in this slot? if (iCurrMainWeapon != -1) { @@ -420,7 +423,7 @@ public Action Timer_InformPlayers(Handle hTimer) } for (int i = 1; i <= MaxClients; i++) { - if (IsClientInGame(i) && GetClientTeam(i) != view_as(L4D2Team_Spectator) && !g_bVoteUnderstood[i]) { + if (IsClientInGame(i) && GetClientTeam(i) != L4D2Team_Spectator && !g_bVoteUnderstood[i]) { CPrintToChat(i, "{blue}[{green}Zone{blue}]{default}: Welcome to {blue}Zone{green}Hunters{default}."); CPrintToChat(i, "{blue}[{green}Zone{blue}]{default}: Type {olive}!mode {default}in chat to vote on weapons used."); } @@ -433,7 +436,7 @@ public Action Timer_InformPlayers(Handle hTimer) void ReturnReadyUpPanel() { for (int i = 1; i <= MaxClients; i++) { - if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) > view_as(L4D2Team_Spectator)) { + if (IsClientInGame(i) && !IsFakeClient(i) && GetClientTeam(i) > L4D2Team_Spectator) { FakeClientCommand(i, "sm_show"); } } diff --git a/addons/sourcemod/scripting/witch_and_tankifier.sp b/addons/sourcemod/scripting/witch_and_tankifier.sp index b62b849e0..f8ac54260 100644 --- a/addons/sourcemod/scripting/witch_and_tankifier.sp +++ b/addons/sourcemod/scripting/witch_and_tankifier.sp @@ -61,7 +61,9 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max CreateNative("IsWitchPercentBlockedForTank", Native_IsWitchPercentBlockedForTank); CreateNative("SetTankPercent", Native_SetTankPercent); CreateNative("SetWitchPercent", Native_SetWitchPercent); + RegPluginLibrary("witch_and_tankifier"); + return APLRes_Success; } public void OnPluginStart() { @@ -130,8 +132,10 @@ public void RoundStartEvent(Event event, const char[] name, bool dontBroadcast) } public Action AdjustBossFlow(Handle timer) { - if (InSecondHalfOfRound()) return; - + if (InSecondHalfOfRound()) { + return Plugin_Stop; + } + hValidTankFlows.Clear(); hValidWitchFlows.Clear(); @@ -242,6 +246,8 @@ public Action AdjustBossFlow(Handle timer) { } PrintDebugInfoDump(); + + return Plugin_Stop; } // ====================================== @@ -335,8 +341,8 @@ void MergeIntervals(ArrayList merged) { if (merged.Length < 2) return; ArrayList intervals = merged.Clone(); - intervals.Sort(Sort_Ascending, Sort_Integer); - + SortADTArray(intervals, Sort_Ascending, Sort_Integer); + merged.Clear(); int current[2]; @@ -407,6 +413,7 @@ public Action StaticTank_Command(int args) { #if DEBUG PrintDebug("[StaticTank_Command] Added: %s", mapname); #endif + return Plugin_Handled; } public Action StaticWitch_Command(int args) { @@ -417,11 +424,13 @@ public Action StaticWitch_Command(int args) { #if DEBUG PrintDebug("[StaticWitch_Command] Added: %s", mapname); #endif + return Plugin_Handled; } public Action Reset_Command(int args) { hStaticTankMaps.Clear(); hStaticWitchMaps.Clear(); + return Plugin_Handled; } // ====================================== @@ -430,11 +439,14 @@ public Action Reset_Command(int args) { public Action Info_Cmd(int client, int args) { PrintDebugInfoDump(); + return Plugin_Handled; } + #if DEBUG public Action Test_Cmd(int client, int args) { PrintDebug("[Test_Cmd] Starting AdjustBossFlow timer..."); CreateTimer(0.5, AdjustBossFlow, _, TIMER_FLAG_NO_MAPCHANGE); + return Plugin_Handled; } public Action Profiler_Cmd(int client, int args) { @@ -472,7 +484,7 @@ public Action Profiler_Cmd(int client, int args) { // Natives // ====================================== -public any Native_IsStaticTankMap(Handle plugin, int numParams) { +public int Native_IsStaticTankMap(Handle plugin, int numParams) { int bytes = 0; char mapname[64]; @@ -486,7 +498,7 @@ public any Native_IsStaticTankMap(Handle plugin, int numParams) { } } -public any Native_IsStaticWitchMap(Handle plugin, int numParams) { +public int Native_IsStaticWitchMap(Handle plugin, int numParams) { int bytes = 0; char mapname[64]; @@ -500,12 +512,12 @@ public any Native_IsStaticWitchMap(Handle plugin, int numParams) { } } -public any Native_IsTankPercentValid(Handle plugin, int numParams) { +public int Native_IsTankPercentValid(Handle plugin, int numParams) { int flow = GetNativeCell(1); return IsTankPercentValid(flow); } -public any Native_IsWitchPercentValid(Handle plugin, int numParams) { +public int Native_IsWitchPercentValid(Handle plugin, int numParams) { int flow = GetNativeCell(1); bool ignoreBlock = GetNativeCell(2); @@ -531,16 +543,16 @@ public any Native_IsWitchPercentValid(Handle plugin, int numParams) { } } -public any Native_IsWitchPercentBlockedForTank(Handle plugin, int numParams) { +public int Native_IsWitchPercentBlockedForTank(Handle plugin, int numParams) { int interval[2]; if (GetTankAvoidInterval(interval) && IsValidInterval(interval)) { int flow = GetNativeCell(1); - return interval[0] <= flow <= interval[1]; + return (interval[0] <= flow <= interval[1]); } return false; } -public any Native_SetTankPercent(Handle plugin, int numParams) { +public int Native_SetTankPercent(Handle plugin, int numParams) { int flow = GetNativeCell(1); if (!IsTankPercentValid(flow)) return false; DynamicAdjustWitchFlow(flow); @@ -548,7 +560,7 @@ public any Native_SetTankPercent(Handle plugin, int numParams) { return true; } -public any Native_SetWitchPercent(Handle plugin, int numParams) { +public int Native_SetWitchPercent(Handle plugin, int numParams) { int flow = GetNativeCell(1); if (!IsWitchPercentValid(flow)) return false; SetWitchPercent(flow);

    i%=e*1q~Q=%WKLuXlfQacJ}5raq@B_A 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 D^YJ!v diff --git a/addons/sourcemod/plugins/optional/l4d2_sniper_bodyshot.smx b/addons/sourcemod/plugins/optional/l4d2_sniper_bodyshot.smx index d97c580794562085acbf8d420161e45af1c6884f..2718242df95b78ca7aaccc176898389668c71b48 100644 GIT binary patch literal 6643 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 literal 4395 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 delta 5238 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 diff --git a/addons/sourcemod/plugins/optional/l4d2_tank_damage_cvars.smx b/addons/sourcemod/plugins/optional/l4d2_tank_damage_cvars.smx index 33e7dab4e9a3f94b501772697ad15db61b48ae87..10734b51ace6e9a4e32d7920d2e49a130f261166 100644 GIT binary patch literal 6768 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 K?-aPfVf25x>fm$$ literal 4319 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