New plugin: FixVPhysicsCrush

refactor FixGameUI to new syntax.
This commit is contained in:
BotoX 2019-09-28 17:15:29 +02:00
parent f528a56118
commit 7f656f3d73
3 changed files with 176 additions and 35 deletions

View File

@ -1,26 +1,24 @@
#pragma semicolon 1 #pragma semicolon 1
#pragma newdecls required
#include <sourcemod> #include <sourcemod>
#include <sdktools_entoutput>
#include <sdktools_entinput>
#include <sdktools_engine>
#include <sdkhooks> #include <sdkhooks>
#include <sdktools> #include <sdktools>
#include <dhooks> #include <dhooks>
public Plugin:myinfo = public Plugin myinfo =
{ {
name = "FixGameUI", name = "FixGameUI",
author = "hlstriker + GoD-Tony", author = "hlstriker + GoD-Tony",
description = "Fixes game_ui entity bug.", description = "Fixes game_ui entity bug and blocks DMG_CRUSH.",
version = "1.0", version = "1.0",
url = "" url = ""
} }
new g_iAttachedGameUI[MAXPLAYERS+1]; Handle g_hAcceptInput;
new Handle:g_hAcceptInput = INVALID_HANDLE; int g_iAttachedGameUI[MAXPLAYERS + 1];
public OnPluginStart() public void OnPluginStart()
{ {
HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post); HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post);
@ -30,17 +28,13 @@ public OnPluginStart()
// Gamedata. // Gamedata.
Handle hConfig = LoadGameConfigFile("sdktools.games"); Handle hConfig = LoadGameConfigFile("sdktools.games");
if (hConfig == INVALID_HANDLE) if (hConfig == INVALID_HANDLE)
{
SetFailState("Couldn't load sdktools game config!"); SetFailState("Couldn't load sdktools game config!");
return;
}
new offset = GameConfGetOffset(hConfig, "AcceptInput"); int offset = GameConfGetOffset(hConfig, "AcceptInput");
if (offset == -1) if (offset == -1)
{
SetFailState("Failed to find AcceptInput offset"); SetFailState("Failed to find AcceptInput offset");
}
CloseHandle(hConfig); delete hConfig;
// DHooks. // DHooks.
g_hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, Hook_AcceptInput); g_hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, Hook_AcceptInput);
@ -52,25 +46,25 @@ public OnPluginStart()
} }
public Action:Event_PlayerDeath(Handle:hEvent, const String:szName[], bool:bDontBroadcast) public Action Event_PlayerDeath(Handle hEvent, const char[] szName, bool bDontBroadcast)
{ {
new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid")); int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
RemoveFromGameUI(iClient); RemoveFromGameUI(client);
SetClientViewEntity(iClient, iClient); SetClientViewEntity(client, client);
new iFlags = GetEntityFlags(iClient); int iFlags = GetEntityFlags(client);
iFlags &= ~FL_ONTRAIN; iFlags &= ~FL_ONTRAIN;
iFlags &= ~FL_FROZEN; iFlags &= ~FL_FROZEN;
iFlags &= ~FL_ATCONTROLS; iFlags &= ~FL_ATCONTROLS;
SetEntityFlags(iClient, iFlags); SetEntityFlags(client, iFlags);
} }
public OnClientDisconnect(iClient) public void OnClientDisconnect(int client)
{ {
RemoveFromGameUI(iClient); RemoveFromGameUI(client);
} }
public GameUI_PlayerOn(const String:szOutput[], iCaller, iActivator, Float:fDelay) public void GameUI_PlayerOn(const char[] szOutput, int iCaller, int iActivator, float fDelay)
{ {
if(!(1 <= iActivator <= MaxClients)) if(!(1 <= iActivator <= MaxClients))
return; return;
@ -78,7 +72,7 @@ public GameUI_PlayerOn(const String:szOutput[], iCaller, iActivator, Float:fDela
g_iAttachedGameUI[iActivator] = EntIndexToEntRef(iCaller); g_iAttachedGameUI[iActivator] = EntIndexToEntRef(iCaller);
} }
public GameUI_PlayerOff(const String:szOutput[], iCaller, iActivator, Float:fDelay) public void GameUI_PlayerOff(const char[] szOutput, int iCaller, int iActivator, float fDelay)
{ {
if(!(1 <= iActivator <= MaxClients)) if(!(1 <= iActivator <= MaxClients))
return; return;
@ -86,19 +80,19 @@ public GameUI_PlayerOff(const String:szOutput[], iCaller, iActivator, Float:fDel
g_iAttachedGameUI[iActivator] = 0; g_iAttachedGameUI[iActivator] = 0;
} }
RemoveFromGameUI(iClient) void RemoveFromGameUI(int client)
{ {
if(!g_iAttachedGameUI[iClient]) if(!g_iAttachedGameUI[client])
return; return;
new iEnt = EntRefToEntIndex(g_iAttachedGameUI[iClient]); int entity = EntRefToEntIndex(g_iAttachedGameUI[client]);
if(iEnt == INVALID_ENT_REFERENCE) if(entity == INVALID_ENT_REFERENCE)
return; return;
AcceptEntityInput(iEnt, "Deactivate", iClient, iEnt); AcceptEntityInput(entity, "Deactivate", client, entity);
} }
public OnEntityCreated(entity, const String:classname[]) public void OnEntityCreated(int entity, const char[] classname)
{ {
if (StrEqual(classname, "game_ui")) if (StrEqual(classname, "game_ui"))
{ {
@ -106,14 +100,14 @@ public OnEntityCreated(entity, const String:classname[])
} }
} }
public MRESReturn:Hook_AcceptInput(thisptr, Handle:hReturn, Handle:hParams) public MRESReturn Hook_AcceptInput(int thisptr, Handle hReturn, Handle hParams)
{ {
new String:sCommand[128]; char sCommand[128];
DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand)); DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand));
if (StrEqual(sCommand, "Deactivate")) if (StrEqual(sCommand, "Deactivate", false))
{ {
new pPlayer = GetEntPropEnt(thisptr, Prop_Data, "m_player"); int pPlayer = GetEntPropEnt(thisptr, Prop_Data, "m_player");
if (pPlayer == -1) if (pPlayer == -1)
{ {

View File

@ -0,0 +1,19 @@
"Games"
{
"cstrike"
{
"Offsets"
{
"SetGameFlags"
{
"linux" "19"
"windows" "18"
}
"GetGameFlags"
{
"linux" "20"
"windows" "19"
}
}
}
}

View File

@ -0,0 +1,128 @@
#pragma semicolon 1
#pragma newdecls required
#include <sourcemod>
#include <sdktools>
#include <dhooks>
#define FVPHYSICS_NO_IMPACT_DMG 0x0400 // don't do impact damage to anything
public Plugin myinfo =
{
name = "FixVPhysicsCrush",
author = "BotoX",
description = "",
version = "0.0",
url = ""
};
Handle g_hAcceptInput;
Handle g_hSetGameFlags;
Handle g_hGetGameFlags;
int g_hPhysicsObject;
public void OnPluginStart()
{
Handle hGameData = LoadGameConfigFile("sdktools.games");
if(!hGameData)
SetFailState("Couldn't load sdktools gamedata.");
// CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID )
int Offset = GameConfGetOffset(hGameData, "AcceptInput");
if(Offset == -1)
SetFailState("Failed to find AcceptInput offset.");
g_hAcceptInput = DHookCreate(Offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, OnAcceptInput);
if(g_hAcceptInput == INVALID_HANDLE)
SetFailState("Failed to DHook AcceptInput.");
DHookAddParam(g_hAcceptInput, HookParamType_CharPtr);
DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity);
DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity);
DHookAddParam(g_hAcceptInput, HookParamType_Object, 20, DHookPass_ByVal|DHookPass_ODTOR|DHookPass_OCTOR|DHookPass_OASSIGNOP); //varaint_t is a union of 12 (float[3]) plus two int type params 12 + 8 = 20
DHookAddParam(g_hAcceptInput, HookParamType_Int);
hGameData = LoadGameConfigFile("FixGameUI.games");
if(!hGameData)
SetFailState("Couldn't load FixGameUI gamedata.");
// CPhysicsObject::SetGameFlags(unsigned short)
StartPrepSDKCall(SDKCall_Raw);
if(!PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "SetGameFlags"))
{
delete hGameData;
SetFailState("PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, \"SetGameFlags\") failed!");
}
PrepSDKCall_AddParameter(SDKType_PlainOldData, SDKPass_Plain);
g_hSetGameFlags = EndPrepSDKCall();
// CPhysicsObject::GetGameFlags()
StartPrepSDKCall(SDKCall_Raw);
if(!PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, "GetGameFlags"))
{
delete hGameData;
SetFailState("PrepSDKCall_SetFromConf(hGameData, SDKConf_Virtual, \"GetGameFlags\") failed!");
}
PrepSDKCall_SetReturnInfo(SDKType_PlainOldData, SDKPass_Plain);
g_hGetGameFlags = EndPrepSDKCall();
int hCollisionGroup = FindSendPropInfo("CBaseEntity", "m_CollisionGroup");
if (hCollisionGroup == -1)
SetFailState("Couldn't find CBaseEntity::m_CollisionGroup");
// CNetworkVar( int, m_CollisionGroup );
// IPhysicsObject *m_pPhysicsObject;
g_hPhysicsObject = hCollisionGroup + 4;
// Late load.
int entity = INVALID_ENT_REFERENCE;
while((entity = FindEntityByClassname(entity, "phys_thruster")) != INVALID_ENT_REFERENCE)
{
OnEntityCreated(entity, "phys_thruster");
}
}
public void OnEntityCreated(int entity, const char[] classname)
{
if(StrEqual(classname, "phys_thruster"))
{
DHookEntity(g_hAcceptInput, true, entity);
}
}
public MRESReturn OnAcceptInput(int entity, Handle hReturn, Handle hParams)
{
char sCommand[128];
DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand));
if(StrEqual(sCommand, "Activate", false))
{
int attachedObject = GetEntPropEnt(entity, Prop_Data, "m_attachedObject");
if(attachedObject)
{
int vphysObj = GetVPhysicsObject(attachedObject);
if(vphysObj)
{
int flags = VPhysicsGetGameFlags(vphysObj);
flags |= FVPHYSICS_NO_IMPACT_DMG;
VPhysicsSetGameFlags(vphysObj, flags);
}
}
}
}
int VPhysicsGetGameFlags(int vphysicsObj)
{
return SDKCall(g_hGetGameFlags, vphysicsObj);
}
void VPhysicsSetGameFlags(int vphysicsObj, int flags)
{
SDKCall(g_hSetGameFlags, vphysicsObj, flags);
}
int GetVPhysicsObject(int entity)
{
return GetEntData(entity, g_hPhysicsObject, 4);
}