#pragma semicolon 1 #pragma newdecls required #include #include #include #include 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; int g_iAttachedGameUI[MAXPLAYERS + 1]; public void 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!"); 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; g_iAttachedGameUI[iActivator] = EntIndexToEntRef(iCaller); } public void GameUI_PlayerOff(const char[] szOutput, int iCaller, int iActivator, float fDelay) { if(!(1 <= iActivator <= MaxClients)) return; g_iAttachedGameUI[iActivator] = 0; } void RemoveFromGameUI(int client) { if(!g_iAttachedGameUI[client]) return; int entity = EntRefToEntIndex(g_iAttachedGameUI[client]); if(entity == INVALID_ENT_REFERENCE) return; AcceptEntityInput(entity, "Deactivate", client, entity); } 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; }