158 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			158 lines
		
	
	
		
			3.6 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
#pragma semicolon 1
 | 
						|
#pragma newdecls required
 | 
						|
 | 
						|
#include <sourcemod>
 | 
						|
#include <sdkhooks>
 | 
						|
#include <sdktools>
 | 
						|
#include <dhooks>
 | 
						|
 | 
						|
public Plugin myinfo =
 | 
						|
{
 | 
						|
	name = "FixGameUI",
 | 
						|
	author = "hlstriker + GoD-Tony",
 | 
						|
	description = "Fixes game_ui entity bug and blocks DMG_CRUSH.",
 | 
						|
	version = "1.0",
 | 
						|
	url = ""
 | 
						|
}
 | 
						|
 | 
						|
Handle g_hAcceptInput;
 | 
						|
ArrayList g_hAttachedClients;
 | 
						|
 | 
						|
public void OnPluginStart()
 | 
						|
{
 | 
						|
	HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post);
 | 
						|
 | 
						|
	HookEntityOutput("game_ui", "PlayerOn", GameUI_PlayerOn);
 | 
						|
	HookEntityOutput("game_ui", "PlayerOff", GameUI_PlayerOff);
 | 
						|
 | 
						|
	g_hAttachedClients = new ArrayList();
 | 
						|
 | 
						|
	// Gamedata.
 | 
						|
	Handle hConfig = LoadGameConfigFile("sdktools.games");
 | 
						|
	if (hConfig == INVALID_HANDLE)
 | 
						|
		SetFailState("Couldn't load sdktools game config!");
 | 
						|
 | 
						|
	int offset = GameConfGetOffset(hConfig, "AcceptInput");
 | 
						|
	if (offset == -1)
 | 
						|
		SetFailState("Failed to find AcceptInput offset");
 | 
						|
 | 
						|
	delete hConfig;
 | 
						|
 | 
						|
	// DHooks.
 | 
						|
	g_hAcceptInput = DHookCreate(offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, Hook_AcceptInput);
 | 
						|
	DHookAddParam(g_hAcceptInput, HookParamType_CharPtr);
 | 
						|
	DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity);
 | 
						|
	DHookAddParam(g_hAcceptInput, HookParamType_CBaseEntity);
 | 
						|
	DHookAddParam(g_hAcceptInput, HookParamType_Object, 20); //varaint_t is a union of 12 (float[3]) plus two int type params 12 + 8 = 20
 | 
						|
	DHookAddParam(g_hAcceptInput, HookParamType_Int);
 | 
						|
}
 | 
						|
 | 
						|
public Action Event_PlayerDeath(Handle hEvent, const char[] szName, bool bDontBroadcast)
 | 
						|
{
 | 
						|
	int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
 | 
						|
	RemoveFromGameUI(client);
 | 
						|
	SetClientViewEntity(client, client);
 | 
						|
 | 
						|
	int iFlags = GetEntityFlags(client);
 | 
						|
	iFlags &= ~FL_ONTRAIN;
 | 
						|
	iFlags &= ~FL_FROZEN;
 | 
						|
	iFlags &= ~FL_ATCONTROLS;
 | 
						|
	SetEntityFlags(client, iFlags);
 | 
						|
}
 | 
						|
 | 
						|
public void OnClientDisconnect(int client)
 | 
						|
{
 | 
						|
	RemoveFromGameUI(client);
 | 
						|
}
 | 
						|
 | 
						|
public void GameUI_PlayerOn(const char[] szOutput, int iCaller, int iActivator, float fDelay)
 | 
						|
{
 | 
						|
	if(!(1 <= iActivator <= MaxClients))
 | 
						|
		return;
 | 
						|
 | 
						|
	int GameUIArray[2];
 | 
						|
	GameUIArray[0] = iCaller;
 | 
						|
	GameUIArray[1] = iActivator;
 | 
						|
 | 
						|
	g_hAttachedClients.PushArray(GameUIArray);
 | 
						|
}
 | 
						|
 | 
						|
public void GameUI_PlayerOff(const char[] szOutput, int iCaller, int iActivator, float fDelay)
 | 
						|
{
 | 
						|
	if(!(1 <= iActivator <= MaxClients))
 | 
						|
		return;
 | 
						|
 | 
						|
	for(int i; i < g_hAttachedClients.Length; i++)
 | 
						|
	{
 | 
						|
		int GameUIArray[2];
 | 
						|
		g_hAttachedClients.GetArray(i, GameUIArray);
 | 
						|
 | 
						|
		if (GameUIArray[0] == iCaller)
 | 
						|
		{
 | 
						|
			g_hAttachedClients.Erase(i);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
public void OnEntityDestroyed(int entity)
 | 
						|
{
 | 
						|
	for(int i; i < g_hAttachedClients.Length; i++)
 | 
						|
	{
 | 
						|
		int GameUIArray[2];
 | 
						|
		g_hAttachedClients.GetArray(i, GameUIArray);
 | 
						|
 | 
						|
		if (GameUIArray[0] == entity)
 | 
						|
		{
 | 
						|
			g_hAttachedClients.Erase(i);
 | 
						|
			break;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
void RemoveFromGameUI(int client)
 | 
						|
{
 | 
						|
	for(int i; i < g_hAttachedClients.Length; i++)
 | 
						|
	{
 | 
						|
		int GameUIArray[2];
 | 
						|
		g_hAttachedClients.GetArray(i, GameUIArray);
 | 
						|
 | 
						|
		if (GameUIArray[1] == client)
 | 
						|
		{
 | 
						|
			AcceptEntityInput(GameUIArray[0], "Deactivate", GameUIArray[1], GameUIArray[0]);
 | 
						|
			g_hAttachedClients.Erase(i);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
public void OnEntityCreated(int entity, const char[] classname)
 | 
						|
{
 | 
						|
	if (StrEqual(classname, "game_ui"))
 | 
						|
	{
 | 
						|
		DHookEntity(g_hAcceptInput, false, entity);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
public MRESReturn Hook_AcceptInput(int thisptr, Handle hReturn, Handle hParams)
 | 
						|
{
 | 
						|
	char sCommand[128];
 | 
						|
	DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand));
 | 
						|
 | 
						|
	if (StrEqual(sCommand, "Deactivate", false))
 | 
						|
	{
 | 
						|
		int pPlayer = GetEntPropEnt(thisptr, Prop_Data, "m_player");
 | 
						|
 | 
						|
		if (pPlayer == -1)
 | 
						|
		{
 | 
						|
			// Manually disable think.
 | 
						|
			SetEntProp(thisptr, Prop_Data, "m_nNextThinkTick", -1);
 | 
						|
 | 
						|
			DHookSetReturn(hReturn, false);
 | 
						|
			return MRES_Supercede;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	DHookSetReturn(hReturn, true);
 | 
						|
	return MRES_Ignored;
 | 
						|
}
 |