2016-01-06 02:11:56 +01:00
|
|
|
#pragma semicolon 1
|
2019-09-28 17:15:29 +02:00
|
|
|
#pragma newdecls required
|
2016-01-06 02:11:56 +01:00
|
|
|
|
|
|
|
#include <sourcemod>
|
|
|
|
#include <sdkhooks>
|
2019-09-10 16:33:50 +02:00
|
|
|
#include <sdktools>
|
2016-01-06 02:11:56 +01:00
|
|
|
#include <dhooks>
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public Plugin myinfo =
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
|
|
|
name = "FixGameUI",
|
|
|
|
author = "hlstriker + GoD-Tony",
|
2019-09-28 17:15:29 +02:00
|
|
|
description = "Fixes game_ui entity bug and blocks DMG_CRUSH.",
|
2016-01-06 02:11:56 +01:00
|
|
|
version = "1.0",
|
|
|
|
url = ""
|
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
Handle g_hAcceptInput;
|
|
|
|
int g_iAttachedGameUI[MAXPLAYERS + 1];
|
2016-01-06 02:11:56 +01:00
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public void OnPluginStart()
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
|
|
|
HookEvent("player_death", Event_PlayerDeath, EventHookMode_Post);
|
|
|
|
|
|
|
|
HookEntityOutput("game_ui", "PlayerOn", GameUI_PlayerOn);
|
|
|
|
HookEntityOutput("game_ui", "PlayerOff", GameUI_PlayerOff);
|
|
|
|
|
|
|
|
// Gamedata.
|
2017-05-20 05:08:31 +02:00
|
|
|
Handle hConfig = LoadGameConfigFile("sdktools.games");
|
2016-01-06 02:11:56 +01:00
|
|
|
if (hConfig == INVALID_HANDLE)
|
2017-05-20 05:08:31 +02:00
|
|
|
SetFailState("Couldn't load sdktools game config!");
|
2016-01-06 02:11:56 +01:00
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
int offset = GameConfGetOffset(hConfig, "AcceptInput");
|
2016-01-06 02:11:56 +01:00
|
|
|
if (offset == -1)
|
|
|
|
SetFailState("Failed to find AcceptInput offset");
|
2019-09-28 17:15:29 +02:00
|
|
|
|
|
|
|
delete hConfig;
|
2016-01-06 02:11:56 +01:00
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public Action Event_PlayerDeath(Handle hEvent, const char[] szName, bool bDontBroadcast)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
2019-09-28 17:15:29 +02:00
|
|
|
int client = GetClientOfUserId(GetEventInt(hEvent, "userid"));
|
|
|
|
RemoveFromGameUI(client);
|
|
|
|
SetClientViewEntity(client, client);
|
2016-01-06 02:11:56 +01:00
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
int iFlags = GetEntityFlags(client);
|
2016-01-06 02:11:56 +01:00
|
|
|
iFlags &= ~FL_ONTRAIN;
|
|
|
|
iFlags &= ~FL_FROZEN;
|
|
|
|
iFlags &= ~FL_ATCONTROLS;
|
2019-09-28 17:15:29 +02:00
|
|
|
SetEntityFlags(client, iFlags);
|
2016-01-06 02:11:56 +01:00
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public void OnClientDisconnect(int client)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
2019-09-28 17:15:29 +02:00
|
|
|
RemoveFromGameUI(client);
|
2016-01-06 02:11:56 +01:00
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public void GameUI_PlayerOn(const char[] szOutput, int iCaller, int iActivator, float fDelay)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
|
|
|
if(!(1 <= iActivator <= MaxClients))
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_iAttachedGameUI[iActivator] = EntIndexToEntRef(iCaller);
|
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public void GameUI_PlayerOff(const char[] szOutput, int iCaller, int iActivator, float fDelay)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
|
|
|
if(!(1 <= iActivator <= MaxClients))
|
|
|
|
return;
|
|
|
|
|
|
|
|
g_iAttachedGameUI[iActivator] = 0;
|
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
void RemoveFromGameUI(int client)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
2019-09-28 17:15:29 +02:00
|
|
|
if(!g_iAttachedGameUI[client])
|
2016-01-06 02:11:56 +01:00
|
|
|
return;
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
int entity = EntRefToEntIndex(g_iAttachedGameUI[client]);
|
|
|
|
if(entity == INVALID_ENT_REFERENCE)
|
2016-01-06 02:11:56 +01:00
|
|
|
return;
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
AcceptEntityInput(entity, "Deactivate", client, entity);
|
2016-01-06 02:11:56 +01:00
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public void OnEntityCreated(int entity, const char[] classname)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
|
|
|
if (StrEqual(classname, "game_ui"))
|
|
|
|
{
|
|
|
|
DHookEntity(g_hAcceptInput, false, entity);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
public MRESReturn Hook_AcceptInput(int thisptr, Handle hReturn, Handle hParams)
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
2019-09-28 17:15:29 +02:00
|
|
|
char sCommand[128];
|
2016-01-06 02:11:56 +01:00
|
|
|
DHookGetParamString(hParams, 1, sCommand, sizeof(sCommand));
|
|
|
|
|
2019-09-28 17:15:29 +02:00
|
|
|
if (StrEqual(sCommand, "Deactivate", false))
|
2016-01-06 02:11:56 +01:00
|
|
|
{
|
2019-09-28 17:15:29 +02:00
|
|
|
int pPlayer = GetEntPropEnt(thisptr, Prop_Data, "m_player");
|
2016-01-06 02:11:56 +01:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|