Member
|
09-21-2021
, 01:23
Re: [L4D1/2] Don't switch weapon to secondary slot when pick up pistols
|
#3
|
Quote:
Originally Posted by Marttt
Try the following codes:
Method 1 (may be a bit glitch)
Spoiler
PHP Code:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#pragma semicolon 1
#pragma newdecls required
public void OnPluginStart()
{
for (int client = 1; client <= MaxClients; client++)
{
if (!IsClientInGame(client))
continue;
OnClientPutInServer(client);
}
}
public void OnClientPutInServer(int client)
{
SDKHook(client, SDKHook_WeaponEquipPost, OnWeaponEquipPost);
}
public void OnWeaponEquipPost(int client, int weapon)
{
if (!IsValidEntity(weapon))
return;
int team = GetClientTeam(client);
if (team != 2)
return;
int secondaryWeapon = GetPlayerWeaponSlot(client, 1);
if (weapon != secondaryWeapon)
return;
int lastWeapon = GetEntPropEnt(client, Prop_Send, "m_hLastWeapon");
if (!IsValidEntity(lastWeapon))
return;
SetEntPropEnt(client, Prop_Send, "m_hActiveWeapon", lastWeapon);
}
Method 2 (didn't have much time to work on this one, need some rework)
Spoiler
PHP Code:
#include <sourcemod>
#include <sdktools>
#include <sdkhooks>
#pragma semicolon 1
#pragma newdecls required
public void OnPluginStart()
{
for (int client = 1; client <= MaxClients; client++)
{
if (!IsClientInGame(client))
continue;
OnClientPutInServer(client);
}
}
int weapon2;
int count;
public void OnClientPutInServer(int client)
{
SDKHook(client, SDKHook_WeaponEquip, OnWeaponEquipPost);
SDKHook(client, SDKHook_WeaponCanSwitchTo, OnWeaponCanSwitch);
}
public void OnWeaponEquipPost(int client, int weapon)
{
if (!IsValidEntity(weapon))
return;
int team = GetClientTeam(client);
if (team != 2)
return;
int lastWeapon = GetEntPropEnt(client, Prop_Send, "m_hLastWeapon");
if (!IsValidEntity(lastWeapon))
return;
char classname[14];
GetEntityClassname(weapon, classname, sizeof(classname));
if (StrEqual(classname, "weapon_pistol"))
{
count = 0;
weapon2 = weapon;
}
}
public Action OnWeaponCanSwitch(int client, int weapon)
{
if (weapon2 != weapon)
{
count = 0;
}
else
{
count++;
if (count == 1 || count == 2) // for some reason pistol triggers the event twice on my tests
return Plugin_Stop;
}
return Plugin_Continue;
}
|
As far as I know, WeaponEquip doesn't fire when picking up the second pistol for both games. Internally uses EquipSecondWeapon.
I've been trying to make memory patches on this, only to get crashes on both games on Windows, but it seems to work on Linux L4D2.
Partial pseudocode from EquipSecondWeapon:
PHP Code:
if ( v4 ) // = (CBaseCombatCharacter *)CTerrorWeapon::GetPlayerOwner(this);
{
if ( this == (CTerrorGun *)CBaseCombatCharacter::GetActiveWeapon(v4) )
{
if ( *((_BYTE *)this + 6114) ) // m_inInitialPickup
(*(void (__cdecl **)(CTerrorGun *))(*(_DWORD *)this + 1128))(this); // CTerrorGun::Reload()
}
else
{
if ( CBaseCombatCharacter::GetActiveWeapon(v4) )
{
v9 = CBaseCombatCharacter::GetActiveWeapon(v4);
(*(void (__cdecl **)(int, _DWORD))(*(_DWORD *)v9 + 1064))(v9, 0); // CTerrorGun::Holster(CBaseCombatWeapon*)
}
CBaseCombatCharacter::SetActiveWeapon(v4, this);
(*(void (__cdecl **)(CTerrorGun *))(*(_DWORD *)this + 1060))(this); // CTerrorGun::Deploy()
}
So I aimed to patch those calls of Holster, SetActiveWeapon and Deploy to NOPs. However as mentioned above, it's crashing on Windows.
My detour setup: (There should be another detour on CWeaponSpawn::Use, otherwise it only functions when picking up dropped pistols)
PHP Code:
Handle hDetour = null;
if (!g_bLeft4Dead2)
{
if (os == 1) // Linux
{
hDetour = DHookCreateDetour(Address_Null, CallConv_CDECL, ReturnType_Void, ThisPointer_Ignore);
DHookAddParam(hDetour, HookParamType_CBaseEntity);
DHookAddParam(hDetour, HookParamType_CBaseEntity);
} else {
hDetour = DHookCreateDetour(Address_Null, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity);
DHookAddParam(hDetour, HookParamType_Int);
DHookAddParam(hDetour, HookParamType_CBaseEntity);
DHookAddParam(hDetour, HookParamType_Int);
DHookAddParam(hDetour, HookParamType_Int);
}
}
else
{
if (os == 1) // Linux
{
hDetour = DHookCreateDetour(Address_Null, CallConv_CDECL, ReturnType_Void, ThisPointer_Ignore);
DHookAddParam(hDetour, HookParamType_CBaseEntity);
DHookAddParam(hDetour, HookParamType_CBaseEntity);
DHookAddParam(hDetour, HookParamType_Int);
} else {
hDetour = DHookCreateDetour(Address_Null, CallConv_THISCALL, ReturnType_Void, ThisPointer_CBaseEntity);
DHookAddParam(hDetour, HookParamType_CBaseEntity);
DHookAddParam(hDetour, HookParamType_Int);
DHookAddParam(hDetour, HookParamType_Int);
DHookAddParam(hDetour, HookParamType_Int);
}
}
if (!hDetour)
SetFailState("detour");
if (!DHookSetFromConf(hDetour, conf, SDKConf_Signature, "CTerrorGun_Use"))
SetFailState("DHookSetFromConf");
if (os == 1) // Linux
{
if (!DHookEnableDetour(hDetour, false, CTerrorGun_OnUse) || !DHookEnableDetour(hDetour, true, CTerrorGun_OnUsePost))
SetFailState("DHookEnableDetour");
} else {
if (!DHookEnableDetour(hDetour, false, Windows_CTerrorGun_OnUse) || !DHookEnableDetour(hDetour, true, Windows_CTerrorGun_OnUsePost))
SetFailState("DHookEnableDetour");
}
Last edited by Forgetest; 09-21-2021 at 01:36.
|
|