diff --git a/PlayerVisibility/scripting/PlayerVisibility.sp b/PlayerVisibility/scripting/PlayerVisibility.sp index 7c69ab19..72a2fa80 100644 --- a/PlayerVisibility/scripting/PlayerVisibility.sp +++ b/PlayerVisibility/scripting/PlayerVisibility.sp @@ -1,6 +1,9 @@ #include #include +#include +#undef REQUIRE_PLUGIN #include +#define REQUIRE_PLUGIN #pragma semicolon 1 #pragma newdecls required @@ -10,22 +13,45 @@ public Plugin myinfo = name = "PlayerVisibility", author = "BotoX", description = "Fades players away when you get close to them.", - version = "1.1", + version = "1.2", url = "" }; +// bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID ) +Handle g_hAcceptInput; + 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, ...}; 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); @@ -38,13 +64,31 @@ public void OnPluginStart() 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); + for(int client = 1; client <= MaxClients; client++) { if(IsClientInGame(client)) OnClientPutInServer(client); } +} - AutoExecConfig(true, "plugin.PlayerVisibility"); +public void OnPluginEnd() +{ + 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) @@ -57,72 +101,151 @@ public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] n else if(convar == g_CVar_MinAlpha) g_fMinAlpha = g_CVar_MinAlpha.FloatValue; -} -public void OnPluginEnd() -{ - for(int client = 1; client <= MaxClients; client++) - { - if(IsClientInGame(client)) - { - if(g_Client_Alpha[client] != 255.0) - SetEntityRenderMode(client, RENDER_NORMAL); - - OnClientDisconnect(client); - } - } + 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; + SDKHook(client, SDKHook_PostThinkPost, OnPostThinkPost); + DHookEntity(g_hAcceptInput, false, client); } -public void OnClientDisconnect(int 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 = DHookGetParam(hParams, 2); + + 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); +} + +Action Timer_SpawnPost(Handle timer, int client) +{ + ToolsSetEntityAlpha(client, 255); g_Client_Alpha[client] = 255; - SDKUnhook(client, SDKHook_PostThinkPost, OnPostThinkPost); + 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 OnPostThinkPost(int client) { - if(!IsPlayerAlive(client)) - { - if(g_Client_Alpha[client] != 255) - { - g_Client_Alpha[client] = 255; - ToolsSetEntityAlpha(client, 255); - } + if(!g_Client_bEnabled[client]) return; - } - - if(GetEntityRenderMode(client) == RENDER_NONE || - GetEntityRenderMode(client) == RENDER_ENVIRONMENTAL || - GetEntityRenderFx(client) != RENDERFX_NONE) - { - g_Client_Alpha[client] = 0; - return; - } - - int aColor[4]; - ToolsGetEntityColor(client, aColor); - if(!aColor[3]) - { - g_Client_Alpha[client] = 0; - return; - } - - if(!ZR_IsClientHuman(client)) - { - if(g_Client_Alpha[client] != 255) - { - g_Client_Alpha[client] = 255; - ToolsSetEntityAlpha(client, 255); - } - return; - } + int PlayersInRange = 0; float fAlpha = 255.0; for(int i = 1; i <= MaxClients; i++) { @@ -140,6 +263,8 @@ public void OnPostThinkPost(int client) float fDistance = GetVectorDistance(fVec1, fVec2, false); if(fDistance <= g_fMaxDistance) { + PlayersInRange++; + float fFactor = fDistance / g_fMaxDistance; if(fFactor < g_fMinFactor) fFactor = g_fMinFactor; @@ -151,13 +276,15 @@ public void OnPostThinkPost(int client) if(fAlpha < g_fMinAlpha) fAlpha = g_fMinAlpha; - int Alpha = RoundToNearest(fAlpha); - int LastAlpha = g_Client_Alpha[client]; - g_Client_Alpha[client] = Alpha; + if(PlayersInRange < g_iMinPlayers) + fAlpha = 255.0; - if(Alpha == LastAlpha) + int Alpha = RoundToNearest(fAlpha); + + if(Alpha == g_Client_Alpha[client]) return; + g_Client_Alpha[client] = Alpha; ToolsSetEntityAlpha(client, Alpha); }