diff --git a/addons/sourcemod/gamedata/left4dhooks.l4d2.txt b/addons/sourcemod/gamedata/left4dhooks.l4d2.txt index ffeb57938..c41e8494c 100644 --- a/addons/sourcemod/gamedata/left4dhooks.l4d2.txt +++ b/addons/sourcemod/gamedata/left4dhooks.l4d2.txt @@ -1005,21 +1005,6 @@ } } - "L4DD::CDirector::EndScenario" - { - "signature" "CDirector::EndScenario" - "callconv" "thiscall" - "return" "void" - "this" "address" - "arguments" - { - "keyvalues" - { - "type" "int" - } - } - } - "L4DD::CTerrorPlayer::OnLedgeGrabbed" { "signature" "CTerrorPlayer::OnLedgeGrabbed" @@ -1116,7 +1101,7 @@ { "signature" "CTerrorPlayer::OnShovedByPounceLanding" "callconv" "thiscall" - "return" "float" + "return" "void" "this" "entity" "arguments" { @@ -1314,6 +1299,21 @@ } } + "L4DD::Infected::OnHitByVomitJar" + { + "signature" "Infected::OnHitByVomitJar" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + } + } + "L4DD::CTerrorPlayer::MaterializeFromGhost" { "signature" "CTerrorPlayer::MaterializeFromGhost" @@ -1413,6 +1413,21 @@ } } + "L4DD::CPhysicsProp::OnTakeDamage" + { + "signature" "CPhysicsProp::OnTakeDamage" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "entity" + { + "type" "objectptr" + } + } + } + "L4DD::CGasCan::Event_Killed" { "signature" "CGasCan::Event_Killed" @@ -2433,6 +2448,37 @@ "windows" "3148" "linux" "3148" } + + + + // Animation offsets: + /* Windows offset: + * + * Search string "PlayerLedgeHangMiddle", which will lead you to "CTerrorPlayerAnimState::HandleActivity_Incapacitated". + * Go to its only xref function, and again, then you are at vtable of "CTerrorPlayerAnimState". + * Double click on the first virtual function "CTerrorPlayerAnimState::ClearAnimationState". + * Go to its function xref 3 times, and you will meet with an enormous constructor function. + * + * 1. Generate pseudocode and you can easily find the offset where the cursor is. + * 2. See the "mov" instruction below the highlighted "call". + */ + "CTerrorPlayer::m_PlayerAnimState" + { + "linux" "10512" + "windows" "10524" + } + + "CMultiPlayerAnimState::m_eCurrentMainSequenceActivity" + { + "linux" "276" + "windows" "276" + } + + "CTerrorPlayerAnimState::m_bIsCustomSequence" + { + "linux" "340" + "windows" "340" + } } @@ -3098,6 +3144,17 @@ + // Animation signatures: + "CMultiPlayerAnimState::ResetMainActivity" + { + "library" "server" + "linux" "@_ZN21CMultiPlayerAnimState17ResetMainActivityEv" + "windows" "\x56\x8B\x2A\x8B\x2A\x8B\x2A\x2A\xC7\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\xFF" + /* 56 8B ? 8B ? 8B ? ? C7 ? ? ? ? ? ? ? ? ? FF */ + } + + + // ==================================================================================================== // DETOURS // ==================================================================================================== @@ -3840,18 +3897,6 @@ /* 55 8B EC 83 EC ? 57 8B F9 E8 ? ? ? ? 84 C0 0F 84 */ } - /* - * CDirector::EndScenario(ScenarioRestartReason) [clone] - */ - "CDirector::EndScenario" - { - "library" "server" - "linux" "@_ZN9CDirector11EndScenarioE21ScenarioRestartReason.part.398" - "windows" "\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x2A\x0F\x2A\x2A\x83\x2A\x2A\x0F\x2A\x2A\x0F\x87\x2A\x2A\x2A\x2A\x56" - /* ? ? ? ? ? ? ? ? ? ? ? 0F ? ? 83 ? ? 0F ? ? 0F 87 ? ? ? ? 56 */ - /* Search: "round_end" */ - } - /* * void CTerrorPlayer::OnLedgeGrabbed(CTerrorPlayer *this, const Vector *) * Search: "%s grabs a ledge - last standing at %s." @@ -4006,6 +4051,16 @@ /* Search: "Fire prop detonated %.0f,%.0f,%.0f. Breaker:%s. Attacker:%s.\n" */ } + /* CPhysicsProp::OnTakeDamage(CPhysicsProp *this, const CTakeDamageInfo) */ + "CPhysicsProp::OnTakeDamage" + { + "library" "server" + "linux" "@_ZN12CPhysicsProp12OnTakeDamageERK15CTakeDamageInfo" + "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\x56\x57\x8B\x2A\x2A\x8B\x2A\x57\x8D" + /* ? ? ? ? ? ? 83 ? ? 83 ? ? 55 8B ? ? 89 ? ? ? 8B ? 81 ? ? ? ? ? A1 ? ? ? ? 33 ? 89 ? ? 56 57 8B ? ? 8B ? 57 8D */ + /* Search: "prop_fuel_barrel" - There are 2 functions that have this string twice, one of them only contain this string, at the bottom of that one is the target call */ + } + /* CGasCan::Event_Killed(CGasCan *this, const CTakeDamageInfo *) */ "CGasCan::Event_Killed" { diff --git a/addons/sourcemod/plugins/left4dhooks.smx b/addons/sourcemod/plugins/left4dhooks.smx index 29a57a9e1..45a9319d2 100644 Binary files a/addons/sourcemod/plugins/left4dhooks.smx and b/addons/sourcemod/plugins/left4dhooks.smx differ diff --git a/addons/sourcemod/scripting/include/left4dhooks.inc b/addons/sourcemod/scripting/include/left4dhooks.inc index bd9df6959..f0def869f 100644 --- a/addons/sourcemod/scripting/include/left4dhooks.inc +++ b/addons/sourcemod/scripting/include/left4dhooks.inc @@ -51,6 +51,8 @@ #endif #define _l4dh_included +#pragma newdecls required + #include #include #include @@ -58,13 +60,13 @@ -// Natives: 256 (including 3 for L4D1 only) -// L4D1 = 31 [left4downtown] + 47 [l4d_direct] + 16 [l4d2addresses] + 66 [silvers - mine!] + 4 [anim] = 165 -// L4D2 = 61 [left4downtown] + 59 [l4d_direct] + 31 [l4d2addresses] + 110 [silvers - mine!] + 4 [anim] = 265 +// Natives: 257 (including 3 for L4D1 only) +// L4D1 = 31 [left4downtown] + 47 [l4d_direct] + 16 [l4d2addresses] + 67 [silvers - mine!] + 4 [anim] = 166 +// L4D2 = 61 [left4downtown] + 59 [l4d_direct] + 31 [l4d2addresses] + 111 [silvers - mine!] + 4 [anim] = 266 -// Forwards: 198 (including 5 for L4D1 only) +// Forwards: 201 (including 5 for L4D1 only) // L4D1 = 138 -// L4D2 = 193 +// L4D2 = 196 // Stocks: 169 (L4D1 = 114, L4D2 = 167) // left4dhooks_silver 46 stocks (L4D1 = 39, L4D2 = 53) @@ -141,6 +143,7 @@ public void __pl_l4dh_SetNTVOptional() MarkNativeAsOptional("L4D_ReadMemoryString"); MarkNativeAsOptional("L4D_GetServerOS"); MarkNativeAsOptional("Left4DHooks_Version"); + MarkNativeAsOptional("L4D_HasMapStarted"); MarkNativeAsOptional("L4D2_GetScriptScope"); MarkNativeAsOptional("L4D2_GetVScriptEntity"); MarkNativeAsOptional("L4D2_ExecVScriptCode"); @@ -392,6 +395,66 @@ public void __pl_l4dh_SetNTVOptional() MarkNativeAsOptional("L4D2_HideVersusScoreboard"); MarkNativeAsOptional("L4D2_HideScavengeScoreboard"); MarkNativeAsOptional("L4D2_HideScoreboard"); + + PlayerAnimState_MarkNativeAsOptional(); +} + +// ANIMATION NATIVES +void PlayerAnimState_MarkNativeAsOptional() +{ + MarkNativeAsOptional("PlayerAnimState.FromPlayer"); + MarkNativeAsOptional("PlayerAnimState.GetMainActivity"); + MarkNativeAsOptional("PlayerAnimState.ResetMainActivity"); + MarkNativeAsOptional("PlayerAnimState.m_bIsCustomSequence.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsCustomSequence.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsDead.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsDead.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsHealing.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsHealing.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsResurrection.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsResurrection.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsHitByCharger.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsHitByCharger.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPummeled.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPummeled.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsSlammedIntoWall.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsSlammedIntoWall.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsSlammedIntoGround.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsSlammedIntoGround.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsStartPummel.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsStartPummel.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPounded.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPounded.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsCarriedByCharger.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsCarriedByCharger.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPunchedByTank.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPunchedByTank.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsSpitting.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsSpitting.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPouncedOn.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPouncedOn.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTongueAttacked.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTongueAttacked.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsStartChainsaw.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsStartChainsaw.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsIsPouncing.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsIsPouncing.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsRiding.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsRiding.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsJockeyRidden.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsJockeyRidden.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTonguing.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTonguing.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsCharging.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsCharging.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPummeling.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPummeling.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPounding.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsPounding.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTongueReelingIn.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTongueReelingIn.set"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTongueAttacking.get"); + MarkNativeAsOptional("PlayerAnimState.m_bIsTongueAttacking.set"); } #endif @@ -399,6 +462,126 @@ public void __pl_l4dh_SetNTVOptional() +// ==================================================================================================== +// ANIMATION NATIVES +// ==================================================================================================== +methodmap PlayerAnimState { + // Get the PlayerAnimState instance of a player. + public static native PlayerAnimState FromPlayer(int client); + + // Main activity of player's animation, matching enums in "left4dhooks_anim.inc". + public native int GetMainActivity(); + + // Restart and recalculate the main activity. + public native void ResetMainActivity(); + + // All booleans (or flags) that used for animation events. + property bool m_bIsCustomSequence { // True only after "CTerrorPlayerAnimState::SetCustomSequence". + public native get(); + public native set(bool value); + } + property bool m_bIsDead { + public native get(); + public native set(bool value); + } + property bool m_bIsHealing { + public native get(); + public native set(bool value); + } + property bool m_bIsResurrection { + public native get(); + public native set(bool value); + } + property bool m_bIsHitByCharger { // aka multi-charged, bowling. + public native get(); + public native set(bool value); + } + property bool m_bIsPummeled { + public native get(); + public native set(bool value); + } + property bool m_bIsSlammedIntoWall { + public native get(); + public native set(bool value); + } + property bool m_bIsSlammedIntoGround { + public native get(); + public native set(bool value); + } + property bool m_bIsStartPummel { // Something to do with charger pummel animation, not sure about the name. + public native get(); + public native set(bool value); + } + property bool m_bIsPounded { // Pummel get-up + public native get(); + public native set(bool value); + } + property bool m_bIsCarriedByCharger { + public native get(); + public native set(bool value); + } + property bool m_bIsPunchedByTank { // Rock get-up shares this + public native get(); + public native set(bool value); + } + property bool m_bIsSpitting { + public native get(); + public native set(bool value); + } + property bool m_bIsPouncedOn { + public native get(); + public native set(bool value); + } + property bool m_bIsTongueAttacked { + public native get(); + public native set(bool value); + } + property bool m_bIsStartChainsaw { + public native get(); + public native set(bool value); + } + property bool m_bIsIsPouncing { + public native get(); + public native set(bool value); + } + property bool m_bIsRiding { + public native get(); + public native set(bool value); + } + property bool m_bIsJockeyRidden { + public native get(); + public native set(bool value); + } + property bool m_bIsTonguing { + public native get(); + public native set(bool value); + } + property bool m_bIsCharging { + public native get(); + public native set(bool value); + } + property bool m_bIsPummeling { + public native get(); + public native set(bool value); + } + property bool m_bIsPounding { + public native get(); + public native set(bool value); + } + property bool m_bIsTongueReelingIn { + public native get(); + public native set(bool value); + } + property bool m_bIsTongueAttacking { + public native get(); + public native set(bool value); + } +} + + + + + // ==================================================================================================== // VARIOUS ENUMS // ==================================================================================================== @@ -562,6 +745,7 @@ enum // Some constants from 'l4d2util_contants.inc' // These are used by the "L4D2Direct_DoAnimationEvent" native and "L4D_OnDoAnimationEvent*" forwards // L4D1 seems to only have 35 animation events, the names may not be relative to those listed here +// For L4D1: See below the enum. enum PlayerAnimEvent_t { // Made by A1m` @@ -574,9 +758,7 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_RELOAD_END = 6, //CMultiPlayerAnimState::DoAnimationEvent, CBaseShotgun::CheckReload->PlayReloadAnim, CTerrorGun::AbortReload PLAYERANIMEVENT_JUMP = 7, // CMultiPlayerAnimState::DoAnimationEvent, CTerrorGameMovement::DoJump, CCSGameMovement::CheckJumpButton PLAYERANIMEVENT_LAND = 8, // CTerrorGameMovement::PlayerRoughLandingEffects - PLAYERANIMEVENT_SWIM = 9, // Not sure, not used in the game anyway - PLAYERANIMEVENT_DIE = 10, // CMultiPlayerAnimState::DoAnimationEvent, CTerrorPlayer::StartSurvivorDeathAnim, CTerrorPlayer::OnIncapacitatedAsTank PLAYERANIMEVENT_FLINCH_CHEST = 11, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_FLINCH_HEAD = 12, // CMultiPlayerAnimState::DoAnimationEvent @@ -584,19 +766,14 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_FLINCH_RIGHTARM = 14, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_FLINCH_LEFTLEG = 15, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_FLINCH_RIGHTLEG = 16, // CMultiPlayerAnimState::DoAnimationEvent - PLAYERANIMEVENT_DOUBLEJUMP = 17, // Not sure, not used in the game anyway - PLAYERANIMEVENT_CANCEL_GESTURE_ATTACK_AND_RELOAD = 18, // CTerrorPlayer::OnShovedByPounceLanding, CTerrorPlayer::OnShovedBySurvivor, CTerrorPlayer::OnRideEnded, CTerrorPlayer::OnPounceEnded - PLAYERANIMEVENT_CANCEL = 19, // Not sure, not used in the game anyway - PLAYERANIMEVENT_SPAWN = 20, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_SNAP_YAW = 21, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_CUSTOM = 22, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_CUSTOM_GESTURE = 23, // CMultiPlayerAnimState::DoAnimationEvent PLAYERANIMEVENT_CUSTOM_SEQUENCE = 24, // CMultiPlayerAnimState::DoAnimationEvent - PLAYERANIMEVENT_CUSTOM_GESTURE_SEQUENCE = 25, // Not sure, not used in the game anyway // TF Specific. Here until there's a derived game solution to this @@ -607,7 +784,6 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_GRENADE1_THROW = 30, // Not sure, not used in the game anyway PLAYERANIMEVENT_GRENADE2_THROW = 31, // Not sure, not used in the game anyway PLAYERANIMEVENT_VOICE_COMMAND_GESTURE = 32, // Not sure, not used in the game?. CTerrorPlayerAnimState::DoAnimationEvent - PLAYERANIMEVENT_HAND_ATTACK = 33, // CClaw::OnSwingStart, CTerrorPlayer::UpdateTankEffects, CTankClaw::OnSwingStart PLAYERANIMEVENT_HAND_LOW_ATTACK = 34, // CTankClaw::OnSwingStart, CTerrorWeapon::OnSwingStart PLAYERANIMEVENT_SHOVE_COMMON = 35, // CTerrorWeapon::OnSwingStart @@ -635,17 +811,13 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_FLINCH_EVENT_SHOVED_BY_TEAMMATE = 57, // CTerrorPlayer::OnTakeDamageInternal->GetFlinchEvent, CTerrorPlayer::OnTakeDamage_Alive->GetFlinchEvent, CTerrorWeapon::OnHit->GetFlinchEvent PLAYERANIMEVENT_FLINCH_EVENT_TAKE_DAMAGE = 58, // CTerrorPlayer::GetFlinchEvent PLAYERANIMEVENT_THROW_ITEM_START = 59, // CBaseCSGrenade::PrimaryAttack - PLAYERANIMEVENT_ROLL_GRENADE = 60, // Not sure, not used in the game anyway - PLAYERANIMEVENT_THROW_ITEM_FINISH = 61, // CBaseCSGrenade::ItemPostFrame PLAYERANIMEVENT_THROW_GRENADE = 62, // CCSPlayer::DoAnimationEvent PLAYERANIMEVENT_THROW_ITEM_HOLSTER = 63, // CBaseCSGrenade::Holster PLAYERANIMEVENT_PLAYER_USE = 64, // CTerrorPlayer::OnUseEntity PLAYERANIMEVENT_CHANGE_SLOT = 65, // CWeaponCSBase::DefaultDeploy - PLAYERANIMEVENT_UNKNOWN_START_GESTURE = 66, // Don't know. Not used in the game? Something like option 32? CTerrorPlayerAnimState::DoAnimationEvent - PLAYERANIMEVENT_TUG_HANGING_PLAYER = 67, // CTerrorPlayer::StartTug PLAYERANIMEVENT_STUMBLE = 68, // CTerrorPlayer::UpdateStagger, CTerrorPlayer::OnShovedByPounceLanding, CTerrorPlayer::OnStaggered, CTerrorPlayer::UpdateStagger, CTerrorPlayer::OnShovedBySurvivor PLAYERANIMEVENT_POUNCE_VICTIM_END = 69, @@ -682,6 +854,35 @@ enum PlayerAnimEvent_t PLAYERANIMEVENT_COUNT // Total size 99. Function 'CTerrorPlayer::DoAnimationEvent' }; +// L4D1 anim values appear to be related to these below. Thanks to "Dragokas" for gathering a list of them: +/* +1 - Primary Attack +2 - Unused +3 - Aiming +4 - Reload Reserved Ammo +5 - Chambering Of A Cartridge (No Sound) +6 - Chambering Of A Cartridge (With Sound) +7 - Shotgun Reload (With Sound) +8 - Shotgun Reload (No Sound) +9 - Shove (Side) +10 - Shove (Forward) +11 - Shove (Right Arm) +12 - Stomp +13 - Heal Myself +14 - Heal Teammate1 +15 - Pick Up Incapped Player +16 - Heal Teammate2 +21 - Headbutt +22 - Headbutt2 +23 - Pick Up Item From Ground +24 - Take Item From Teammate +25 - Change Weapon +26 - Weapon Reload Fast +27 - Weapon Recoil + Reload +28 - Weapon Recoil + Reload (same) +29... - Seems unused (Same for 2, 17-20). +*/ + @@ -698,7 +899,7 @@ typeset AnimHookCallback * @param client Client triggering * @param sequence The animation "activity" (pre-hook) or "m_nSequence" (post-hook) sequence number being used * - * @return Plugin_Changed to change animation, Plugin_Continue otherwise + * @return Plugin_Changed to change the animation sequence, Plugin_Continue otherwise */ function Action(int client, int &sequence); } @@ -1995,39 +2196,6 @@ forward void L4D2_OnEndVersusModeRound_Post(); */ forward void L4D2_OnEndVersusModeRound_PostHandled(); -/** - * @brief Called whenever CDirector::EndScenario(ScenarioRestartReason) [clone] is invoked - * @remarks Called before when a round is about to end - * - * @param reason The reason for ending, please provide a list of known reason numbers - * - * @return Plugin_Handled to block, Plugin_Continue otherwise - */ - -#pragma deprecated This is for private testing and not released for public usage yet -forward Action L4D_OnEndScenario(int reason); - -/** - * @brief Called whenever CDirector::EndScenario(ScenarioRestartReason) [clone] is invoked - * @remarks This forward will not trigger if the relative pre-hook forward has been blocked with Plugin_Handled - * - * @param reason The reason for ending, please provide a list of known reason numbers - * - * @noreturn - */ -#pragma deprecated This is for private testing and not released for public usage yet -forward void L4D_OnEndScenario_Post(int reason); - -/** - * @brief Called whenever CDirector::EndScenario(ScenarioRestartReason) [clone] is invoked - * @remarks This forward will ONLY trigger if the relative pre-hook forward has been blocked with Plugin_Handled - * - * @param reason The reason for ending, please provide a list of known reason numbers - * - * @noreturn - */ -#pragma deprecated This is for private testing and not released for public usage yet -forward void L4D_OnEndScenario_PostHandled(int reason); /** * @brief Called whenever CTerrorPlayer::OnLedgeGrabbed(CTerrorPlayer *this, const Vector *) is invoked @@ -2841,6 +3009,41 @@ forward void L4D2_OnHitByVomitJar_Post(int victim, int attacker); */ forward void L4D2_OnHitByVomitJar_PostHandled(int victim, int attacker); +/** + * @brief Called whenever Infected::OnHitByVomitJar is invoked + * @remarks Called when a common infected or Witch is about to be hit from a Bilejar explosion and possibly boomer explosion + * + * @param victim the common who's now it + * @param attacker the attacker who caused the vomit (can be 0) + * + * @return Plugin_Handled to block, Plugin_Changed to use overwritten values from plugin, Plugin_Continue otherwise + */ +forward Action L4D2_Infected_HitByVomitJar(int victim, int &attacker); + +/** + * @brief Called whenever Infected::OnHitByVomitJar is invoked + * @remarks Called when a common infected or Witch is hit from a Bilejar explosion and possibly boomer explosion + * @remarks This forward will not trigger if the relative pre-hook forward has been blocked with Plugin_Handled + * + * @param victim the common who's now it + * @param attacker the attacker who caused the vomit (can be 0) + * + * @noreturn + */ +forward void L4D2_Infected_HitByVomitJar_Post(int victim, int attacker); + +/** + * @brief Called whenever Infected::OnHitByVomitJar is invoked + * @remarks Called when a common infected or Witch is hit from a Bilejar explosion and possibly boomer explosion + * @remarks This forward will ONLY trigger if the relative pre-hook forward has been blocked with Plugin_Handled + * + * @param victim the common who's now it + * @param attacker the attacker who caused the vomit (can be 0) + * + * @noreturn + */ +forward void L4D2_Infected_HitByVomitJar_PostHandled(int victim, int attacker); + /** * @brief Called whenever CPipeBombProjectile::Create is invoked * @remarks Called when a PipeBomb projectile is being created @@ -3054,6 +3257,7 @@ forward void L4D_CBreakableProp_Break(int prop, int entity); * @note: Detouring as a pre-hook for changing "first_aid_heal_percent" per player before healing finishes * @note: Detouring as a post-hook for changing "first_aid_heal_percent" back to default value after healing finishes * @note: This does not change the animation speed + * @note: To find the use entity that is being targeted, use the native: "L4D_FindUseEntity" * * @param client the client performing the action * @param entity the medkit entity they are using @@ -3069,6 +3273,7 @@ forward Action L4D1_FirstAidKit_StartHealing(int client, int entity); * @note: Detouring as a pre-hook for changing "first_aid_heal_percent" per player before healing finishes * @note: Detouring as a post-hook for changing "first_aid_heal_percent" back to default value after healing finishes * @note: This does not change the animation speed + * @note: To find the use entity that is being targeted, use the native: "L4D_FindUseEntity" * * @param client the client performing the action * @param entity the medkit entity they are using @@ -3084,6 +3289,7 @@ forward void L4D1_FirstAidKit_StartHealing_Post(int client, int entity); * @note: Detouring as a pre-hook for changing "first_aid_heal_percent" per player before healing finishes * @note: Detouring as a post-hook for changing "first_aid_heal_percent" back to default value after healing finishes * @note: This does not change the animation speed + * @note: To find the use entity that is being targeted, use the native: "L4D_FindUseEntity" * * @param client the client performing the action * @param entity the medkit entity they are using @@ -3105,6 +3311,7 @@ forward void L4D1_FirstAidKit_StartHealing_PostHandled(int client, int entity); * - "gas_can_use_duration" * - "upgrade_pack_use_duration" * @note: Detouring as a post-hook for changing the above back to default values after starting any actions + * @note: To find the use entity that is being targeted, use the native: "L4D_FindUseEntity" * * @param client the client performing the action * @param entity the medkit entity they are using @@ -3127,6 +3334,7 @@ forward Action L4D2_BackpackItem_StartAction(int client, int entity, any type); * - "gas_can_use_duration" * - "upgrade_pack_use_duration" * @note: Detouring as a post-hook for changing the above back to default values after starting any actions + * @note: To find the use entity that is being targeted, use the native: "L4D_FindUseEntity" * * @param client the client performing the action * @param entity the medkit entity they are using @@ -3149,6 +3357,7 @@ forward void L4D2_BackpackItem_StartAction_Post(int client, int entity, any type * - "gas_can_use_duration" * - "upgrade_pack_use_duration" * @note: Detouring as a post-hook for changing the above back to default values after starting any actions + * @note: To find the use entity that is being targeted, use the native: "L4D_FindUseEntity" * * @param client the client performing the action * @param entity the medkit entity they are using @@ -3413,6 +3622,13 @@ native int L4D_GetServerOS(); */ native int Left4DHooks_Version(); +/** + * @brief Checks if the map and addresses are loaded that some natives rely on + * + * @return True if the map has started and addresses are loaded, false otherwise + */ +native bool L4D_HasMapStarted(); + /** * @brief Returns an entities script scope (HSCRIPT) * diff --git a/addons/sourcemod/scripting/include/left4dhooks_anim.inc b/addons/sourcemod/scripting/include/left4dhooks_anim.inc index 776a50920..f7660acee 100644 --- a/addons/sourcemod/scripting/include/left4dhooks_anim.inc +++ b/addons/sourcemod/scripting/include/left4dhooks_anim.inc @@ -21,6 +21,8 @@ #endif #define _l4d_anim_included +#pragma newdecls required + #include #include diff --git a/addons/sourcemod/scripting/include/left4dhooks_lux_library.inc b/addons/sourcemod/scripting/include/left4dhooks_lux_library.inc index dea96be64..21d327bff 100644 --- a/addons/sourcemod/scripting/include/left4dhooks_lux_library.inc +++ b/addons/sourcemod/scripting/include/left4dhooks_lux_library.inc @@ -20,6 +20,8 @@ #endif #define _lux_library_included +#pragma newdecls required + #include #include @@ -27,7 +29,7 @@ #tryinclude #tryinclude -#define LUX_LIBRARY_VERSION "0.5.7" +#define LUX_LIBRARY_VERSION "0.5.8" #define GIMMEDATA "lux_library" @@ -1434,10 +1436,10 @@ stock void EmitMixedAmbientSound(int client, const char[] sample, if(flDistMulti > 1.0) { - newPitch = FloatToInt(newPitch / (flDistMulti > 2.0 ? 2.0 : flDistMulti)); + newPitch = RoundToNearest(newPitch / (flDistMulti > 2.0 ? 2.0 : flDistMulti)); } - DistLevelBoost = FloatToInt((flDistPercent * exponent) * levelBoost); + DistLevelBoost = RoundToNearest((flDistPercent * exponent) * levelBoost); if(DistLevelBoost > levelBoost) DistLevelBoost = levelBoost; @@ -1518,21 +1520,16 @@ stock void EmitMixedAmbientSound_FallBack(int client, const char[] sample, newPitch = pitch; if(flDistMulti > 1.0) { - newPitch = FloatToInt(newPitch / (flDistMulti > 2.0 ? 2.0 : flDistMulti)); + newPitch = RoundToNearest(newPitch / (flDistMulti > 2.0 ? 2.0 : flDistMulti)); } - DistLevelBoost = FloatToInt((flDistPercent * exponent) * levelBoost); + DistLevelBoost = RoundToNearest((flDistPercent * exponent) * levelBoost); if(DistLevelBoost > levelBoost) DistLevelBoost = levelBoost; EmitSoundToClient(client, sample, entity, sndChannel, level + DistLevelBoost, _, _, newPitch, _, origin); } -int FloatToInt(float val) -{ - return RoundFloat(val); -} - ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////Legacy Particle Stock/////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/addons/sourcemod/scripting/include/left4dhooks_silver.inc b/addons/sourcemod/scripting/include/left4dhooks_silver.inc index 49a46ea8a..018a8d5f7 100644 --- a/addons/sourcemod/scripting/include/left4dhooks_silver.inc +++ b/addons/sourcemod/scripting/include/left4dhooks_silver.inc @@ -21,6 +21,8 @@ #endif #define _l4d_silver_included +#pragma newdecls required + #include #include diff --git a/addons/sourcemod/scripting/include/left4dhooks_stocks.inc b/addons/sourcemod/scripting/include/left4dhooks_stocks.inc index 75be97c9f..3bf460328 100644 --- a/addons/sourcemod/scripting/include/left4dhooks_stocks.inc +++ b/addons/sourcemod/scripting/include/left4dhooks_stocks.inc @@ -32,6 +32,8 @@ #endif #define _l4d_stocks_included +#pragma newdecls required + #tryinclude #tryinclude #tryinclude @@ -665,7 +667,7 @@ stock int L4D_GetPendingTankPlayer() * @return True if glow was set, false if entity does not support glow. */ // L4D2 only. -stock bool L4D2_SetEntityGlow(int entity, L4D2GlowType type, int range, int minRange, colorOverride[3], bool flashing) +stock bool L4D2_SetEntityGlow(int entity, L4D2GlowType type, int range, int minRange, int colorOverride[3], bool flashing) { if (!IsValidEntity(entity)) { diff --git a/addons/sourcemod/scripting/l4dd/l4dd_forwards.sp b/addons/sourcemod/scripting/l4dd/l4dd_forwards.sp index 20675f096..a7d076c89 100644 --- a/addons/sourcemod/scripting/l4dd/l4dd_forwards.sp +++ b/addons/sourcemod/scripting/l4dd/l4dd_forwards.sp @@ -125,9 +125,6 @@ GlobalForward g_hFWD_CDirectorScriptedEventManager_ChangeFinaleStage_PostPost; GlobalForward g_hFWD_CDirectorVersusMode_EndVersusModeRound_Pre; GlobalForward g_hFWD_CDirectorVersusMode_EndVersusModeRound_Post; GlobalForward g_hFWD_CDirectorVersusMode_EndVersusModeRound_PostHandled; -// GlobalForward g_hFWD_CDirector_EndScenario_Pre; -// GlobalForward g_hFWD_CDirector_EndScenario_Post; -// GlobalForward g_hFWD_CDirector_EndScenario_PostHandled; GlobalForward g_hFWD_CBaseAnimating_SelectWeightedSequence_Pre; GlobalForward g_hFWD_CBaseAnimating_SelectWeightedSequence_Post; GlobalForward g_hFWD_CTerrorPlayer_DoAnimationEvent; @@ -150,6 +147,9 @@ GlobalForward g_hFWD_CTerrorPlayer_OnVomitedUpon_PostHandled; GlobalForward g_hFWD_CTerrorPlayer_OnHitByVomitJar; GlobalForward g_hFWD_CTerrorPlayer_OnHitByVomitJar_Post; GlobalForward g_hFWD_CTerrorPlayer_OnHitByVomitJar_PostHandled; +GlobalForward g_hFWD_Infected_OnHitByVomitJar; +GlobalForward g_hFWD_Infected_OnHitByVomitJar_Post; +GlobalForward g_hFWD_Infected_OnHitByVomitJar_PostHandled; GlobalForward g_hFWD_CBreakableProp_Break_Post; GlobalForward g_hFWD_CGasCanEvent_Killed; GlobalForward g_hFWD_CGasCanEvent_Killed_Post; @@ -307,14 +307,6 @@ void SetupDetours(GameData hGameData = null) CreateDetour(hGameData, DTR_CTerrorPlayer_RecalculateVersusScore, DTR_CTerrorPlayer_RecalculateVersusScore_Post, "L4DD::CTerrorPlayer::RecalculateVersusScore", "L4D_OnRecalculateVersusScore"); CreateDetour(hGameData, DTR_CTerrorPlayer_RecalculateVersusScore, DTR_CTerrorPlayer_RecalculateVersusScore_Post, "L4DD::CTerrorPlayer::RecalculateVersusScore", "L4D_OnRecalculateVersusScore_Post", true); } -/* - else - { - CreateDetour(hGameData, DTR_CDirector_EndScenario_Pre, DTR_CDirector_EndScenario_Post, "L4DD::CDirector::EndScenario", "L4D_OnEndScenario"); - CreateDetour(hGameData, DTR_CDirector_EndScenario_Pre, DTR_CDirector_EndScenario_Post, "L4DD::CDirector::EndScenario", "L4D_OnEndScenario_Post", true); - CreateDetour(hGameData, DTR_CDirector_EndScenario_Pre, DTR_CDirector_EndScenario_Post, "L4DD::CDirector::EndScenario", "L4D_OnEndScenario_PostHandled", true); - } -*/ CreateDetour(hGameData, DTR_CDirector_OnFirstSurvivorLeftSafeArea, DTR_CDirector_OnFirstSurvivorLeftSafeArea_Post, "L4DD::CDirector::OnFirstSurvivorLeftSafeArea", "L4D_OnFirstSurvivorLeftSafeArea"); CreateDetour(hGameData, DTR_CDirector_OnFirstSurvivorLeftSafeArea, DTR_CDirector_OnFirstSurvivorLeftSafeArea_Post, "L4DD::CDirector::OnFirstSurvivorLeftSafeArea", "L4D_OnFirstSurvivorLeftSafeArea_Post", true); @@ -332,7 +324,7 @@ void SetupDetours(GameData hGameData = null) CreateDetour(hGameData, DTR_CDirectorVersusMode_GetMissionVersusBossSpawning, DTR_CDirectorVersusMode_GetMissionVersusBossSpawning_Post, "L4DD::CDirectorVersusMode::GetMissionVersusBossSpawning", "L4D_OnGetMissionVSBossSpawning_PostHandled", true); 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_Post3", true); + CreateDetour(hGameData, DTR_CTankClaw_DoSwing_Pre, DTR_CTankClaw_DoSwing_Post, "L4DD::CTankClaw::DoSwing", "L4D_TankClaw_DoSwing_Post", true); 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); CreateDetour(hGameData, DTR_CTankClaw_OnPlayerHit_Pre, DTR_CTankClaw_OnPlayerHit_Post, "L4DD::CTankClaw::OnPlayerHit", "L4D_TankClaw_OnPlayerHit_Pre"); @@ -484,6 +476,9 @@ void SetupDetours(GameData hGameData = null) CreateDetour(hGameData, DTR_CGasCanEvent_Killed, DTR_CGasCanEvent_Killed_Post, "L4DD::CGasCan::Event_Killed", "L4D2_CGasCan_EventKilled"); CreateDetour(hGameData, DTR_CGasCanEvent_Killed, DTR_CGasCanEvent_Killed_Post, "L4DD::CGasCan::Event_Killed", "L4D2_CGasCan_EventKilled_Post", true); CreateDetour(hGameData, DTR_CGasCanEvent_Killed, DTR_CGasCanEvent_Killed_Post, "L4DD::CGasCan::Event_Killed", "L4D2_CGasCan_EventKilled_PostHandled", true); + CreateDetour(hGameData, DTR_CPhysicsProp_OnTakeDamage, DTR_CPhysicsProp_OnTakeDamage_Post, "L4DD::CPhysicsProp::OnTakeDamage", "L4D2_CGasCan_EventKilled"); + CreateDetour(hGameData, DTR_CPhysicsProp_OnTakeDamage, DTR_CPhysicsProp_OnTakeDamage_Post, "L4DD::CPhysicsProp::OnTakeDamage", "L4D2_CGasCan_EventKilled_Post", true); + CreateDetour(hGameData, DTR_CPhysicsProp_OnTakeDamage, DTR_CPhysicsProp_OnTakeDamage_Post, "L4DD::CPhysicsProp::OnTakeDamage", "L4D2_CGasCan_EventKilled_PostHandled", true); CreateDetour(hGameData, DTR_CGasCan_ShouldStartAction, DTR_CGasCan_ShouldStartAction_Post, "L4DD::CGasCan::ShouldStartAction", "L4D2_CGasCan_ShouldStartAction"); CreateDetour(hGameData, DTR_CGasCan_ShouldStartAction, DTR_CGasCan_ShouldStartAction_Post, "L4DD::CGasCan::ShouldStartAction", "L4D2_CGasCan_ShouldStartAction_Post", true); CreateDetour(hGameData, DTR_CGasCan_ShouldStartAction, DTR_CGasCan_ShouldStartAction_Post, "L4DD::CGasCan::ShouldStartAction", "L4D2_CGasCan_ShouldStartAction_PostHandled", true); @@ -514,6 +509,9 @@ void SetupDetours(GameData hGameData = null) CreateDetour(hGameData, DTR_CTerrorPlayer_OnHitByVomitJar, DTR_CTerrorPlayer_OnHitByVomitJar_Post, "L4DD::CTerrorPlayer::OnHitByVomitJar", "L4D2_OnHitByVomitJar"); CreateDetour(hGameData, DTR_CTerrorPlayer_OnHitByVomitJar, DTR_CTerrorPlayer_OnHitByVomitJar_Post, "L4DD::CTerrorPlayer::OnHitByVomitJar", "L4D2_OnHitByVomitJar_Post", true); CreateDetour(hGameData, DTR_CTerrorPlayer_OnHitByVomitJar, DTR_CTerrorPlayer_OnHitByVomitJar_Post, "L4DD::CTerrorPlayer::OnHitByVomitJar", "L4D2_OnHitByVomitJar_PostHandled", true); + CreateDetour(hGameData, DTR_Infected_OnHitByVomitJar, DTR_Infected_OnHitByVomitJar_Post, "L4DD::Infected::OnHitByVomitJar", "L4D2_Infected_HitByVomitJar"); + CreateDetour(hGameData, DTR_Infected_OnHitByVomitJar, DTR_Infected_OnHitByVomitJar_Post, "L4DD::Infected::OnHitByVomitJar", "L4D2_Infected_HitByVomitJar_Post", true); + CreateDetour(hGameData, DTR_Infected_OnHitByVomitJar, DTR_Infected_OnHitByVomitJar_Post, "L4DD::Infected::OnHitByVomitJar", "L4D2_Infected_HitByVomitJar_PostHandled", true); CreateDetour(hGameData, DTR_ZombieManager_SpawnWitchBride, DTR_ZombieManager_SpawnWitchBride_Post, "L4DD::ZombieManager::SpawnWitchBride", "L4D2_OnSpawnWitchBride"); CreateDetour(hGameData, DTR_ZombieManager_SpawnWitchBride, DTR_ZombieManager_SpawnWitchBride_Post, "L4DD::ZombieManager::SpawnWitchBride", "L4D2_OnSpawnWitchBride_Post", true); CreateDetour(hGameData, DTR_ZombieManager_SpawnWitchBride, DTR_ZombieManager_SpawnWitchBride_Post, "L4DD::ZombieManager::SpawnWitchBride", "L4D2_OnSpawnWitchBride_PostHandled", true); @@ -2630,48 +2628,6 @@ MRESReturn DTR_CDirectorVersusMode_EndVersusModeRound_Post(DHookReturn hReturn, return MRES_Ignored; } -/* -bool g_bBlock_CDirector_EndScenario; -MRESReturn DTR_CDirector_EndScenario_Pre(int pThis, DHookParam hParams) // Forward "L4D_OnEndScenario" -{ - //PrintToServer("##### DTR_CDirector_EndScenario_Pre"); - if( g_bRoundEnded ) return MRES_Ignored; - - int a1 = hParams.Get(1); - - Action aResult = Plugin_Continue; - Call_StartForward(g_hFWD_CDirector_EndScenario_Pre); - Call_PushCell(a1); - Call_Finish(aResult); - - if( aResult == Plugin_Handled ) - { - g_bBlock_CDirector_EndScenario = true; - - return MRES_Supercede; - } - - g_bBlock_CDirector_EndScenario = false; - - return MRES_Ignored; -} - -MRESReturn DTR_CDirector_EndScenario_Post(int pThis, DHookParam hParams) // Forward "L4D_OnEndScenario_Post" and "L4D_OnEndScenario_PostHandled" -{ - //PrintToServer("##### DTR_CDirector_EndScenario_Post"); - if( g_bRoundEnded ) return MRES_Ignored; - g_bRoundEnded = true; - - int a1 = hParams.Get(1); - - Call_StartForward(g_bBlock_CDirector_EndScenario ? g_hFWD_CDirector_EndScenario_PostHandled : g_hFWD_CDirector_EndScenario_Post); - Call_PushCell(a1); - Call_Finish(); - - return MRES_Ignored; -} -*/ - bool g_bBlock_CTerrorPlayer_OnLedgeGrabbed; MRESReturn DTR_CTerrorPlayer_OnLedgeGrabbed(int pThis, DHookReturn hReturn, DHookParam hParams) // Forward "L4D_OnLedgeGrabbed" { @@ -3024,7 +2980,7 @@ MRESReturn DTR_CTerrorWeapon_OnHit_Post(int weapon, DHookReturn hReturn, DHookPa } bool g_bBlock_CTerrorPlayer_OnShovedByPounceLanding; -MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding(int pThis, DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_OnPounceOrLeapStumble" +MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding(int pThis, DHookParam hParams) // Forward "L4D2_OnPounceOrLeapStumble" { //PrintToServer("##### DTR_CTerrorPlayer_OnShovedByPounceLanding"); int a1 = hParams.Get(1); @@ -3039,7 +2995,6 @@ MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding(int pThis, DHookReturn hRet { g_bBlock_CTerrorPlayer_OnShovedByPounceLanding = true; - hReturn.Value = 0.0; return MRES_Supercede; } @@ -3048,7 +3003,7 @@ MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding(int pThis, DHookReturn hRet return MRES_Ignored; } -MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding_Post(int pThis, DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_OnPounceOrLeapStumble_Post" and "L4D2_OnPounceOrLeapStumble_PostHandled" +MRESReturn DTR_CTerrorPlayer_OnShovedByPounceLanding_Post(int pThis, DHookParam hParams) // Forward "L4D2_OnPounceOrLeapStumble_Post" and "L4D2_OnPounceOrLeapStumble_PostHandled" { //PrintToServer("##### DTR_CTerrorPlayer_OnShovedByPounceLanding_Post"); int a1 = hParams.Get(1); @@ -3964,6 +3919,60 @@ MRESReturn DTR_CGasCanEvent_Killed_Post(int pThis, DHookReturn hReturn, DHookPar return MRES_Ignored; } +MRESReturn DTR_CPhysicsProp_OnTakeDamage(int pThis, DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_CGasCan_EventKilled" +{ + if( GetEntProp(pThis, Prop_Data, "m_nModelIndex") != g_iGasCanModel ) return MRES_Ignored; // Verify "weapon_gascan" type + + //PrintToServer("##### DTR_CPhysicsProp_OnTakeDamage"); + + int a1 = hParams.GetObjectVar(1, 48, ObjectValueType_EhandlePtr); + int a2 = hParams.GetObjectVar(1, 52, ObjectValueType_EhandlePtr); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_CGasCanEvent_Killed); + Call_PushCell(pThis); + Call_PushCellRef(a1); + Call_PushCellRef(a2); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + g_bBlock_CGasCanEvent_Killed = true; + + hReturn.Value = 0; + return MRES_Supercede; + } + + if( aResult == Plugin_Changed ) + { + hParams.SetObjectVar(1, 48, ObjectValueType_EhandlePtr, a1); + hParams.SetObjectVar(1, 52, ObjectValueType_EhandlePtr, a2); + return MRES_ChangedHandled; + } + + g_bBlock_CGasCanEvent_Killed = false; + + return MRES_Ignored; +} + +MRESReturn DTR_CPhysicsProp_OnTakeDamage_Post(int pThis, DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_CGasCan_EventKilled_Post" and "L4D2_CGasCan_EventKilled_PostHandled" +{ + if( GetEntProp(pThis, Prop_Data, "m_nModelIndex") != g_iGasCanModel ) return MRES_Ignored; // Verify "weapon_gascan" type + + //PrintToServer("##### DTR_CPhysicsProp_OnTakeDamage"); + + int a1 = hParams.GetObjectVar(1, 48, ObjectValueType_EhandlePtr); + int a2 = hParams.GetObjectVar(1, 52, ObjectValueType_EhandlePtr); + + Call_StartForward(g_bBlock_CGasCanEvent_Killed ? g_hFWD_CGasCanEvent_Killed_PostHandled : g_hFWD_CGasCanEvent_Killed_Post); + Call_PushCell(pThis); + Call_PushCell(a1); + Call_PushCell(a2); + Call_Finish(); + + return MRES_Ignored; +} + bool g_bBlock_CGasCan_ShouldStartAction; MRESReturn DTR_CGasCan_ShouldStartAction(DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_CGasCan_ShouldStartAction" { @@ -4599,6 +4608,58 @@ MRESReturn DTR_CTerrorPlayer_OnHitByVomitJar_Post(int client, DHookReturn hRetur return MRES_Ignored; } +bool g_bBlock_Infected_OnHitByVomitJar; +MRESReturn DTR_Infected_OnHitByVomitJar(int client, DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_Infected_HitByVomitJar" +{ + //PrintToServer("##### DTR_Infected_OnHitByVomitJar"); + + int a1; + + if( !hParams.IsNull(1) ) + a1 = hParams.Get(1); + + Action aResult = Plugin_Continue; + Call_StartForward(g_hFWD_Infected_OnHitByVomitJar); + Call_PushCell(client); + Call_PushCellRef(a1); + Call_Finish(aResult); + + if( aResult == Plugin_Handled ) + { + g_bBlock_Infected_OnHitByVomitJar = true; + + hReturn.Value = 0; + return MRES_Supercede; + } + + g_bBlock_Infected_OnHitByVomitJar = false; + + if( aResult == Plugin_Changed ) + { + hParams.Set(1, a1); + return MRES_ChangedHandled; + } + + return MRES_Ignored; +} + +MRESReturn DTR_Infected_OnHitByVomitJar_Post(int client, DHookReturn hReturn, DHookParam hParams) // Forward "L4D2_Infected_HitByVomitJar_Post" and "L4D2_Infected_HitByVomitJar_PostHandled" +{ + //PrintToServer("##### DTR_Infected_OnHitByVomitJar_Post"); + + int a1; + + if( !hParams.IsNull(1) ) + a1 = hParams.Get(1); + + Call_StartForward(g_bBlock_Infected_OnHitByVomitJar ? g_hFWD_Infected_OnHitByVomitJar_PostHandled : g_hFWD_Infected_OnHitByVomitJar_Post); + Call_PushCell(client); + Call_PushCell(a1); + Call_Finish(); + + return MRES_Ignored; +} + /* diff --git a/addons/sourcemod/scripting/l4dd/l4dd_gamedata.sp b/addons/sourcemod/scripting/l4dd/l4dd_gamedata.sp index 106a4bc02..a897d7165 100644 --- a/addons/sourcemod/scripting/l4dd/l4dd_gamedata.sp +++ b/addons/sourcemod/scripting/l4dd/l4dd_gamedata.sp @@ -126,6 +126,24 @@ void LoadGameData() + // ========================= + // ANIMATION NATIVES + // ========================= + if( g_bLeft4Dead2 ) + { + StartPrepSDKCall(SDKCall_Raw); + if( PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CMultiPlayerAnimState::ResetMainActivity") == false ) + { + LogError("Failed to find signature: \"CMultiPlayerAnimState::ResetMainActivity\" (%s)", g_sSystem); + } else { + g_hSDK_CMultiPlayerAnimState_ResetMainActivity = EndPrepSDKCall(); + if( g_hSDK_CMultiPlayerAnimState_ResetMainActivity == null ) + LogError("Failed to create SDKCall: \"CMultiPlayerAnimState::ResetMainActivity\" (%s)", g_sSystem); + } + } + + + // ========================= // SILVERS NATIVES // ========================= @@ -2079,13 +2097,28 @@ void LoadGameData() // ==================================================================================================== // OFFSETS // ==================================================================================================== - // Various #if defined DEBUG #if DEBUG PrintToServer("Various Offsets:"); #endif #endif + // Animation offsets + if( g_bLeft4Dead2 ) + { + g_iOff_m_PlayerAnimState = hGameData.GetOffset("CTerrorPlayer::m_PlayerAnimState"); + ValidateOffset(g_iOff_m_PlayerAnimState, "CTerrorPlayer::m_PlayerAnimState"); + + g_iOff_m_eCurrentMainSequenceActivity = hGameData.GetOffset("CMultiPlayerAnimState::m_eCurrentMainSequenceActivity"); + ValidateOffset(g_iOff_m_eCurrentMainSequenceActivity, "CMultiPlayerAnimState::m_eCurrentMainSequenceActivity"); + + g_iOff_m_bIsCustomSequence = hGameData.GetOffset("CTerrorPlayerAnimState::m_bIsCustomSequence"); + ValidateOffset(g_iOff_m_bIsCustomSequence, "CTerrorPlayerAnimState::m_bIsCustomSequence"); + } + + + + // Various offsets g_iOff_m_iCampaignScores = hGameData.GetOffset("m_iCampaignScores"); ValidateOffset(g_iOff_m_iCampaignScores, "m_iCampaignScores"); @@ -2340,6 +2373,10 @@ void LoadGameData() PrintToServer("m_preIncapacitatedHealthBuffer = %d", g_iOff_m_preIncapacitatedHealthBuffer); PrintToServer("m_maxFlames = %d", g_iOff_m_maxFlames); PrintToServer(""); + PrintToServer("g_iOff_m_PlayerAnimState = %d", g_iOff_m_PlayerAnimState); + PrintToServer("g_iOff_m_eCurrentMainSequenceActivity = %d", g_iOff_m_eCurrentMainSequenceActivity); + PrintToServer("g_iOff_m_bIsCustomSequence = %d", g_iOff_m_bIsCustomSequence); + PrintToServer(""); } #endif #endif diff --git a/addons/sourcemod/scripting/l4dd/l4dd_natives.sp b/addons/sourcemod/scripting/l4dd/l4dd_natives.sp index 71b64353e..2f41b85bf 100644 --- a/addons/sourcemod/scripting/l4dd/l4dd_natives.sp +++ b/addons/sourcemod/scripting/l4dd/l4dd_natives.sp @@ -114,6 +114,7 @@ Handle g_hSDK_ZombieManager_SpawnWitchBride; Handle g_hSDK_GetWeaponInfo; Handle g_hSDK_CMeleeWeaponInfoStore_GetMeleeWeaponInfo; Handle g_hSDK_CTerrorGameRules_GetMissionInfo; +Handle g_hSDK_CMultiPlayerAnimState_ResetMainActivity; Handle g_hSDK_CDirector_TryOfferingTankBot; Handle g_hSDK_CNavMesh_GetNavArea; Handle g_hSDK_CNavArea_IsConnected; @@ -266,6 +267,11 @@ int Native_Left4DHooks_Version(Handle plugin, int numParams) // Native "Left4DHo return PLUGIN_VERLONG; } +int Native_HasMapStarted(Handle plugin, int numParams) // Native "L4D_HasMapStarted" +{ + return g_bMapStarted; +} + // ================================================== @@ -1642,6 +1648,25 @@ int Native_CGrenadeLauncher_Projectile_Create(Handle plugin, int numParams) // N // return entity; } + + +// ==================================================================================================== +// Spitter acid projectile damage +// ==================================================================================================== +bool g_bAcidWatch; +int g_iAcidEntity[2048]; + +// Sounds are based on "PlayerZombie.AttackHit" from "game_sounds_infected_special.txt" +char g_sAcidSounds[6][] = +{ + "player/PZ/hit/zombie_slice_1.wav", + "player/PZ/hit/zombie_slice_2.wav", + "player/PZ/hit/zombie_slice_3.wav", + "player/PZ/hit/zombie_slice_4.wav", + "player/PZ/hit/zombie_slice_5.wav", + "player/PZ/hit/zombie_slice_6.wav" +}; + int Native_CSpitterProjectile_Create(Handle plugin, int numParams) // Native "L4D2_SpitterPrj" { if( !g_bLeft4Dead2 ) ThrowNativeError(SP_ERROR_NOT_RUNNABLE, NATIVE_UNSUPPORTED2); @@ -1657,14 +1682,20 @@ int Native_CSpitterProjectile_Create(Handle plugin, int numParams) // Native "L4 int entity = SDKCall(g_hSDK_CSpitterProjectile_Create, vPos, vAng, vAng, vAng, client); // SetEntPropFloat(entity, Prop_Data, "m_flCreateTime", GetGameTime()); + AcidDamageTest(client, entity); + + return entity; +} + +void AcidDamageTest(int client, int entity) +{ // Not watching for acid damage if( !g_bAcidWatch ) { // Verify client is not team 3, which causes sound bug - if( !client || GetClientTeam(client) != 3 ) + if( !client || GetClientTeam(client) != 3 || !IsClientInGame(client) ) { g_bAcidWatch = true; - g_iAcidEntity[entity] = EntIndexToEntRef(entity); // Hook clients damage for( int i = 1; i <= MaxClients; i++ ) @@ -1677,7 +1708,7 @@ int Native_CSpitterProjectile_Create(Handle plugin, int numParams) // Native "L4 } } - return entity; + g_iAcidEntity[entity] = EntIndexToEntRef(entity); } void OnAcidDamage(int victim, int attacker, int inflictor, float damage, int damagetype) @@ -1687,9 +1718,18 @@ void OnAcidDamage(int victim, int attacker, int inflictor, float damage, int dam { if( ((damagetype == (DMG_ENERGYBEAM|DMG_RADIATION) && attacker > 0 && attacker <= MaxClients && IsClientInGame(attacker) && GetClientTeam(attacker) != 3)) || (damagetype == (DMG_ENERGYBEAM|DMG_RADIATION|DMG_PREVENT_PHYSICS_FORCE) && attacker > MaxClients) ) { - float vPos[3]; - GetClientAbsOrigin(victim, vPos); - EmitSoundToAll(g_sAcidSounds[GetRandomInt(0, sizeof(g_sAcidSounds) - 1)], _, SNDCHAN_AUTO, 85, _, 0.55, GetRandomInt(95, 105), _, vPos); + EmitSoundToAll(g_sAcidSounds[GetRandomInt(0, sizeof(g_sAcidSounds) - 1)], inflictor, SNDCHAN_AUTO, 85, _, 0.55, GetRandomInt(95, 105)); + + // Red flash when taking damage + Handle msg = StartMessageOne("Fade", victim); + BfWriteShort(msg, 256); + BfWriteShort(msg, 0); // Duration + BfWriteShort(msg, 1); // Type + BfWriteByte(msg, 255); // Red + BfWriteByte(msg, 0); // Green + BfWriteByte(msg, 0); // Blue + BfWriteByte(msg, 30); // Alpha + EndMessage(); } } } @@ -1727,6 +1767,9 @@ public void OnEntityDestroyed(int entity) } } } +// ==================================================================================================== + + int Native_CTerrorPlayer_OnAdrenalineUsed(Handle plugin, int numParams) // Native "L4D2_UseAdrenaline" { @@ -5202,5 +5245,344 @@ int Native_CDirector_UnregisterForbiddenTarget(Handle plugin, int numParams) // //PrintToServer("#### CALL g_hSDK_CDirector_UnregisterForbiddenTarget"); SDKCall(g_hSDK_CDirector_UnregisterForbiddenTarget, g_pDirector, entity); + return 0; +} + + + + + +// ==================================================================================================== +// ANIMATION NATIVES +// Thanks for "Forgetest" and "A1m`" for providing. +// ==================================================================================================== +void PlayerAnimState_CreateNatives() +{ + CreateNative("PlayerAnimState.FromPlayer", Native_PlayerAnimState_FromPlayer); + CreateNative("PlayerAnimState.GetMainActivity", Native_PlayerAnimState_GetMainActivity); + CreateNative("PlayerAnimState.ResetMainActivity", Native_PlayerAnimState_ResetMainActivity); + CreateNative("PlayerAnimState.m_bIsCustomSequence.get", Native_PlayerAnimState_m_bIsCustomSequence_get); + CreateNative("PlayerAnimState.m_bIsCustomSequence.set", Native_PlayerAnimState_m_bIsCustomSequence_set); + CreateNative("PlayerAnimState.m_bIsDead.get", Native_PlayerAnimState_m_bIsDead_get); + CreateNative("PlayerAnimState.m_bIsDead.set", Native_PlayerAnimState_m_bIsDead_set); + CreateNative("PlayerAnimState.m_bIsHealing.get", Native_PlayerAnimState_m_bIsHealing_get); + CreateNative("PlayerAnimState.m_bIsHealing.set", Native_PlayerAnimState_m_bIsHealing_set); + CreateNative("PlayerAnimState.m_bIsResurrection.get", Native_PlayerAnimState_m_bIsResurrection_get); + CreateNative("PlayerAnimState.m_bIsResurrection.set", Native_PlayerAnimState_m_bIsResurrection_set); + CreateNative("PlayerAnimState.m_bIsHitByCharger.get", Native_PlayerAnimState_m_bIsHitByCharger_get); + CreateNative("PlayerAnimState.m_bIsHitByCharger.set", Native_PlayerAnimState_m_bIsHitByCharger_set); + CreateNative("PlayerAnimState.m_bIsPummeled.get", Native_PlayerAnimState_m_bIsPummeled_get); + CreateNative("PlayerAnimState.m_bIsPummeled.set", Native_PlayerAnimState_m_bIsPummeled_set); + CreateNative("PlayerAnimState.m_bIsSlammedIntoWall.get", Native_PlayerAnimState_m_bIsSlammedIntoWall_get); + CreateNative("PlayerAnimState.m_bIsSlammedIntoWall.set", Native_PlayerAnimState_m_bIsSlammedIntoWall_set); + CreateNative("PlayerAnimState.m_bIsSlammedIntoGround.get", Native_PlayerAnimState_m_bIsSlammedIntoGround_get); + CreateNative("PlayerAnimState.m_bIsSlammedIntoGround.set", Native_PlayerAnimState_m_bIsSlammedIntoGround_set); + CreateNative("PlayerAnimState.m_bIsStartPummel.get", Native_PlayerAnimState_m_bIsStartPummel_get); + CreateNative("PlayerAnimState.m_bIsStartPummel.set", Native_PlayerAnimState_m_bIsStartPummel_set); + CreateNative("PlayerAnimState.m_bIsPounded.get", Native_PlayerAnimState_m_bIsPounded_get); + CreateNative("PlayerAnimState.m_bIsPounded.set", Native_PlayerAnimState_m_bIsPounded_set); + CreateNative("PlayerAnimState.m_bIsCarriedByCharger.get", Native_PlayerAnimState_m_bIsCarriedByCharger_get); + CreateNative("PlayerAnimState.m_bIsCarriedByCharger.set", Native_PlayerAnimState_m_bIsCarriedByCharger_set); + CreateNative("PlayerAnimState.m_bIsPunchedByTank.get", Native_PlayerAnimState_m_bIsPunchedByTank_get); + CreateNative("PlayerAnimState.m_bIsPunchedByTank.set", Native_PlayerAnimState_m_bIsPunchedByTank_set); + CreateNative("PlayerAnimState.m_bIsSpitting.get", Native_PlayerAnimState_m_bIsSpitting_get); + CreateNative("PlayerAnimState.m_bIsSpitting.set", Native_PlayerAnimState_m_bIsSpitting_set); + CreateNative("PlayerAnimState.m_bIsPouncedOn.get", Native_PlayerAnimState_m_bIsPouncedOn_get); + CreateNative("PlayerAnimState.m_bIsPouncedOn.set", Native_PlayerAnimState_m_bIsPouncedOn_set); + CreateNative("PlayerAnimState.m_bIsTongueAttacked.get", Native_PlayerAnimState_m_bIsTongueAttacked_get); + CreateNative("PlayerAnimState.m_bIsTongueAttacked.set", Native_PlayerAnimState_m_bIsTongueAttacked_set); + CreateNative("PlayerAnimState.m_bIsStartChainsaw.get", Native_PlayerAnimState_m_bIsStartChainsaw_get); + CreateNative("PlayerAnimState.m_bIsStartChainsaw.set", Native_PlayerAnimState_m_bIsStartChainsaw_set); + CreateNative("PlayerAnimState.m_bIsIsPouncing.get", Native_PlayerAnimState_m_bIsIsPouncing_get); + CreateNative("PlayerAnimState.m_bIsIsPouncing.set", Native_PlayerAnimState_m_bIsIsPouncing_set); + CreateNative("PlayerAnimState.m_bIsRiding.get", Native_PlayerAnimState_m_bIsRiding_get); + CreateNative("PlayerAnimState.m_bIsRiding.set", Native_PlayerAnimState_m_bIsRiding_set); + CreateNative("PlayerAnimState.m_bIsJockeyRidden.get", Native_PlayerAnimState_m_bIsJockeyRidden_get); + CreateNative("PlayerAnimState.m_bIsJockeyRidden.set", Native_PlayerAnimState_m_bIsJockeyRidden_set); + CreateNative("PlayerAnimState.m_bIsTonguing.get", Native_PlayerAnimState_m_bIsTonguing_get); + CreateNative("PlayerAnimState.m_bIsTonguing.set", Native_PlayerAnimState_m_bIsTonguing_set); + CreateNative("PlayerAnimState.m_bIsCharging.get", Native_PlayerAnimState_m_bIsCharging_get); + CreateNative("PlayerAnimState.m_bIsCharging.set", Native_PlayerAnimState_m_bIsCharging_set); + CreateNative("PlayerAnimState.m_bIsPummeling.get", Native_PlayerAnimState_m_bIsPummeling_get); + CreateNative("PlayerAnimState.m_bIsPummeling.set", Native_PlayerAnimState_m_bIsPummeling_set); + CreateNative("PlayerAnimState.m_bIsPounding.get", Native_PlayerAnimState_m_bIsPounding_get); + CreateNative("PlayerAnimState.m_bIsPounding.set", Native_PlayerAnimState_m_bIsPounding_set); + CreateNative("PlayerAnimState.m_bIsTongueReelingIn.get", Native_PlayerAnimState_m_bIsTongueReelingIn_get); + CreateNative("PlayerAnimState.m_bIsTongueReelingIn.set", Native_PlayerAnimState_m_bIsTongueReelingIn_set); + CreateNative("PlayerAnimState.m_bIsTongueAttacking.get", Native_PlayerAnimState_m_bIsTongueAttacking_get); + CreateNative("PlayerAnimState.m_bIsTongueAttacking.set", Native_PlayerAnimState_m_bIsTongueAttacking_set); +} + +any Native_PlayerAnimState_FromPlayer(Handle plugin, int numParams) +{ + ValidateOffset(g_iOff_m_PlayerAnimState, "CTerrorPlayer::m_PlayerAnimState"); + + int client = GetNativeCell(1); + Address anim = view_as
(GetEntData(client, g_iOff_m_PlayerAnimState)); + // null check? + + return anim; +} + +any Native_PlayerAnimState_GetMainActivity(Handle plugin, int numParams) +{ + ValidateOffset(g_iOff_m_eCurrentMainSequenceActivity, "CMultiPlayerAnimState::m_eCurrentMainSequenceActivity"); + + Address anim = GetNativeCell(1); + + return LoadFromAddress(anim + view_as
(g_iOff_m_eCurrentMainSequenceActivity), NumberType_Int32); +} + +any Native_PlayerAnimState_ResetMainActivity(Handle plugin, int numParams) +{ + ValidateNatives(g_hSDK_CMultiPlayerAnimState_ResetMainActivity, "CMultiPlayerAnimState::ResetMainActivity"); + + Address anim = GetNativeCell(1); + SDKCall(g_hSDK_CMultiPlayerAnimState_ResetMainActivity, anim); + + return 0; +} + +// relOffset = relative offset to "m_bIsCustomSequence" +// for booleans from "m_bIsCustomSequence" all the way to "m_bIsTongueAttacking" + +bool PlayerAnimState_GetFlag(int relOffset) +{ + ValidateOffset(g_iOff_m_bIsCustomSequence, "CTerrorPlayerAnimState::m_bIsCustomSequence"); + Address anim = GetNativeCell(1); + return LoadFromAddress(anim + view_as
(g_iOff_m_bIsCustomSequence + relOffset), NumberType_Int8); +} + +void PlayerAnimState_SetFlag(int relOffset) +{ + ValidateOffset(g_iOff_m_bIsCustomSequence, "CTerrorPlayerAnimState::m_bIsCustomSequence"); + Address anim = GetNativeCell(1); + bool val = GetNativeCell(2); + StoreToAddress(anim + view_as
(g_iOff_m_bIsCustomSequence + relOffset), val, NumberType_Int8); +} + +any Native_PlayerAnimState_m_bIsCustomSequence_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(0); +} +any Native_PlayerAnimState_m_bIsCustomSequence_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(0); + return 0; +} +any Native_PlayerAnimState_m_bIsDead_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(1); +} +any Native_PlayerAnimState_m_bIsDead_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(1); + return 0; +} +any Native_PlayerAnimState_m_bIsHealing_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(2); +} +any Native_PlayerAnimState_m_bIsHealing_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(2); + return 0; +} +any Native_PlayerAnimState_m_bIsResurrection_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(3); +} +any Native_PlayerAnimState_m_bIsResurrection_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(3); + return 0; +} +any Native_PlayerAnimState_m_bIsHitByCharger_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(4); +} +any Native_PlayerAnimState_m_bIsHitByCharger_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(4); + return 0; +} +any Native_PlayerAnimState_m_bIsPummeled_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(5); +} +any Native_PlayerAnimState_m_bIsPummeled_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(5); + return 0; +} +any Native_PlayerAnimState_m_bIsSlammedIntoWall_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(6); +} +any Native_PlayerAnimState_m_bIsSlammedIntoWall_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(6); + return 0; +} +any Native_PlayerAnimState_m_bIsSlammedIntoGround_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(7); +} +any Native_PlayerAnimState_m_bIsSlammedIntoGround_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(7); + return 0; +} +any Native_PlayerAnimState_m_bIsStartPummel_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(8); +} +any Native_PlayerAnimState_m_bIsStartPummel_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(8); + return 0; +} +any Native_PlayerAnimState_m_bIsPounded_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(9); +} +any Native_PlayerAnimState_m_bIsPounded_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(9); + return 0; +} +any Native_PlayerAnimState_m_bIsCarriedByCharger_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(10); +} +any Native_PlayerAnimState_m_bIsCarriedByCharger_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(10); + return 0; +} +any Native_PlayerAnimState_m_bIsPunchedByTank_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(11); +} +any Native_PlayerAnimState_m_bIsPunchedByTank_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(11); + return 0; +} +any Native_PlayerAnimState_m_bIsSpitting_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(12); +} +any Native_PlayerAnimState_m_bIsSpitting_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(12); + return 0; +} +any Native_PlayerAnimState_m_bIsPouncedOn_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(13); +} +any Native_PlayerAnimState_m_bIsPouncedOn_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(13); + return 0; +} +any Native_PlayerAnimState_m_bIsTongueAttacked_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(14); +} +any Native_PlayerAnimState_m_bIsTongueAttacked_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(14); + return 0; +} +any Native_PlayerAnimState_m_bIsStartChainsaw_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(15); +} +any Native_PlayerAnimState_m_bIsStartChainsaw_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(15); + return 0; +} +any Native_PlayerAnimState_m_bIsIsPouncing_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(16); +} +any Native_PlayerAnimState_m_bIsIsPouncing_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(16); + return 0; +} +any Native_PlayerAnimState_m_bIsRiding_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(17); +} +any Native_PlayerAnimState_m_bIsRiding_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(17); + return 0; +} +any Native_PlayerAnimState_m_bIsJockeyRidden_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(18); +} +any Native_PlayerAnimState_m_bIsJockeyRidden_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(18); + return 0; +} +any Native_PlayerAnimState_m_bIsTonguing_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(19); +} +any Native_PlayerAnimState_m_bIsTonguing_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(19); + return 0; +} +any Native_PlayerAnimState_m_bIsCharging_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(20); +} +any Native_PlayerAnimState_m_bIsCharging_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(20); + return 0; +} +any Native_PlayerAnimState_m_bIsPummeling_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(21); +} +any Native_PlayerAnimState_m_bIsPummeling_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(21); + return 0; +} +any Native_PlayerAnimState_m_bIsPounding_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(22); +} +any Native_PlayerAnimState_m_bIsPounding_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(22); + return 0; +} +any Native_PlayerAnimState_m_bIsTongueReelingIn_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(23); +} +any Native_PlayerAnimState_m_bIsTongueReelingIn_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(23); + return 0; +} +any Native_PlayerAnimState_m_bIsTongueAttacking_get(Handle plugin, int numParams) +{ + return PlayerAnimState_GetFlag(24); +} +any Native_PlayerAnimState_m_bIsTongueAttacking_set(Handle plugin, int numParams) +{ + PlayerAnimState_SetFlag(24); return 0; } \ No newline at end of file diff --git a/addons/sourcemod/scripting/l4dd/l4dd_setup.sp b/addons/sourcemod/scripting/l4dd/l4dd_setup.sp index c380bd612..ae501f81d 100644 --- a/addons/sourcemod/scripting/l4dd/l4dd_setup.sp +++ b/addons/sourcemod/scripting/l4dd/l4dd_setup.sp @@ -114,9 +114,6 @@ void SetupForwardsNatives() 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_CDirectorVersusMode_EndVersusModeRound_PostHandled = new GlobalForward("L4D2_OnEndVersusModeRound_PostHandled", ET_Event); - // g_hFWD_CDirector_EndScenario_Pre = new GlobalForward("L4D_OnEndScenario", ET_Event, Param_Cell); - // g_hFWD_CDirector_EndScenario_Post = new GlobalForward("L4D_OnEndScenario_Post", ET_Event, Param_Cell); - // g_hFWD_CDirector_EndScenario_PostHandled = new GlobalForward("L4D_OnEndScenario_PostHandled", ET_Event, Param_Cell); g_hFWD_CServerGameDLL_ServerHibernationUpdate = new GlobalForward("L4D_OnServerHibernationUpdate", ET_Event, Param_Cell); g_hFWD_CTerrorPlayer_OnLedgeGrabbed = new GlobalForward("L4D_OnLedgeGrabbed", ET_Event, Param_Cell); g_hFWD_CTerrorPlayer_OnLedgeGrabbed_Post = new GlobalForward("L4D_OnLedgeGrabbed_Post", ET_Event, Param_Cell); @@ -229,6 +226,9 @@ void SetupForwardsNatives() g_hFWD_CTerrorPlayer_OnHitByVomitJar = new GlobalForward("L4D2_OnHitByVomitJar", ET_Event, Param_Cell, Param_CellByRef); g_hFWD_CTerrorPlayer_OnHitByVomitJar_Post = new GlobalForward("L4D2_OnHitByVomitJar_Post", ET_Event, Param_Cell, Param_Cell); g_hFWD_CTerrorPlayer_OnHitByVomitJar_PostHandled = new GlobalForward("L4D2_OnHitByVomitJar_PostHandled", ET_Event, Param_Cell, Param_Cell); + g_hFWD_Infected_OnHitByVomitJar = new GlobalForward("L4D2_Infected_HitByVomitJar", ET_Event, Param_Cell, Param_CellByRef); + g_hFWD_Infected_OnHitByVomitJar_Post = new GlobalForward("L4D2_Infected_HitByVomitJar_Post", ET_Event, Param_Cell, Param_Cell); + g_hFWD_Infected_OnHitByVomitJar_PostHandled = new GlobalForward("L4D2_Infected_HitByVomitJar_PostHandled", ET_Event, Param_Cell, Param_Cell); 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_GetScriptValueVector = new GlobalForward("L4D_OnGetScriptValueVector", ET_Event, Param_String, Param_Array); @@ -256,6 +256,8 @@ void SetupForwardsNatives() // ==================================================================================================== // NATIVES // ==================================================================================================== + PlayerAnimState_CreateNatives(); + // ANIMATION HOOK CreateNative("AnimHookEnable", Native_AnimHookEnable); CreateNative("AnimHookDisable", Native_AnimHookDisable); @@ -273,6 +275,7 @@ void SetupForwardsNatives() CreateNative("L4D_ReadMemoryString", Native_ReadMemoryString); CreateNative("L4D_GetServerOS", Native_GetServerOS); CreateNative("Left4DHooks_Version", Native_Left4DHooks_Version); + CreateNative("L4D_HasMapStarted", Native_HasMapStarted); CreateNative("L4D_GetGameModeType", Native_Internal_GetGameMode); CreateNative("L4D2_IsGenericCooperativeMode", Native_CTerrorGameRules_IsGenericCooperativeMode); CreateNative("L4D_IsCoopMode", Native_Internal_IsCoopMode); diff --git a/addons/sourcemod/scripting/l4dd/left4dhooks_changelog.txt b/addons/sourcemod/scripting/l4dd/left4dhooks_changelog.txt index 3669c4981..aac434273 100644 --- a/addons/sourcemod/scripting/l4dd/left4dhooks_changelog.txt +++ b/addons/sourcemod/scripting/l4dd/left4dhooks_changelog.txt @@ -1,3 +1,30 @@ +1.138 (25-Sep-2023) + - Fixed the "L4D2_CGasCan_EventKilled*" forwards not triggering when a gascan had not been picked up. Thanks to "Mystik Spiral" for reporting. + + - Updated: Plugin and test plugin. + - Updated: "/gamedata/left4dhooks.l4d2.txt" GameData file. + - Updated: "/scripting/include/left4dhooks.inc" Include file. + - Updated: "/scripting/l4dd/l4dd_forwards.sp" project file. + - Updated: "/scripting/l4dd/l4dd_natives.sp" project file. + +1.137 (23-Sep-2023) + - Added forwards "L4D2_Infected_HitByVomitJar", "L4D2_Infected_HitByVomitJar_Post" and "L4D2_Infected_HitByVomitJar_PostHandled" to trigger when common infected are hit with a VomitJar. Requested by "Eyal282". + - Incorporated the Spitter Acid no sound fix for when clients disconnected. Thanks to "Marttt" for reporting. + - Now also flashes red like the game should when taking damage from this bugged entity. Thanks to "Marttt" for reporting. + - Updated to the latest version of the "lux_library" include file. Thanks to "Lux" for reporting. + +1.136 (05-Sep-2023) + - Fixed the last update logging an error in L4D1. Thanks to "HarryPotter" for reporting. + - Fixed forward "L4D_TankClaw_DoSwing_Post" having the wrong name and not activating. Thanks to "Forgetest" for reporting. + +1.135 (18-Aug-2023) + - Added a ton of natives for "PlayerAnimState" in L4D2 only. See the "methodmap PlayerAnimState" section of the "left4dhooks.inc" include file. Thanks to "Forgetest" for the code and "A1m`" for various stuff. + - Added native "L4D_HasMapStarted" to check if game addresses have been loaded in OnMapStart. For use with some natives that require being called only after OnMapStart. + - Added an example to the test plugin for use with "L4D_HasMapStarted" and natives that require waiting after OnMapStart. See the first OnMapStart section that is commented out. + - Fixed forward "L4D2_OnPounceOrLeapStumble" detour to potentially fix rare random crashes. Thanks to "A1m`" and "Forgetest" for reporting. + - Fixed stock "L4D2_SetEntityGlow" to use the newdecls. Thanks to "Dragokas" for reporting. + - Fixed the test plugin examples for "L4D1_FirstAidKit_StartHealing" and "L4D2_BackpackItem_StartAction". Thanks to "Mystik Spiral" for reporting. + 1.134 (10-Jul-2023) - Added "POINTER_SURVIVALMODE" enum for the "L4D_GetPointer" native to return the SurvivalMode pointer. - Added "L4D2CT_SurvivalSetupTimer" to the "L4D2CountdownTimer" enum for use with the "L4D2_CTimer*" natives. @@ -11,16 +38,6 @@ - Fixed L4D2 GameData offset for "L4D2_GetFirstSpawnClass" and "L4D2_SetFirstSpawnClass" natives. Thanks to "Forgetest" for reporting the new offset. - Errors about using natives before OnMapStart will now show the plugin causing it. - - Updated: Plugin and test plugin. - - Updated: "/scripting/gamedata/left4dhooks.l4d1.txt" GameData file. - - Updated: "/scripting/gamedata/left4dhooks.l4d2.txt" GameData file. - - Updated: "/scripting/include/left4dhooks.inc" Include file. - - Updated: "/scripting/include/left4dhooks_stocks.inc" Include file. - - Updated: "/scripting/l4dd/l4dd_forwards.sp" project file. - - Updated: "/scripting/l4dd/l4dd_gamedata.sp" project file. - - Updated: "/scripting/l4dd/l4dd_natives.sp" project file. - - Updated: "/scripting/l4dd/l4dd_setup.sp" project file. - 1.133 (19-Jun-2023) - Added details to some natives explaining they can only be used 1 frame after "OnMapStart" due to pointers being unavailable before. Thanks to "HarryPotter" for reporting. - Added an error log when certain natives are used before before "OnMapStart" instead of an ambiguous error about invalid offsets. @@ -422,7 +439,7 @@ 1.81 (30-Nov-2021) - Fixed forward "L4D_OnVomitedUpon" sometimes throwing errors about null pointer. Thanks to "Krufftys Killers" for reporting. - - Changed function "Local_GetRandomClient" in "left4dhooks_silver.inc" to be stock. Thanks to "A1m1" for reporting. + - Changed function "Local_GetRandomClient" in "left4dhooks_silver.inc" to be stock. Thanks to "A1m`" for reporting. 1.80 (24-Nov-2021) - Fixed forward "L4D_OnSpawnSpecial_Post" param error. Thanks to "fdxx" for reporting. diff --git a/addons/sourcemod/scripting/left4dhooks.sp b/addons/sourcemod/scripting/left4dhooks.sp index 89dc576bd..cf21166fe 100644 --- a/addons/sourcemod/scripting/left4dhooks.sp +++ b/addons/sourcemod/scripting/left4dhooks.sp @@ -18,8 +18,8 @@ -#define PLUGIN_VERSION "1.134" -#define PLUGIN_VERLONG 1134 +#define PLUGIN_VERSION "1.138" +#define PLUGIN_VERLONG 1138 #define DEBUG 0 // #define DEBUG 1 // Prints addresses + detour info (only use for debugging, slows server down). @@ -120,6 +120,8 @@ native void Updater_AddPlugin(const char[] url); // ==================================================================================================== + + // PROFILER #if DEBUG #include @@ -179,6 +181,9 @@ float g_fProf; // Dissolver #define SPRITE_GLOW "sprites/blueglow1.vmt" +// GasCan model for damage hook +#define MODEL_GASCAN "models/props_junk/gascan001a.mdl" + // Precache models for spawning @@ -264,6 +269,9 @@ int g_iOff_VersusMaxCompletionScore; int g_iOff_OnBeginRoundSetupTime; int g_iOff_m_iTankCount; int g_iOff_m_iWitchCount; +int g_iOff_m_PlayerAnimState; +int g_iOff_m_eCurrentMainSequenceActivity; +int g_iOff_m_bIsCustomSequence; int g_iOff_m_iCampaignScores; int g_iOff_m_fTankSpawnFlowPercent; int g_iOff_m_fWitchSpawnFlowPercent; @@ -341,6 +349,7 @@ int g_iPrimaryAmmoType; int g_iCurrentMode; int g_iMaxChapters; int g_iClassTank; +int g_iGasCanModel; char g_sSystem[16]; bool g_bLinuxOS; bool g_bLeft4Dead2; @@ -360,22 +369,6 @@ DynamicHook g_hScriptHook; -// Spitter acid projectile damage -bool g_bAcidWatch; -int g_iAcidEntity[2048]; - -char g_sAcidSounds[6][] = -{ - "player/PZ/hit/zombie_slice_1.wav", - "player/PZ/hit/zombie_slice_2.wav", - "player/PZ/hit/zombie_slice_3.wav", - "player/PZ/hit/zombie_slice_4.wav", - "player/PZ/hit/zombie_slice_5.wav", - "player/PZ/hit/zombie_slice_6.wav" -}; - - - #if DEBUG bool g_bLateLoad; #endif @@ -384,29 +377,19 @@ bool g_bLateLoad; -// ==================================================================================================== -// TARGET FILTERS -// ==================================================================================================== +// TARGET FILTERS #include "l4dd/l4dd_targetfilters.sp" -// ==================================================================================================== -// NATIVES -// ==================================================================================================== +// NATIVES #include "l4dd/l4dd_natives.sp" -// ==================================================================================================== -// DETOURS - FORWARDS -// ==================================================================================================== +// DETOURS - FORWARDS #include "l4dd/l4dd_forwards.sp" -// ==================================================================================================== -// GAMEDATA -// ==================================================================================================== +// GAMEDATA #include "l4dd/l4dd_gamedata.sp" -// ==================================================================================================== -// SETUP FORWARDS AND NATIVES -// ==================================================================================================== +// SETUP FORWARDS AND NATIVES #include "l4dd/l4dd_setup.sp" @@ -446,16 +429,16 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max - // ==================================================================================================== - // UPDATER - // ==================================================================================================== + // ================= + // UPDATER + // ================= MarkNativeAsOptional("Updater_AddPlugin"); - // ==================================================================================================== - // DUPLICATE PLUGIN RUNNING - // ==================================================================================================== + // ================= + // DUPLICATE PLUGIN RUNNING + // ================= if( GetFeatureStatus(FeatureType_Native, "L4D_BecomeGhost") == FeatureStatus_Available ) { strcopy(error, err_max, "\n====================\nPlugin \"Left 4 DHooks\" is already running. Please remove the duplicate plugin.\n===================="); @@ -464,9 +447,9 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max - // ==================================================================================================== - // EXTENSION BLOCK - // ==================================================================================================== + // ================= + // EXTENSION BLOCK + // ================= if( GetFeatureStatus(FeatureType_Native, "L4D_RestartScenarioFromVote") != FeatureStatus_Unknown ) { strcopy(error, err_max, "\n====================\nThis plugin replaces Left4Downtown. Delete the extension to run.\n===================="); @@ -475,16 +458,16 @@ public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max - // ==================================================================================================== - // SETUP FORWARDS AND NATIVES - // ==================================================================================================== + // ================= + // SETUP FORWARDS AND NATIVES + // ================= SetupForwardsNatives(); // From: "l4dd/l4dd_setup.sp" - // ==================================================================================================== - // END SETUP - // ==================================================================================================== + // ================= + // END SETUP + // ================= RegPluginLibrary("left4dhooks"); @@ -729,8 +712,8 @@ public void OnPluginStart() HookEvent("round_end", Event_RoundEnd); HookEvent("player_entered_start_area", Event_EnteredStartArea); HookEvent("player_left_start_area", Event_LeftStartArea); - HookEvent("player_left_checkpoint", Event_LeftCheckpoint); HookEvent("player_entered_checkpoint", Event_EnteredCheckpoint); + HookEvent("player_left_checkpoint", Event_LeftCheckpoint); } } @@ -1026,6 +1009,24 @@ public void OnClientDisconnect(int client) i++; } } + + + + // Acid damage, no sound fix + if( g_bLeft4Dead2 ) + { + if( !IsClientInGame(client) || (GetClientTeam(client) == 3 && GetEntProp(client, Prop_Send, "m_zombieClass") == L4D2_ZOMBIE_CLASS_SPITTER) ) + { + int entity = -1; + while( (entity = FindEntityByClassname(entity, "insect_swarm")) != INVALID_ENT_REFERENCE ) + { + if( GetEntPropEnt(entity, Prop_Data, "m_hOwnerEntity") == client ) + { + AcidDamageTest(0, entity); // See the "l4dd_natives.sp" file + } + } + } + } } public void OnNotifyPluginUnloaded(Handle plugin) @@ -1456,8 +1457,6 @@ public void OnMapStart() // Because reload command calls this function. We only want these loaded on actual map start. if( !g_bMapStarted ) { - g_bMapStarted = true; - GetGameMode(); // Get current game mode @@ -1480,6 +1479,8 @@ public void OnMapStart() g_iAcidEntity[i] = 0; } + g_iGasCanModel = PrecacheModel(MODEL_GASCAN); + // Director Variables initialized before the plugin is able to hook. @@ -1567,6 +1568,8 @@ public void OnMapStart() } } } + + g_bMapStarted = true; } } diff --git a/addons/sourcemod/scripting/left4dhooks_test.sp b/addons/sourcemod/scripting/left4dhooks_test.sp index c756aa619..2718ab8e1 100644 --- a/addons/sourcemod/scripting/left4dhooks_test.sp +++ b/addons/sourcemod/scripting/left4dhooks_test.sp @@ -18,7 +18,7 @@ -#define PLUGIN_VERSION "1.133" +#define PLUGIN_VERSION "1.137" /*======================================================================================= Plugin Info: @@ -122,6 +122,34 @@ public void OnPluginStart() +// ==================================================================================================== +// ADDRESSES - Demonstrating when addresses are valid for use with certain natives (documented in left4dhooks.inc) +// ==================================================================================================== +/* +public void OnMapStart() +{ + // "L4D_HasMapStarted" native is only available in left4dhooks version 1.135+ this just checks if the version being used would allow calling the native, you could just require 1.135 instead of adding these extra checks + if( GetFeatureStatus(FeatureType_Native, "Left4DHooks_Version") != FeatureStatus_Available || Left4DHooks_Version() < 1135 || !L4D_HasMapStarted() ) + { + RequestFrame(OnFrameStart); + } + else + { + OnFrameStart(); + } +} + +void OnFrameStart() +{ + // Basically depending on plugin load order, OnMapStart might fire before or after Left4DHooks + // If it's after then everything should be fine, but before would cause problems as some natives are not ready to be called by then + // So using RequestFrame would fix the issue, but this way you could call the native either in OnMapStart or 1 frame later if it's not ready yet + // The native "L4D2_GetSurvivorSetMap" is one of those which need the addresses to be loaded first + // If you search for "OnMapStart" in the include file you will see all the other natives that require this method if used early on + bool g_bIsL4D1 = L4D2_GetSurvivorSetMap() == 2 ? false : true; +} +// */ + // ==================================================================================================== @@ -322,6 +350,68 @@ Action sm_l4dd(int client, int args) + // PrintToServer("L4D_HasMapStarted %d", L4D_HasMapStarted()); // WORKS + + + + /* + if( client > 0 ) + { + PlayerAnimState anim = PlayerAnimState.FromPlayer(client); + + // Not gonna show the right number until next frame of a new animation event (the following) + PrintToChat(client, "Activity = %d", anim.GetMainActivity()); + + // Should be true if in intro sequence + PrintToChat(client, "m_bIsCustomSequence = %s", anim.m_bIsCustomSequence ? "true" : "false"); + + if( !anim.m_bIsCustomSequence ) + { + static bool time_to_restart = false; + + if( time_to_restart ) + { + anim.ResetMainActivity(); + time_to_restart = false; + + PrintToChat(client, "ResetMainActivity"); + } + else + { + static int step = 0; + static const int max_step = 2; + + switch( step ) + { + case 0: + { + L4D2Direct_DoAnimationEvent(client, view_as(PLAYERANIMEVENT_PLAYERHIT_BY_TANK)); + + // Should be true after "L4D2Direct_DoAnimationEvent" above + PrintToChat(client, "m_bIsPunchedByTank = %s", anim.m_bIsPunchedByTank ? "true" : "false"); + } + case 1: + { + L4D2_CTerrorPlayer_Fling(client, client, view_as({0.0, 0.0, 0.0})); + + // Should be true after "L4D2_CTerrorPlayer_Fling" above + PrintToChat(client, "m_bIsHitByCharger = %s", anim.m_bIsHitByCharger ? "true" : "false"); + } + } + + step++; + time_to_restart = true; + if( step >= max_step ) + step = 0; + } + } + + // There are more bits, but regarding how these natives are implemented, it's promised the rest be working. + } + // */ + + + // L4D_EndVersusModeRound(false); // WORKS // L4D2_SpawnAllScavengeItems(); // WORKS // L4D2_StartRematchVote(); // WORKS @@ -3309,49 +3399,6 @@ public void L4D2_OnEndVersusModeRound_PostHandled() } } -/* -public Action L4D_OnEndScenario(int reason) -{ - static int called; - if( called < MAX_CALLS ) - { - if( called == 0 ) g_iForwards++; - called++; - - ForwardCalled("\"L4D_OnEndScenario\" Reason: %d", reason); - } - - // DOESN'T STOP THE ROUND ENDING - // return Plugin_Handled; - - return Plugin_Continue; -} - -public void L4D_OnEndScenario_Post(int reason) -{ - static int called; - if( called < MAX_CALLS ) - { - if( called == 0 ) g_iForwards++; - called++; - - ForwardCalled("\"L4D_OnEndScenario_Post\" Reason: %d", reason); - } -} - -public void L4D_OnEndScenario_PostHandled(int reason) -{ - static int called; - if( called < MAX_CALLS ) - { - if( called == 0 ) g_iForwards++; - called++; - - ForwardCalled("\"L4D_OnEndScenario_PostHandled\" Reason: %d", reason); - } -} -*/ - public Action L4D_OnRecalculateVersusScore(int client) { static int called; @@ -3915,7 +3962,7 @@ public Action L4D2_OnHitByVomitJar(int victim, int &attacker) if( called == 0 ) g_iForwards++; called++; - ForwardCalled("\"L4D2_OnHitByVomitJar\" %d > %d)", victim, attacker); + ForwardCalled("\"L4D2_OnHitByVomitJar\" %d > %d", victim, attacker); } // attacker = victim; @@ -3935,7 +3982,7 @@ public void L4D2_OnHitByVomitJar_Post(int victim, int attacker) if( called == 0 ) g_iForwards++; called++; - ForwardCalled("\"L4D2_OnHitByVomitJar_Post\" %d > %d)", victim, attacker); + ForwardCalled("\"L4D2_OnHitByVomitJar_Post\" %d > %d", victim, attacker); } } @@ -3947,7 +3994,51 @@ public void L4D2_OnHitByVomitJar_PostHandled(int victim, int attacker) if( called == 0 ) g_iForwards++; called++; - ForwardCalled("\"L4D2_OnHitByVomitJar_PostHandled\" %d > %d)", victim, attacker); + ForwardCalled("\"L4D2_OnHitByVomitJar_PostHandled\" %d > %d", victim, attacker); + } +} + +public Action L4D2_Infected_HitByVomitJar(int victim, int &attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_Infected_HitByVomitJar\" %d > %d", victim, attacker); + } + + // attacker = victim; + // return Plugin_Changed; + + // WORKS + // return Plugin_Handled; + + return Plugin_Continue; +} + +public void L4D2_Infected_HitByVomitJar_Post(int victim, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_Infected_HitByVomitJar_Post\" %d > %d", victim, attacker); + } +} + +public void L4D2_Infected_HitByVomitJar_PostHandled(int victim, int attacker) +{ + static int called; + if( called < MAX_CALLS ) + { + if( called == 0 ) g_iForwards++; + called++; + + ForwardCalled("\"L4D2_Infected_HitByVomitJar_PostHandled\" %d > %d", victim, attacker); } } @@ -4227,6 +4318,9 @@ public Action L4D1_FirstAidKit_StartHealing(int client, int entity) int target = L4D_FindUseEntity(client, true, range); // "m_healTarget" is not set at this point, must call this native if you wish to identify the target before healing if( target < 0 || target > MaxClients ) target = 0; + if( GetClientButtons(client) & IN_ATTACK ) + target = client; + ForwardCalled("\"L4D1_FirstAidKit_StartHealing\" %d (%N) - MedKit = %d. Healing: %d (%N)", client, client, entity, target, target); } @@ -4306,7 +4400,10 @@ public Action L4D2_BackpackItem_StartAction(int client, int entity, any type) if( type == L4D2WeaponId_FirstAidKit || type == L4D2WeaponId_Defibrillator ) { - if( target < 0 || target > MaxClients ) target = 0; + if( GetClientButtons(client) & IN_ATTACK ) + target = client; + else + if( target < 1 || target > MaxClients ) target = client; } else { @@ -5518,7 +5615,7 @@ void ForwardCalled(const char[] format, any ...) // LogAction(0, -1, "Forward %d/%d called %s", g_iForwards, g_iForwardsMax, buffer); // PrintToServer("----------"); - PrintToServer("L4DD: %s", buffer); + PrintToServer(" > L4DD: %s", buffer); // PrintToServer("----------"); }