PlayerVisibility: Improved and fixed bugs.

This commit is contained in:
BotoX 2017-05-20 05:07:26 +02:00
parent 34e17ed6d2
commit 69c13e42bb

View File

@ -1,6 +1,9 @@
#include <sourcemod>
#include <sdkhooks>
#include <dhooks>
#undef REQUIRE_PLUGIN
#include <zombiereloaded>
#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<RenderMode>(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<RenderFx>(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);
}