From a50e877fbda30774cf5d1c7001e508255040584e Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Fri, 10 Oct 2025 20:54:30 +0800 Subject: [PATCH 01/11] Add files via upload block m2 pass pills --- addons/sourcemod/gamedata/block_m2_giver.txt | 49 ++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 addons/sourcemod/gamedata/block_m2_giver.txt diff --git a/addons/sourcemod/gamedata/block_m2_giver.txt b/addons/sourcemod/gamedata/block_m2_giver.txt new file mode 100644 index 000000000..e78099eb7 --- /dev/null +++ b/addons/sourcemod/gamedata/block_m2_giver.txt @@ -0,0 +1,49 @@ +"Games" +{ + "left4dead2" + { + "Functions" + { + "CY115::CTerrorPlayer::ThrowWeapon" + { + "signature" "CTerrorPlayer::ThrowWeapon" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + "a2" + { + "type" "cbaseentity" + } + "a3" + { + "type" "float" + } + "a4" + { + "type" "charptr" + } + "a5" + { + "type" "charptr" + } + } + } + } + + "Signatures" + { + "CTerrorPlayer::ThrowWeapon" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer11ThrowWeaponEP13CTerrorWeaponPS_fPKcS4_" + "windows" "\x55\x89\xE5\x57\x56\x53\x81\xEC\x6C\x01\x00\x00\x8B\x75\x0C" + } + } + } +} From ce2a27cb380bb22cfc5214cd9635d0ec60e297dc Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Fri, 10 Oct 2025 20:54:58 +0800 Subject: [PATCH 02/11] Add files via upload block m2 pass pills --- .../plugins/optional/block_m2_giver.smx | Bin 0 -> 4365 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 addons/sourcemod/plugins/optional/block_m2_giver.smx diff --git a/addons/sourcemod/plugins/optional/block_m2_giver.smx b/addons/sourcemod/plugins/optional/block_m2_giver.smx new file mode 100644 index 0000000000000000000000000000000000000000..aed93ce73a0e6ba1c8aa100370ea520dd9d16dfd GIT binary patch literal 4365 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 Yvc^V_Jq;$2zhhY=l7GULEl-a5KfARsUH||9 literal 0 HcmV?d00001 From 61899178ebfb721f56cdc4f78498b3c2f4441299 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Fri, 10 Oct 2025 20:55:05 +0800 Subject: [PATCH 03/11] Add files via upload block m2 pass pills --- addons/sourcemod/scripting/block_m2_giver.sp | 81 ++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 addons/sourcemod/scripting/block_m2_giver.sp diff --git a/addons/sourcemod/scripting/block_m2_giver.sp b/addons/sourcemod/scripting/block_m2_giver.sp new file mode 100644 index 000000000..c1c9ca724 --- /dev/null +++ b/addons/sourcemod/scripting/block_m2_giver.sp @@ -0,0 +1,81 @@ +#pragma semicolon 1 +#pragma newdecls required + +#define GAMEDATA "block_m2_giver" +#define FUNCTION "CY115::CTerrorPlayer::ThrowWeapon" + +enum { + BLOCKTYPE_NONE = 0, + BLOCKTYPE_PILLS, + BLOCKTYPE_ADRENALINE, + + BLOCKTYPE_SIZE +}; + +#include + +int + g_iBlockType = 0; + +public void OnPluginStart() +{ + InitGameData(); + + CreateConVarHook("block_item_giver_mask", "1", "Block Pass Item By M2[0=dont block, 1=block pills, 2=block adrenaline, 3=block both]", _, true, 0.0, true, 3.0, OnBlockTypeChanged).IntValue; +} + +void InitGameData() +{ + GameData gd = new GameData(GAMEDATA); + if (!gd) { + SetFailState("Missing gamedata \"%s.txt\"", GAMEDATA); + } + + DynamicDetour hDetour = DynamicDetour.FromConf(gd, FUNCTION); + if (!hDetour) { + SetFailState("Failed to setup detour \"%s\"", FUNCTION); + } + + if (!hDetour.Enable(Hook_Pre, OnCTerrorPlayerThrowWeaponPre)) { + SetFailState("Failed to create detour pre-hook \"%s\"", FUNCTION); + } + + delete hDetour; + delete gd; +} + +void OnBlockTypeChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_iBlockType = convar.IntValue; +} + +MRESReturn OnCTerrorPlayerThrowWeaponPre(int pThis, DHookReturn hReturn, DHookParam hParams) +{ + int entity = hParams.Get(1); + if (entity && IsValidEntity(entity)) { + char weapon[64]; + GetEntityClassname(entity, weapon, sizeof(weapon)); + if ((StrEqual(weapon, "weapon_pain_pills") && (g_iBlockType & BLOCKTYPE_PILLS)) || + StrEqual(weapon, "weapon_adrenaline") && (g_iBlockType & BLOCKTYPE_ADRENALINE)) { + return MRES_Supercede; + } + + } + + return MRES_Ignored; +} + +ConVar CreateConVarHook(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, ConVarChanged callback) { + ConVar convar = CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); + + Call_StartFunction(INVALID_HANDLE, callback); + Call_PushCell(convar); + Call_PushNullString(); + Call_PushNullString(); + Call_Finish(); + + convar.AddChangeHook(callback); + + return convar; +} \ No newline at end of file From 360ffa8533c6bfaa0c4d1649ad2b717ae8765e37 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Fri, 10 Oct 2025 20:55:43 +0800 Subject: [PATCH 04/11] Update generalfixes.cfg block m2 pass pills --- cfg/generalfixes.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/cfg/generalfixes.cfg b/cfg/generalfixes.cfg index db039efac..4de4c6ca4 100644 --- a/cfg/generalfixes.cfg +++ b/cfg/generalfixes.cfg @@ -70,6 +70,7 @@ sm plugins load fixes/l4d_fix_stagger_dir.smx sm plugins load fixes/l4d2_fix_rocket_pull.smx sm plugins load optional/l4d_return_thrown_items.smx sm plugins load fixes/l4d_prop_touching_rules.smx +sm plugins load optional/block_m2_giver.smx // Anti-Cheat. sm plugins load anticheat/l4d2_noghostcheat.smx From c68ae6ee7bab45b57c76e8c4753e1d00900cef18 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:35:20 +0800 Subject: [PATCH 05/11] Better Pills Passer Add function to block m2 give pills by mistake and make button reload give pill anim --- addons/sourcemod/gamedata/pill_passer.txt | 52 +++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 addons/sourcemod/gamedata/pill_passer.txt diff --git a/addons/sourcemod/gamedata/pill_passer.txt b/addons/sourcemod/gamedata/pill_passer.txt new file mode 100644 index 000000000..a42628a42 --- /dev/null +++ b/addons/sourcemod/gamedata/pill_passer.txt @@ -0,0 +1,52 @@ +"Games" +{ + "left4dead2" + { + "Functions" + { + "CTerrorPlayer::ThrowWeapon" + { + "signature" "CTerrorPlayer::ThrowWeapon" + "callconv" "thiscall" + "return" "int" + "this" "entity" + "arguments" + { + "a1" + { + "type" "cbaseentity" + } + "a2" + { + "type" "cbaseentity" + } + "a3" + { + "type" "float" + } + "a4" + { + "type" "charptr" + } + "a5" + { + "type" "charptr" + } + } + } + } + "Signatures" + { + "CTerrorWeapon::OnDropped" + { + "library" "server" + "linux" "@_ZN13CTerrorWeapon9OnDroppedEP13CTerrorPlayerS1_" + } + "CTerrorPlayer::ThrowWeapon" + { + "library" "server" + "linux" "@_ZN13CTerrorPlayer11ThrowWeaponEP13CTerrorWeaponPS_fPKcS4_" + } + } + } +} \ No newline at end of file From 582ce7e54e8a7b205d866c54e7ce25f6a26f2124 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:37:09 +0800 Subject: [PATCH 06/11] Better Pills Passer Add function to block m2 give pills by mistake and make button reload give pill anim --- .../plugins/optional/pill_passer.smx | Bin 10237 -> 11539 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/addons/sourcemod/plugins/optional/pill_passer.smx b/addons/sourcemod/plugins/optional/pill_passer.smx index 7e2e139c561c4bce01b291a6295ede0be6037d1b..ed56e586c6e81a5bc2bca3bbe2bcb5a1bdc400a7 100644 GIT binary patch literal 11539 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 Date: Mon, 27 Oct 2025 15:37:17 +0800 Subject: [PATCH 07/11] Better Pills Passer Add function to block m2 give pills by mistake and make button reload give pill anim --- addons/sourcemod/scripting/pill_passer.sp | 580 ++++++++++++---------- 1 file changed, 327 insertions(+), 253 deletions(-) diff --git a/addons/sourcemod/scripting/pill_passer.sp b/addons/sourcemod/scripting/pill_passer.sp index 21c029d9a..b290f9ad2 100644 --- a/addons/sourcemod/scripting/pill_passer.sp +++ b/addons/sourcemod/scripting/pill_passer.sp @@ -1,253 +1,327 @@ -#pragma semicolon 1 -#pragma newdecls required - -#include -#include -#include -#define L4D2UTIL_STOCKS_ONLY 1 -#include -#undef REQUIRE_PLUGIN -#include - -#define USE_GIVEPLAYERITEM 0 // Works correctly only in the latest version of sourcemod 1.11 (GivePlayerItem sourcemod native) - -public Plugin myinfo = -{ - name = "Easier Pill Passer", - author = "CanadaRox, A1m`, Forgetest", - description = "Lets players pass pills and adrenaline with +reload when they are holding one of those items", - version = "1.6.2", - url = "https://github.com/SirPlease/L4D2-Competitive-Rework" -}; - -bool g_bLateLoad, g_bLagCompAvailable; -float g_flSqRange; -bool g_bLOSClear, g_bLagComp; -int g_iPasser = -1; - -public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) -{ - if (GetEngineVersion() != Engine_Left4Dead2) - { - strcopy(error, err_max, "Plugin supports L4D2 only"); - return APLRes_SilentFailure; - } - - g_bLateLoad = late; - return APLRes_Success; -} - -public void OnPluginStart() -{ - CreateConVarHook("pill_passer_range", - "274.0", - "Max distance to transfer pills between players.", - FCVAR_CHEAT, - true, 0.0, false, 0.0, - CvarChg_Range); - - CreateConVarHook("pill_passer_los_clear", - "0", - "Whether to require LOS clear when passing pills.", - FCVAR_CHEAT, - true, 0.0, true, 1.0, - CvarChg_LOSClear); - - CreateConVarHook("pill_passer_lag_compensate", - "1", - "Whether to enable lag compensation when passing pills.", - FCVAR_CHEAT, - true, 0.0, true, 1.0, - CvarChg_LagComp); - - if (g_bLateLoad) - { - for (int i = 1; i <= MaxClients; ++i) - { - if (IsClientInGame(i)) OnClientPutInServer(i); - } - } -} - -public void OnAllPluginsLoaded() -{ - g_bLagCompAvailable = LibraryExists("l4d2_lagcomp_manager"); -} - -public void OnLibraryAdded(const char[] name) -{ - if (strcmp(name, "l4d2_lagcomp_manager") == 0) - g_bLagCompAvailable = true; -} - -public void OnLibraryRemoved(const char[] name) -{ - if (strcmp(name, "l4d2_lagcomp_manager") == 0) - g_bLagCompAvailable = false; -} - -void CvarChg_Range(ConVar convar, const char[] oldValue, const char[] newValue) -{ - float val = convar.FloatValue; - g_flSqRange = val * val; -} - -void CvarChg_LOSClear(ConVar convar, const char[] oldValue, const char[] newValue) -{ - g_bLOSClear = convar.BoolValue; -} - -void CvarChg_LagComp(ConVar convar, const char[] oldValue, const char[] newValue) -{ - g_bLagComp = convar.BoolValue; -} - -public Action L4D2_LagComp_OnWantsLagCompensationOnEntity(int client, int entity, bool &result, int buttons, int impulse) -{ - if (client != g_iPasser) - return Plugin_Continue; - - if (entity <= 0 || entity > MaxClients || !IsClientInGame(entity)) - return Plugin_Continue; - - if (GetClientTeam(entity) != 2) - return Plugin_Continue; - - if (!IsPlayerAlive(entity)) - return Plugin_Continue; - - result = true; - return Plugin_Handled; -} - -public void OnClientPutInServer(int client) -{ - if (!IsFakeClient(client)) - SDKHook(client, SDKHook_PostThinkPost, SDK_OnPostThink_Post); -} - -void SDK_OnPostThink_Post(int iClient) -{ - int buttons = GetClientButtons(iClient); - if (buttons & IN_RELOAD && !(buttons & IN_USE)) { - char sWeaponName[ENTITY_MAX_NAME_LENGTH]; - GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); - - int iWeapId = WeaponNameToId(sWeaponName); - if (iWeapId == WEPID_PAIN_PILLS || iWeapId == WEPID_ADRENALINE) { - if (g_bLagCompAvailable && g_bLagComp) { - g_iPasser = iClient; // better detection in "WantsLagCompensationOnEntity" - L4D2_LagComp_StartLagCompensation(iClient, LAG_COMPENSATE_BOUNDS); - } - - int iTarget = -1; - if (g_bLOSClear) - iTarget = GetClientAimTargetLOS(iClient, true); - else - iTarget = GetClientAimTarget(iClient, true); - - if (iTarget > 0 && GetClientTeam(iTarget) == L4D2Team_Survivor && !IsPlayerIncap(iTarget)) { - int iTargetWeaponIndex = GetPlayerWeaponSlot(iTarget, L4D2WeaponSlot_LightHealthItem); - - if (iTargetWeaponIndex == -1) { - float fClientOrigin[3], fTargetOrigin[3]; - GetClientAbsOrigin(iClient, fClientOrigin); - GetClientAbsOrigin(iTarget, fTargetOrigin); - - if (GetVectorDistance(fClientOrigin, fTargetOrigin, true) < g_flSqRange) { - // Remove item - int iGiverWeaponIndex = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_LightHealthItem); - RemovePlayerItem(iClient, iGiverWeaponIndex); - - #if (SOURCEMOD_V_MINOR == 11) || USE_GIVEPLAYERITEM - RemoveEntity(iGiverWeaponIndex); - iGiverWeaponIndex = GivePlayerItem(iTarget, sWeaponName); // Fixed only in the latest version of sourcemod 1.11 - #else - EquipPlayerWeapon(iTarget, iGiverWeaponIndex); - #endif - - // If the entity was sucessfully given to the player - if (iGiverWeaponIndex > 0) { - // Call Event - Handle hFakeEvent = CreateEvent("weapon_given"); - SetEventInt(hFakeEvent, "userid", GetClientUserId(iTarget)); - SetEventInt(hFakeEvent, "giver", GetClientUserId(iClient)); - SetEventInt(hFakeEvent, "weapon", iWeapId); - SetEventInt(hFakeEvent, "weaponentid", iGiverWeaponIndex); - - FireEvent(hFakeEvent); - } - } - } - } - - if (g_bLagCompAvailable && g_bLagComp) { - L4D2_LagComp_FinishLagCompensation(iClient); - g_iPasser = -1; - } - } - } -} - -int GetClientAimTargetLOS(int client, bool only_clients = true) -{ - float pos[3], ang[3]; - GetClientEyePosition(client, pos); - GetClientEyeAngles(client, ang); - - // "GetClientAimTarget" uses (MASK_SOLID|CONTENTS_HITBOX|CONTENTS_DEBRIS) - static const int LOS_CLEAR_FLAGS = MASK_VISIBLE_AND_NPCS|CONTENTS_GRATE|CONTENTS_HITBOX|CONTENTS_DEBRIS; - Handle tr = TR_TraceRayFilterEx(pos, ang, LOS_CLEAR_FLAGS, RayType_Infinite, TraceFilter_IgnoreSelf, client); - - int entity = -1; - float end[3]; - if (TR_DidHit(tr)) - { - entity = TR_GetEntityIndex(tr); - TR_GetEndPosition(end, tr); - } - - delete tr; - - if (entity == -1) - return -1; - - if (only_clients) - { - if (!entity || entity > MaxClients) - return -1; - } - - return entity; -} - -bool TraceFilter_IgnoreSelf(int entity, int contentsMask, any data) -{ - return data != entity; -} - -bool IsPlayerIncap(int iClient) -{ - return (GetEntProp(iClient, Prop_Send, "m_isIncapacitated", 1) == 1); -} - -ConVar CreateConVarHook(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, - ConVarChanged callback) -{ - ConVar cv = CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); - - Call_StartFunction(INVALID_HANDLE, callback); - Call_PushCell(cv); - Call_PushNullString(); - Call_PushNullString(); - Call_Finish(); - - cv.AddChangeHook(callback); - - return cv; -} +#pragma semicolon 1 +#pragma newdecls required + +#include +#include +#include +#define L4D2UTIL_STOCKS_ONLY 1 +#include +#undef REQUIRE_PLUGIN +#include + +#define GAMEDATA "pill_passer" +#define FUNCTION_1 "CTerrorPlayer::ThrowWeapon" +#define FUNCTION_2 "CTerrorWeapon::OnDropped" + +public Plugin myinfo = +{ + name = "Easier Pill Passer", + author = "CanadaRox, A1m`, Forgetest, Hitomi", + description = "Lets players pass pills and adrenaline with +reload when they are holding one of those items", + version = "1.7.0", + url = "https://github.com/cy115/" +}; + +bool + g_bLateLoad, + g_bDisableM2, + g_bIsCallByPlugin, + g_bLagCompAvailable; + +float + g_flSqRange; + +bool + g_bLOSClear, + g_bLagComp; + +int + g_iPasser = -1; + +static Handle + g_hThrowWeapon, + g_hOnDropped; + +public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max) +{ + g_bLateLoad = late; + + return APLRes_Success; +} + +public void OnPluginStart() +{ + InitGameData(); + + CreateConVarHook("pill_passer_range", + "274.0", + "Max distance to transfer pills between players.", + FCVAR_CHEAT, + true, 0.0, false, 0.0, + CvarChg_Range); + + CreateConVarHook("pill_passer_los_clear", + "0", + "Whether to require LOS clear when passing pills.", + FCVAR_CHEAT, + true, 0.0, true, 1.0, + CvarChg_LOSClear); + + CreateConVarHook("pill_passer_lag_compensate", + "1", + "Whether to enable lag compensation when passing pills.", + FCVAR_CHEAT, + true, 0.0, true, 1.0, + CvarChg_LagComp); + + CreateConVarHook("pill_passer_block_m2", + "0", + "Whether to disable m2 passing pills.", + FCVAR_CHEAT, + true, 0.0, true, 1.0, + CvarChg_Block); + + if (g_bLateLoad) { + for (int i = 1; i <= MaxClients; ++i) { + if (IsClientInGame(i)) { + OnClientPutInServer(i); + } + } + } +} + +void InitGameData() +{ + GameData hGamedata = new GameData(GAMEDATA); + if (!hGamedata) { + SetFailState("Missing gamedata \"%s.txt\"", GAMEDATA); + } + + StartPrepSDKCall(SDKCall_Player); + if (!PrepSDKCall_SetFromConf(hGamedata, SDKConf_Signature, FUNCTION_1)) { + SetFailState("Error finding the '%s' signature.", FUNCTION_1); + } else { + PrepSDKCall_AddParameter(SDKType_CBaseEntity, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_Float, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain); + PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain); + g_hThrowWeapon = EndPrepSDKCall(); + } + + DynamicDetour hDetour = DynamicDetour.FromConf(hGamedata, FUNCTION_1); + if (!hDetour) { + SetFailState("Failed to setup detour \"%s\"", FUNCTION_1); + } + + if (!hDetour.Enable(Hook_Pre, OnCTerrorPlayerThrowWeaponPre)) { + SetFailState("Failed to create detour pre-hook \"%s\"", FUNCTION_1); + } + + StartPrepSDKCall(SDKCall_Entity); + if (!PrepSDKCall_SetFromConf(hGamedata, SDKConf_Signature, FUNCTION_2)) { + SetFailState("Error finding the '%s' signature.", FUNCTION_2); + } else { + PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + PrepSDKCall_AddParameter(SDKType_CBasePlayer, SDKPass_Pointer); + g_hOnDropped = EndPrepSDKCall(); + } + + delete hGamedata; +} + +public void OnAllPluginsLoaded() +{ + g_bLagCompAvailable = LibraryExists("l4d2_lagcomp_manager"); +} + +public void OnLibraryAdded(const char[] name) +{ + if (!strcmp(name, "l4d2_lagcomp_manager")) { + g_bLagCompAvailable = true; + } +} + +public void OnLibraryRemoved(const char[] name) +{ + if (!strcmp(name, "l4d2_lagcomp_manager")) { + g_bLagCompAvailable = false; + } +} + +void CvarChg_Range(ConVar convar, const char[] oldValue, const char[] newValue) +{ + float val = convar.FloatValue; + g_flSqRange = val * val; +} + +void CvarChg_LOSClear(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_bLOSClear = convar.BoolValue; +} + +void CvarChg_LagComp(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_bLagComp = convar.BoolValue; +} + +void CvarChg_Block(ConVar convar, const char[] oldValue, const char[] newValue) +{ + g_bDisableM2 = convar.BoolValue; +} + +public Action L4D2_LagComp_OnWantsLagCompensationOnEntity(int client, int entity, bool &result, int buttons, int impulse) +{ + if (client != g_iPasser) { + return Plugin_Continue; + } + + if (entity <= 0 || entity > MaxClients || !IsClientInGame(entity)) { + return Plugin_Continue; + } + + if (GetClientTeam(entity) != 2) { + return Plugin_Continue; + } + + if (!IsPlayerAlive(entity)) { + return Plugin_Continue; + } + + result = true; + + return Plugin_Handled; +} + +public void OnClientPutInServer(int client) +{ + if (!IsFakeClient(client)) { + SDKHook(client, SDKHook_PostThinkPost, SDK_OnPostThink_Post); + } +} + +void SDK_OnPostThink_Post(int iClient) +{ + int buttons = GetClientButtons(iClient); + if (buttons & IN_RELOAD && !(buttons & IN_USE)) { + char sWeaponName[ENTITY_MAX_NAME_LENGTH]; + GetClientWeapon(iClient, sWeaponName, sizeof(sWeaponName)); + int iWeapId = WeaponNameToId(sWeaponName); + if (iWeapId == WEPID_PAIN_PILLS || iWeapId == WEPID_ADRENALINE) { + if (g_bLagCompAvailable && g_bLagComp) { + g_iPasser = iClient; + L4D2_LagComp_StartLagCompensation(iClient, LAG_COMPENSATE_BOUNDS); + } + + int iTarget = -1; + if (g_bLOSClear) { + iTarget = GetClientAimTargetLOS(iClient, true); + } else { + iTarget = GetClientAimTarget(iClient, true); + } + + if (iTarget > 0 && GetClientTeam(iTarget) == L4D2Team_Survivor && !IsPlayerIncap(iTarget)) { + int iTargetWeaponIndex = GetPlayerWeaponSlot(iTarget, L4D2WeaponSlot_LightHealthItem); + if (iTargetWeaponIndex == -1) { + float fClientOrigin[3], fTargetOrigin[3]; + GetClientAbsOrigin(iClient, fClientOrigin); + GetClientAbsOrigin(iTarget, fTargetOrigin); + if (GetVectorDistance(fClientOrigin, fTargetOrigin, true) < g_flSqRange) { + int iGiverWeaponIndex = GetPlayerWeaponSlot(iClient, L4D2WeaponSlot_LightHealthItem); + g_bIsCallByPlugin = true; + SDKCall(g_hThrowWeapon, iClient, iGiverWeaponIndex, iTarget, 512.0, 0, 0); + g_bIsCallByPlugin = false; + SDKCall(g_hOnDropped, iGiverWeaponIndex, iClient, iTarget); + } + } + } + + if (g_bLagCompAvailable && g_bLagComp) { + L4D2_LagComp_FinishLagCompensation(iClient); + g_iPasser = -1; + } + } + } +} + +int GetClientAimTargetLOS(int client, bool only_clients = true) +{ + float pos[3], ang[3]; + GetClientEyePosition(client, pos); + GetClientEyeAngles(client, ang); + // "GetClientAimTarget" uses (MASK_SOLID|CONTENTS_HITBOX|CONTENTS_DEBRIS) + static const int LOS_CLEAR_FLAGS = MASK_VISIBLE_AND_NPCS|CONTENTS_GRATE|CONTENTS_HITBOX|CONTENTS_DEBRIS; + Handle tr = TR_TraceRayFilterEx(pos, ang, LOS_CLEAR_FLAGS, RayType_Infinite, TraceFilter_IgnoreSelf, client); + int entity = -1; + float end[3]; + if (TR_DidHit(tr)) { + entity = TR_GetEntityIndex(tr); + TR_GetEndPosition(end, tr); + } + + delete tr; + + if (entity == -1) { + return -1; + } + + if (only_clients) { + if (!entity || entity > 32) { + return -1; + } + } + + return entity; +} + +bool TraceFilter_IgnoreSelf(int entity, int contentsMask, any data) { + return data != entity; +} + +bool IsPlayerIncap(int iClient) { + return (GetEntProp(iClient, Prop_Send, "m_isIncapacitated", 1) == 1); +} + +ConVar CreateConVarHook(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, + ConVarChanged callback) { + ConVar cv = CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); + + Call_StartFunction(INVALID_HANDLE, callback); + Call_PushCell(cv); + Call_PushNullString(); + Call_PushNullString(); + Call_Finish(); + + cv.AddChangeHook(callback); + + return cv; +} + +MRESReturn OnCTerrorPlayerThrowWeaponPre(int pThis, DHookReturn hReturn, DHookParam hParams) +{ + if (!g_bDisableM2) { + return MRES_Ignored; + } else { // If Disable M2 passing pills + if (g_bIsCallByPlugin) { + int entity = hParams.Get(1); + if (entity && IsValidEntity(entity)) { + char weapon[32]; + GetEntityClassname(entity, weapon, sizeof(weapon)); + if (StrEqual(weapon, "weapon_pain_pills") || StrEqual(weapon, "weapon_adrenaline")) { + return MRES_Ignored; + } + } + } else { + hReturn.Value = 0; + return MRES_Supercede; + } + + return MRES_Ignored; + } +} \ No newline at end of file From 7c6204a843706fda7edf11066ee2a57e6b1325c6 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:39:02 +0800 Subject: [PATCH 08/11] Update generalfixes.cfg --- cfg/generalfixes.cfg | 1 - 1 file changed, 1 deletion(-) diff --git a/cfg/generalfixes.cfg b/cfg/generalfixes.cfg index 4de4c6ca4..db039efac 100644 --- a/cfg/generalfixes.cfg +++ b/cfg/generalfixes.cfg @@ -70,7 +70,6 @@ sm plugins load fixes/l4d_fix_stagger_dir.smx sm plugins load fixes/l4d2_fix_rocket_pull.smx sm plugins load optional/l4d_return_thrown_items.smx sm plugins load fixes/l4d_prop_touching_rules.smx -sm plugins load optional/block_m2_giver.smx // Anti-Cheat. sm plugins load anticheat/l4d2_noghostcheat.smx From 41055988c807b246643bc0bdcfa1b8495d585551 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:40:44 +0800 Subject: [PATCH 09/11] Delete addons/sourcemod/gamedata/block_m2_giver.txt --- addons/sourcemod/gamedata/block_m2_giver.txt | 49 -------------------- 1 file changed, 49 deletions(-) delete mode 100644 addons/sourcemod/gamedata/block_m2_giver.txt diff --git a/addons/sourcemod/gamedata/block_m2_giver.txt b/addons/sourcemod/gamedata/block_m2_giver.txt deleted file mode 100644 index e78099eb7..000000000 --- a/addons/sourcemod/gamedata/block_m2_giver.txt +++ /dev/null @@ -1,49 +0,0 @@ -"Games" -{ - "left4dead2" - { - "Functions" - { - "CY115::CTerrorPlayer::ThrowWeapon" - { - "signature" "CTerrorPlayer::ThrowWeapon" - "callconv" "thiscall" - "return" "int" - "this" "entity" - "arguments" - { - "a1" - { - "type" "cbaseentity" - } - "a2" - { - "type" "cbaseentity" - } - "a3" - { - "type" "float" - } - "a4" - { - "type" "charptr" - } - "a5" - { - "type" "charptr" - } - } - } - } - - "Signatures" - { - "CTerrorPlayer::ThrowWeapon" - { - "library" "server" - "linux" "@_ZN13CTerrorPlayer11ThrowWeaponEP13CTerrorWeaponPS_fPKcS4_" - "windows" "\x55\x89\xE5\x57\x56\x53\x81\xEC\x6C\x01\x00\x00\x8B\x75\x0C" - } - } - } -} From 8f2ac595b6da1178421423b34eb1914eb36435d4 Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:40:55 +0800 Subject: [PATCH 10/11] Delete addons/sourcemod/scripting/block_m2_giver.sp --- addons/sourcemod/scripting/block_m2_giver.sp | 81 -------------------- 1 file changed, 81 deletions(-) delete mode 100644 addons/sourcemod/scripting/block_m2_giver.sp diff --git a/addons/sourcemod/scripting/block_m2_giver.sp b/addons/sourcemod/scripting/block_m2_giver.sp deleted file mode 100644 index c1c9ca724..000000000 --- a/addons/sourcemod/scripting/block_m2_giver.sp +++ /dev/null @@ -1,81 +0,0 @@ -#pragma semicolon 1 -#pragma newdecls required - -#define GAMEDATA "block_m2_giver" -#define FUNCTION "CY115::CTerrorPlayer::ThrowWeapon" - -enum { - BLOCKTYPE_NONE = 0, - BLOCKTYPE_PILLS, - BLOCKTYPE_ADRENALINE, - - BLOCKTYPE_SIZE -}; - -#include - -int - g_iBlockType = 0; - -public void OnPluginStart() -{ - InitGameData(); - - CreateConVarHook("block_item_giver_mask", "1", "Block Pass Item By M2[0=dont block, 1=block pills, 2=block adrenaline, 3=block both]", _, true, 0.0, true, 3.0, OnBlockTypeChanged).IntValue; -} - -void InitGameData() -{ - GameData gd = new GameData(GAMEDATA); - if (!gd) { - SetFailState("Missing gamedata \"%s.txt\"", GAMEDATA); - } - - DynamicDetour hDetour = DynamicDetour.FromConf(gd, FUNCTION); - if (!hDetour) { - SetFailState("Failed to setup detour \"%s\"", FUNCTION); - } - - if (!hDetour.Enable(Hook_Pre, OnCTerrorPlayerThrowWeaponPre)) { - SetFailState("Failed to create detour pre-hook \"%s\"", FUNCTION); - } - - delete hDetour; - delete gd; -} - -void OnBlockTypeChanged(ConVar convar, const char[] oldValue, const char[] newValue) -{ - g_iBlockType = convar.IntValue; -} - -MRESReturn OnCTerrorPlayerThrowWeaponPre(int pThis, DHookReturn hReturn, DHookParam hParams) -{ - int entity = hParams.Get(1); - if (entity && IsValidEntity(entity)) { - char weapon[64]; - GetEntityClassname(entity, weapon, sizeof(weapon)); - if ((StrEqual(weapon, "weapon_pain_pills") && (g_iBlockType & BLOCKTYPE_PILLS)) || - StrEqual(weapon, "weapon_adrenaline") && (g_iBlockType & BLOCKTYPE_ADRENALINE)) { - return MRES_Supercede; - } - - } - - return MRES_Ignored; -} - -ConVar CreateConVarHook(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, ConVarChanged callback) { - ConVar convar = CreateConVar(name, defaultValue, description, flags, hasMin, min, hasMax, max); - - Call_StartFunction(INVALID_HANDLE, callback); - Call_PushCell(convar); - Call_PushNullString(); - Call_PushNullString(); - Call_Finish(); - - convar.AddChangeHook(callback); - - return convar; -} \ No newline at end of file From f2d27641c1efafd8a417060e60c01941eb8e281e Mon Sep 17 00:00:00 2001 From: 0d00 <104008433+cy115@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:41:07 +0800 Subject: [PATCH 11/11] Delete addons/sourcemod/plugins/optional/block_m2_giver.smx --- .../plugins/optional/block_m2_giver.smx | Bin 4365 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 addons/sourcemod/plugins/optional/block_m2_giver.smx diff --git a/addons/sourcemod/plugins/optional/block_m2_giver.smx b/addons/sourcemod/plugins/optional/block_m2_giver.smx deleted file mode 100644 index aed93ce73a0e6ba1c8aa100370ea520dd9d16dfd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4365 zcmYk11z6Kv`^QHKk`D?ZgGneYA)NvW2ux5?x;w^%Q8EEhrh?L?BOXE;q?<9_L&yX~ zN_r!uM>qU``uhCe_gvTK`hL!R?sK2(XlXq(A}1qbUv>*^Y;4$1FkQ$Ic3Do7BnJ2#9|%MZ%#sIu zg&zcZ1EeNEAkdf&q#?j%K@g}ENNa#Lz*&Iw1Q__^!GJFUt^wpL01+V&$O_0LfR})C z1DOR-0Js?y2viLCIq>*jK-K^-iGx7OKz;&%0{*Mk3vdp&7&(BWkCQV<%*h^M4-$j> zJ9xP}`u&ywdtX3c_6YX?=ilNDgf9Z&{-568=IxAd^Ktr9{N zcKM&3pEKgm&e6->&+os7F7D1=z&J4{2Ujr{cduXX{!%Y@*uUxybMg64@!z+9cer}_ zIM{pr+wSA|%Y(*}Eo|XdChV$#fz^6r(v$h>BF5Ib*;Jns^0I4~JF3trgZ$oZsVTZV ztvypNflsQNCqgK`+~-36)P6_I?%jFDevGBS8J9}Q53rY9c}r_pX<_^q;$bn1I+bRb zMXg!bw90hr{;HlYHY5E6vwhmD5{B8%2-}}Xguc)gm8LvZ{OdbS;+->Jnpp0eYJxna zYC&lVcZvKm6Fdxo#<+}c@B#4p8&rr1uC#@;h89< zLL#GQLoRqd4W*P#%$J#9XV@=Bg;?UO2jN98@~36~y-;3A>;|ugqm)XCncv_7zZwJe zan|49Jzp9dox$Z$9D`ef3b=OwPAxOR%&`9grBp=J_iT71Gob|5&s$hfl%5b~2t=be zhT+Z(foeENKRnj6VHUiehf*pd+I)vEN>7A<^`(1yM2Fxa(pIUcX1!lCb5P^CM6cgB zzQgZHPXIR>e$CDtf{S}J_<`3GP@a08N7lGqj|MV^dQ04p%!E3_KJcINU;lxE*C7le ziVvz6+#19fMm`eP`{8w{<8+i#4l%~P!JT102c`6pDCW^H?9yYS`~Opd!Rxme_G?ff zj~UnPQ>Z!veAn$w^lja1Tw6L0gbrpV z8QR!wKvTtSZSIC7YU*+cJ7*eY`Z$cg^g}?M$K9S1V4fy=^Av9z^9U{a0cA z`?!Np?5v_Q9-d;%=`~ zh$!fv9qxU8=WT{P?A(5s6@ttzo%M{K_jAfJ?VS}{Uzyr_cc>rMg^XT%d&n<89Zt8L z?sQ!0djIh`Wz*k%#$r>8B}o{|>@IUnoBS@Qs@+-Cv4O~O#xg}l<*jXr@f*zBiQ%5n zJwwq+w_`hn`p^xnT$&9QLf3QWa)++l-8iPX$Nz=qxFUs{$36DuviG_}jm-AYpR2rR3z*)2+N@ybOzk1~HehbN z9EzQ>dOEN0XyN&k=BBY@;J2|w%{9DcE6d1XkLTbQ7un^8eK4YG^sVCPi56tv%`x;l zCxfD_&hwa%`pVE}DlFDc`Rqr3*SjvPR5AG37nD3+>aokQfL;bY~ z1~Py7FtE@FsXQnYdTmH(YxiNnL36RuQ_QWtt_{EJmAQ_aZJD?bowlOo$SSXhqz`v> z6t;ZW#Rpg4K?)8WH8Q^*u69Y&CjARNlt^>Xs(f-&{=C zYOIH-WYdZg>u7eW1B3tZ8|j=G%)4MMQDF>`D^h0*Dk`4km-!j-DSw%~FQaH1&9XF_ z?6BFPcu#EjZ?wT;*E|>@wanRQ_Z+5`!C`H|uV+mD%gb5#CL( zAJ*$6o<41_G751ka31y?VtVJ2YhGDqI9%dvjYk){LQ@{0;e~ng z=Zo99jJvLJ>XVf)-b8%*i=eJByF8dFDRz}@iT8NZ{GU0g?`#K<&wWcOY_k2(esh6m ze0MW9rzshqx2f{%AIXxC)vJBGpOko~Vh5U|JpUT5>+;j4CK2b5M zt*gvtd;mReTox2~XPhaEg(3b-D6jm@-tlej?l(Ltrk5J0uFX}{f@LY2^On<0E>#!O z)-E%8Wfu?M^>rztGWzOPcEn9HS6fFHEF)hylZmS+&4i5A*&oXuv>LIVQb=Hgnb0u` zy|;zCL%*^*>l=uth=>WpMZiWRh^=YLH5MsW%vEX6!J4(!g`c64)q-d-E6q2LiZL`l zT+xo@g68XmMnxfm8+@Kw3icsYYoUQ&WsKvO9g~H7oqiZ<#Yji6x&$tx=h zFJE<&2~ogMcx41IX^$QVB|6!uM0vnqZyt=ekBB2Ily|;xS%*vj%kp5e%vE z*`E|Etq(!a`pvC};@jQIHWqG|#H^JY-&=c~P>X)T_mXBb&38&-sh^-Bx@SMbvhd<% z`h+$It&{9q$=}) zwuxlc{Y9h0{7mhkOEd>ijxsGz^{f6}yczfXZZ9DeH}Kv|HSq-#mzf?W+~*bF+UBm= zdxfm(R9o0#8Wku^=T}WgVCHh_SBJdv-W(F$Vz!HN`;0XD4v&B8r&^qt<(fB%=!@mg`(eS4(KuQgO`7xStb~M|IApjk2X53a-qKM9Gpp*vz?0N87r1tRjB9hV)Hp z5|!jm=23vxvU%gilf!0`8f2i@sPPINX_X`>-hCYxZ6uZY&cNnj?RHKgn=i4^sH@#I zF^=w=EDu}u@gW7RVr##H1_zBroIYKn;HgGe zIP2`1Yu~Tgf@uaOS#_1na+GZ!=$@OUCt!k1wYi$)`0!`oef-EF)w0|{zPn>3{JVpSMU z$iiOil7|`Z-aXS^rVrcMxqf68E~|&geiyg9f2qpr=*KJMjy$Pgr=ODKig2ev>U7Cv zif>b^)DSJ{kdd-5okIg#$N?Q8cXhlo{A0hS66uk&YF;+=l5Nh&&pT3Aq_04+Z37qNL_5a}2&zklG(qv=73X?> z%p_IhEj>qnR?<_9@tOFpDoJwpTzTmrmW+XL(e85`TfGiJ3CmK!&N!mM)kZde-Ngo@ zS~&Tp(e4J zu^sgx3yGExOt?p{P~rBxjsD;k!Ge&CR4RY0s%5t`$@ZgI< zGH{`QbNsVbtmn_aE7Xpf7+S6b(F8$A7YVuqX*erMhOmo`#&U#1t_I1GH-~3n)d_l7 zNeOCYnilqhppuiqZQ~Lv5gV#KkT~cOh1Au)R;+%L7a1dH1O&xex_gtAUsobKF0@fo zw1Zd*juZ!mZ#b5=P`A+Ebg(hIGfN*tb?Asz{+aHXD1Iak`glVXmbh)x$@}B&399n) z!9~nm9zKdfO|cN-qFkkYE$yf8mg1Ib2VL~sJhQd%l-l+Mk`_3NJ-G6*#C0aKmy%oG zXUw#&MLZyTG$4=fqWe%Uwe{I!)Zw)`p-fsV+|ykdG_o0K%GE=?wuRMVLm(Q^lvfI; zunbOF0gVAJc1dI&)0Y}iQ*|2GNEe==-EWgK_RCYi=JCnmeN~xxtQnu!BrgsNDCk8o zz0>2h82D%x!68rtnNu7UQ72w{});v|hZjIGrM%(ZVOyWQ$JGQ={7}-f}0Zcy;kgD@^+K z`l8N<#KcT9UTA@OLW?l7kb8kzNw9BZ4m~F9LAhZPJBC|tiW90sq1>pLlHl^pDJzHG Yvc^V_Jq;$2zhhY=l7GULEl-a5KfARsUH||9