#include #include #include #undef REQUIRE_PLUGIN #include #define REQUIRE_PLUGIN #pragma semicolon 1 #pragma newdecls required public Plugin myinfo = { name = "PlayerVisibility", author = "BotoX", description = "Fades players away when you get close to them.", version = "1.2", url = "" }; // bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ) Handle g_hAcceptInput; Handle g_hThinkTimer; ConVar g_CVar_MaxDistance; ConVar g_CVar_MinFactor; ConVar g_CVar_MinAlpha; ConVar g_CVar_MinPlayers; float g_fMaxDistance; float g_fMinFactor; float g_fMinAlpha; int g_iMinPlayers; int g_Client_Alpha[MAXPLAYERS + 1] = {255, ...}; bool g_Client_bEnabled[MAXPLAYERS + 1] = {false, ...}; bool g_Plugin_zombiereloaded = false; public void OnPluginStart() { Handle hGameConf = LoadGameConfigFile("sdktools.games"); if(hGameConf == INVALID_HANDLE) { SetFailState("Couldn't load sdktools game config!"); return; } int Offset = GameConfGetOffset(hGameConf, "AcceptInput"); g_hAcceptInput = DHookCreate(Offset, HookType_Entity, ReturnType_Bool, ThisPointer_CBaseEntity, 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); CloseHandle(hGameConf); g_CVar_MaxDistance = CreateConVar("sm_pvis_maxdistance", "100.0", "Distance at which models stop fading.", 0, true, 0.0); g_fMaxDistance = g_CVar_MaxDistance.FloatValue; g_CVar_MaxDistance.AddChangeHook(OnConVarChanged); g_CVar_MinFactor = CreateConVar("sm_pvis_minfactor", "0.75", "Smallest allowed alpha factor per client.", 0, true, 0.0, true, 1.0); g_fMinFactor = g_CVar_MinFactor.FloatValue; g_CVar_MinFactor.AddChangeHook(OnConVarChanged); g_CVar_MinAlpha = CreateConVar("sm_pvis_minalpha", "75.0", "Minimum allowed alpha value.", 0, true, 0.0, true, 255.0); g_fMinAlpha = g_CVar_MinAlpha.FloatValue; g_CVar_MinAlpha.AddChangeHook(OnConVarChanged); g_CVar_MinPlayers = CreateConVar("sm_pvis_minplayers", "3.0", "Minimum players within distance to enable fading.", 0, true, 0.0, true, 255.0); g_iMinPlayers = g_CVar_MinPlayers.IntValue; g_CVar_MinPlayers.AddChangeHook(OnConVarChanged); AutoExecConfig(true, "plugin.PlayerVisibility"); HookEvent("player_spawn", Event_Spawn, EventHookMode_Post); HookEvent("player_death", Event_Death, EventHookMode_Post); for(int client = 1; client <= MaxClients; client++) { if(IsClientInGame(client)) OnClientPutInServer(client); } g_hThinkTimer = CreateTimer(0.2, Timer_Think, _, TIMER_REPEAT); } public Action Timer_Think(Handle timer) { for(int client = 1; client <= MaxClients; client++) { if(IsClientInGame(client)) DoClientThink(client); } return Plugin_Continue; } public void OnAllPluginsLoaded() { g_Plugin_zombiereloaded = LibraryExists("zombiereloaded"); } public void OnLibraryAdded(const char[] sName) { if(strcmp(sName, "zombiereloaded", false) == 0) g_Plugin_zombiereloaded = true; } public void OnLibraryRemoved(const char[] sName) { if(strcmp(sName, "zombiereloaded", false) == 0) g_Plugin_zombiereloaded = false; } public void OnPluginEnd() { KillTimer(g_hThinkTimer); for(int client = 1; client <= MaxClients; client++) { if(IsClientInGame(client)) { if(g_Client_bEnabled[client] && g_Client_Alpha[client] != 255.0) SetEntityRenderMode(client, RENDER_NORMAL); } } } public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) { if(convar == g_CVar_MaxDistance) g_fMaxDistance = g_CVar_MaxDistance.FloatValue; else if(convar == g_CVar_MinFactor) g_fMinFactor = g_CVar_MinFactor.FloatValue; else if(convar == g_CVar_MinAlpha) g_fMinAlpha = g_CVar_MinAlpha.FloatValue; else if(convar == g_CVar_MinPlayers) g_iMinPlayers = g_CVar_MinPlayers.IntValue; } public void OnClientPutInServer(int client) { g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = true; DHookEntity(g_hAcceptInput, false, client); } // bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ) public MRESReturn AcceptInput(int pThis, Handle hReturn, Handle hParams) { // Should not happen? if(DHookIsNullParam(hParams, 2)) return MRES_Ignored; int client = EntRefToEntIndex(DHookGetParam(hParams, 2)); if(client < 1 || client > MAXPLAYERS) return MRES_Ignored; if(!g_Client_bEnabled[client]) return MRES_Ignored; char szInputName[32]; DHookGetParamString(hParams, 1, szInputName, sizeof(szInputName)); if(!StrEqual(szInputName, "addoutput", false)) return MRES_Ignored; char sValue[128]; DHookGetParamObjectPtrString(hParams, 4, 0, ObjectValueType_String, sValue, sizeof(sValue)); int iValueLen = strlen(sValue); int aArgs[4] = {0, ...}; int iArgs = 0; bool bFound = false; for(int i = 0; i < iValueLen; i++) { if(sValue[i] == ' ') { if(bFound) { sValue[i] = '\0'; bFound = false; if(iArgs >= sizeof(aArgs)) break; } continue; } if(!bFound) { aArgs[iArgs++] = i; bFound = true; } } if(StrEqual(szInputName, "addoutput", false)) { if(StrEqual(sValue[aArgs[0]], "rendermode", false)) { RenderMode renderMode = view_as(StringToInt(sValue[aArgs[1]]) & 0xFF); if(renderMode == RENDER_ENVIRONMENTAL) { ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = false; } else g_Client_bEnabled[client] = true; } else if(StrEqual(sValue[aArgs[0]], "renderfx", false)) { RenderFx renderFx = view_as(StringToInt(sValue[aArgs[1]]) & 0xFF); if(renderFx != RENDERFX_NONE) { ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = false; } else g_Client_bEnabled[client] = true; } } else if(StrEqual(szInputName, "alpha", false)) { int iAlpha = StringToInt(sValue[aArgs[0]]) & 0xFF; if(iAlpha == 0) { ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = false; } else { g_Client_bEnabled[client] = true; return MRES_Supercede; } } return MRES_Ignored; } public void Event_Spawn(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(GetEventInt(event, "userid")); if(!client) return; CreateTimer(0.1, Timer_SpawnPost, client, TIMER_FLAG_NO_MAPCHANGE); } public void Event_Death(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(GetEventInt(event, "userid")); if(!client) return; g_Client_bEnabled[client] = false; } public Action Timer_SpawnPost(Handle timer, int client) { if(!IsClientInGame(client) || !IsPlayerAlive(client)) return Plugin_Stop; ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = true; return Plugin_Stop; } public void ZR_OnClientInfected(int client, int attacker, bool motherInfect, bool respawnOverride, bool respawn) { ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = false; } public void ZR_OnClientHumanPost(int client, bool respawn, bool protect) { ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; g_Client_bEnabled[client] = true; } public void DoClientThink(int client) { if(!g_Client_bEnabled[client]) return; int PlayersInRange = 0; float fAlpha = 255.0; for(int i = 1; i <= MaxClients; i++) { if(i == client || !IsClientInGame(i) || !IsPlayerAlive(i)) continue; if(g_Plugin_zombiereloaded && !ZR_IsClientHuman(i)) continue; static float fVec1[3]; static float fVec2[3]; GetClientAbsOrigin(client, fVec1); GetClientAbsOrigin(i, fVec2); float fDistance = GetVectorDistance(fVec1, fVec2, false); if(fDistance <= g_fMaxDistance) { PlayersInRange++; float fFactor = fDistance / g_fMaxDistance; if(fFactor < g_fMinFactor) fFactor = g_fMinFactor; fAlpha *= fFactor; } } if(fAlpha < g_fMinAlpha) fAlpha = g_fMinAlpha; if(PlayersInRange < g_iMinPlayers) fAlpha = 255.0; int Alpha = RoundToNearest(fAlpha); if(Alpha == g_Client_Alpha[client]) return; g_Client_Alpha[client] = Alpha; ToolsSetEntityAlpha(client, Alpha); } stock void ToolsSetEntityAlpha(int client, int Alpha) { if(Alpha == 255) { SetEntityRenderMode(client, RENDER_NORMAL); return; } int aColor[4]; ToolsGetEntityColor(client, aColor); SetEntityRenderMode(client, RENDER_TRANSCOLOR); SetEntityRenderColor(client, aColor[0], aColor[1], aColor[2], Alpha); } stock void ToolsGetEntityColor(int entity, int aColor[4]) { static bool s_GotConfig = false; static char s_sProp[32]; if(!s_GotConfig) { Handle GameConf = LoadGameConfigFile("core.games"); bool Exists = GameConfGetKeyValue(GameConf, "m_clrRender", s_sProp, sizeof(s_sProp)); CloseHandle(GameConf); if(!Exists) strcopy(s_sProp, sizeof(s_sProp), "m_clrRender"); s_GotConfig = true; } int Offset = GetEntSendPropOffs(entity, s_sProp); for(int i = 0; i < 4; i++) aColor[i] = GetEntData(entity, Offset + i, 1) & 0xFF; }