130 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			SourcePawn
		
	
	
	
	
	
| #pragma semicolon 1
 | |
| 
 | |
| #include <sourcemod>
 | |
| #include <sdktools_entoutput>
 | |
| #include <sdktools_entinput>
 | |
| #include <sdktools_engine>
 | |
| #include <sdkhooks>
 | |
| #include <dhooks>
 | |
| 
 | |
| public Plugin:myinfo =
 | |
| {
 | |
| 	name = "FixGameUI",
 | |
| 	author = "hlstriker + GoD-Tony",
 | |
| 	description = "Fixes game_ui entity bug.",
 | |
| 	version = "1.0",
 | |
| 	url = ""
 | |
| }
 | |
| 
 | |
| new g_iAttachedGameUI[MAXPLAYERS+1];
 | |
| new Handle:g_hAcceptInput = INVALID_HANDLE;
 | |
| 
 | |
| public OnPluginStart()
 | |
| {
 | |
| 	HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post);
 | |
| 
 | |
| 	HookEntityOutput("game_ui", "PlayerOn", GameUI_PlayerOn);
 | |
| 	HookEntityOutput("game_ui", "PlayerOff", GameUI_PlayerOff);
 | |
| 
 | |
| 	// Gamedata.
 | |
| 	Handle hConfig = LoadGameConfigFile("sdktools.games");
 | |
| 	if (hConfig == INVALID_HANDLE)
 | |
| 	{
 | |
| 		SetFailState("Couldn't load sdktools game config!");
 | |
| 		return;
 | |
| 	}
 | |
| 
 | |
| 	new offset = GameConfGetOffset(hConfig, "AcceptInput");
 | |
| 	if (offset == -1)
 | |
| 	{
 | |
| 		SetFailState("Failed to find AcceptInput offset");
 | |
| 	}
 | |
| 	CloseHandle(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 String:szName[], bool:bDontBroadcast)
 | |
| {
 | |
| 	new iClient = GetClientOfUserId(GetEventInt(hEvent, "userid"));
 | |
| 	RemoveFromGameUI(iClient);
 | |
| 	SetClientViewEntity(iClient, iClient);
 | |
| 
 | |
| 	new iFlags = GetEntityFlags(iClient);
 | |
| 	iFlags &= ~FL_ONTRAIN;
 | |
| 	iFlags &= ~FL_FROZEN;
 | |
| 	iFlags &= ~FL_ATCONTROLS;
 | |
| 	SetEntityFlags(iClient, iFlags);
 | |
| }
 | |
| 
 | |
| public OnClientDisconnect(iClient)
 | |
| {
 | |
| 	RemoveFromGameUI(iClient);
 | |
| }
 | |
| 
 | |
| public GameUI_PlayerOn(const String:szOutput[], iCaller, iActivator, Float:fDelay)
 | |
| {
 | |
| 	if(!(1 <= iActivator <= MaxClients))
 | |
| 		return;
 | |
| 
 | |
| 	g_iAttachedGameUI[iActivator] = EntIndexToEntRef(iCaller);
 | |
| }
 | |
| 
 | |
| public GameUI_PlayerOff(const String:szOutput[], iCaller, iActivator, Float:fDelay)
 | |
| {
 | |
| 	if(!(1 <= iActivator <= MaxClients))
 | |
| 		return;
 | |
| 
 | |
| 	g_iAttachedGameUI[iActivator] = 0;
 | |
| }
 | |
| 
 | |
| RemoveFromGameUI(iClient)
 | |
| {
 | |
| 	if(!g_iAttachedGameUI[iClient])
 | |
| 		return;
 | |
| 
 | |
| 	new iEnt = EntRefToEntIndex(g_iAttachedGameUI[iClient]);
 | |
| 	if(iEnt == INVALID_ENT_REFERENCE)
 | |
| 		return;
 | |
| 
 | |
| 	AcceptEntityInput(iEnt, "Deactivate", iClient, iEnt);
 | |
| }
 | |
| 
 | |
| public OnEntityCreated(entity, const String:classname[])
 | |
| {
 | |
| 	if (StrEqual(classname, "game_ui"))
 | |
| 	{
 | |
| 		DHookEntity(g_hAcceptInput, false, entity);
 | |
| 	}
 | |
| }
 | |
| 
 | |
| public MRESReturn:Hook_AcceptInput(thisptr, Handle:hReturn, Handle:hParams)
 | |
| {
 | |
| 	new String:sCommand[128];
 | |
| 	DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand));
 | |
| 
 | |
| 	if (StrEqual(sCommand, "Deactivate"))
 | |
| 	{
 | |
| 		new 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;
 | |
| }
 |