2016-05-08 02:46:46 +02:00
# include <sourcemod>
2017-05-20 05:07:26 +02:00
# include <dhooks>
# undef REQUIRE_PLUGIN
2016-05-08 02:46:46 +02:00
# include <zombiereloaded>
2017-05-20 05:07:26 +02:00
# define REQUIRE_PLUGIN
2016-05-08 02:46:46 +02:00
2016-08-10 01:12:03 +02:00
# pragma semicolon 1
2016-05-19 16:12:34 +02:00
# pragma newdecls required
2016-05-08 02:46:46 +02:00
public Plugin myinfo =
{
name = " PlayerVisibility " ,
author = " BotoX " ,
description = " Fades players away when you get close to them. " ,
2017-05-20 05:07:26 +02:00
version = " 1.2 " ,
2016-05-08 02:46:46 +02:00
url = " "
} ;
2017-05-20 05:07:26 +02:00
// bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID )
Handle g_hAcceptInput ;
2019-08-21 15:04:23 +02:00
Handle g_hThinkTimer ;
2017-05-20 05:07:26 +02:00
2016-05-08 23:03:46 +02:00
ConVar g_CVar_MaxDistance ;
ConVar g_CVar_MinFactor ;
ConVar g_CVar_MinAlpha ;
2017-05-20 05:07:26 +02:00
ConVar g_CVar_MinPlayers ;
2016-05-08 23:03:46 +02:00
float g_fMaxDistance ;
float g_fMinFactor ;
float g_fMinAlpha ;
2017-05-20 05:07:26 +02:00
int g_iMinPlayers ;
2016-05-08 23:03:46 +02:00
2016-05-08 02:46:46 +02:00
int g_Client_Alpha [ MAXPLAYERS + 1 ] = { 255 , . . . } ;
2017-05-20 05:07:26 +02:00
bool g_Client_bEnabled [ MAXPLAYERS + 1 ] = { false , . . . } ;
2016-05-08 02:46:46 +02:00
2018-02-22 15:16:33 +01:00
bool g_Plugin_zombiereloaded = false ;
2016-05-08 02:46:46 +02:00
public void OnPluginStart ( )
{
2017-05-20 05:07:26 +02:00
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 ) ;
2016-05-08 23:03:46 +02:00
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 ) ;
2017-05-20 05:07:26 +02:00
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 ) ;
2019-08-21 15:04:23 +02:00
HookEvent ( " player_death " , Event_Death , EventHookMode_Post ) ;
2017-05-20 05:07:26 +02:00
2016-05-08 02:46:46 +02:00
for ( int client = 1 ; client < = MaxClients ; client + + )
{
if ( IsClientInGame ( client ) )
OnClientPutInServer ( client ) ;
}
2019-08-21 15:04:23 +02:00
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 ;
2017-05-20 05:07:26 +02:00
}
2016-05-08 23:03:46 +02:00
2018-02-22 15:16:33 +01:00
public void OnAllPluginsLoaded ( )
{
2018-02-22 15:18:28 +01:00
g_Plugin_zombiereloaded = LibraryExists ( " zombiereloaded " ) ;
2018-02-22 15:16:33 +01:00
}
2017-05-20 05:07:26 +02:00
public void OnPluginEnd ( )
{
2019-08-21 15:04:23 +02:00
KillTimer ( g_hThinkTimer ) ;
2017-05-20 05:07:26 +02:00
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 ) ;
}
}
2016-05-08 23:03:46 +02:00
}
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 ;
2016-05-08 02:46:46 +02:00
2017-05-20 05:07:26 +02:00
else if ( convar = = g_CVar_MinPlayers )
g_iMinPlayers = g_CVar_MinPlayers . IntValue ;
2016-05-08 02:46:46 +02:00
}
public void OnClientPutInServer ( int client )
{
2016-05-08 23:03:46 +02:00
g_Client_Alpha [ client ] = 255 ;
2017-05-20 05:07:26 +02:00
g_Client_bEnabled [ client ] = true ;
DHookEntity ( g_hAcceptInput , false , client ) ;
2016-05-08 02:46:46 +02:00
}
2017-05-20 05:07:26 +02:00
// bool CBaseEntity::AcceptInput( const char *szInputName, CBaseEntity *pActivator, CBaseEntity *pCaller, variant_t Value, int outputID )
public MRESReturn AcceptInput ( int pThis , Handle hReturn , Handle hParams )
2016-05-08 02:46:46 +02:00
{
2017-05-20 05:07:26 +02:00
// Should not happen?
if ( DHookIsNullParam ( hParams , 2 ) )
return MRES_Ignored ;
2016-05-08 02:46:46 +02:00
2017-08-12 15:06:41 +02:00
int client = EntRefToEntIndex ( DHookGetParam ( hParams , 2 ) ) ;
if ( client < 1 | | client > MAXPLAYERS )
return MRES_Ignored ;
2017-05-20 05:07:26 +02:00
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 + + )
2016-05-08 02:46:46 +02:00
{
2017-05-20 05:07:26 +02:00
if ( sValue [ i ] = = ' ' )
2016-05-08 02:46:46 +02:00
{
2017-05-20 05:07:26 +02:00
if ( bFound )
{
sValue [ i ] = '\0' ;
bFound = false ;
2019-08-30 20:20:11 +02:00
if ( iArgs > = sizeof ( aArgs ) )
2017-05-20 05:07:26 +02:00
break ;
}
continue ;
2016-05-08 02:46:46 +02:00
}
2017-05-20 05:07:26 +02:00
if ( ! bFound )
{
aArgs [ iArgs + + ] = i ;
bFound = true ;
}
2016-08-10 01:12:03 +02:00
}
2017-05-20 05:07:26 +02:00
if ( StrEqual ( szInputName , " addoutput " , false ) )
2016-08-10 01:12:03 +02:00
{
2017-05-20 05:07:26 +02:00
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 ;
}
2016-08-10 01:12:03 +02:00
}
2017-05-20 05:07:26 +02:00
else if ( StrEqual ( szInputName , " alpha " , false ) )
2016-08-10 01:12:03 +02:00
{
2017-05-20 05:07:26 +02:00
int iAlpha = StringToInt ( sValue [ aArgs [ 0 ] ] ) & 0xFF ;
if ( iAlpha = = 0 )
2016-08-10 01:12:03 +02:00
{
ToolsSetEntityAlpha ( client , 255 ) ;
2017-05-20 05:07:26 +02:00
g_Client_Alpha [ client ] = 255 ;
g_Client_bEnabled [ client ] = false ;
}
else
{
g_Client_bEnabled [ client ] = true ;
return MRES_Supercede ;
2016-08-10 01:12:03 +02:00
}
2016-05-08 02:46:46 +02:00
}
2017-05-20 05:07:26 +02:00
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 ) ;
}
2019-08-21 15:04:23 +02:00
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 ;
}
2017-10-12 21:52:36 +02:00
public Action Timer_SpawnPost ( Handle timer , int client )
2017-05-20 05:07:26 +02:00
{
2018-07-20 15:28:00 +02:00
if ( ! IsClientInGame ( client ) | | ! IsPlayerAlive ( client ) )
return Plugin_Stop ;
2017-05-20 05:07:26 +02:00
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 ;
}
2019-08-21 15:04:23 +02:00
public void DoClientThink ( int client )
2017-05-20 05:07:26 +02:00
{
if ( ! g_Client_bEnabled [ client ] )
return ;
int PlayersInRange = 0 ;
2016-05-08 02:46:46 +02:00
float fAlpha = 255.0 ;
for ( int i = 1 ; i < = MaxClients ; i + + )
{
if ( i = = client | | ! IsClientInGame ( i ) | | ! IsPlayerAlive ( i ) )
continue ;
2018-02-22 15:16:33 +01:00
if ( g_Plugin_zombiereloaded & & ! ZR_IsClientHuman ( i ) )
2016-05-08 02:46:46 +02:00
continue ;
static float fVec1 [ 3 ] ;
static float fVec2 [ 3 ] ;
GetClientAbsOrigin ( client , fVec1 ) ;
GetClientAbsOrigin ( i , fVec2 ) ;
float fDistance = GetVectorDistance ( fVec1 , fVec2 , false ) ;
2016-05-08 23:03:46 +02:00
if ( fDistance < = g_fMaxDistance )
2016-05-08 02:46:46 +02:00
{
2017-05-20 05:07:26 +02:00
PlayersInRange + + ;
2016-05-08 23:03:46 +02:00
float fFactor = fDistance / g_fMaxDistance ;
if ( fFactor < g_fMinFactor )
fFactor = g_fMinFactor ;
2016-05-08 02:46:46 +02:00
fAlpha * = fFactor ;
}
}
2016-05-08 23:03:46 +02:00
if ( fAlpha < g_fMinAlpha )
fAlpha = g_fMinAlpha ;
2016-05-08 02:46:46 +02:00
2017-05-20 05:07:26 +02:00
if ( PlayersInRange < g_iMinPlayers )
fAlpha = 255.0 ;
2016-05-08 02:46:46 +02:00
int Alpha = RoundToNearest ( fAlpha ) ;
2017-05-20 05:07:26 +02:00
if ( Alpha = = g_Client_Alpha [ client ] )
2016-05-08 02:46:46 +02:00
return ;
2017-05-20 05:07:26 +02:00
g_Client_Alpha [ client ] = Alpha ;
2016-05-08 02:46:46 +02:00
ToolsSetEntityAlpha ( client , Alpha ) ;
}
2016-08-10 01:12:03 +02:00
stock void ToolsSetEntityAlpha ( int client , int Alpha )
2016-05-08 02:46:46 +02:00
{
if ( Alpha = = 255 )
{
SetEntityRenderMode ( client , RENDER_NORMAL ) ;
return ;
}
int aColor [ 4 ] ;
ToolsGetEntityColor ( client , aColor ) ;
SetEntityRenderMode ( client , RENDER_TRANSCOLOR ) ;
2016-08-10 01:12:03 +02:00
SetEntityRenderColor ( client , aColor [ 0 ] , aColor [ 1 ] , aColor [ 2 ] , Alpha ) ;
2016-05-08 02:46:46 +02:00
}
2016-08-10 01:12:03 +02:00
stock void ToolsGetEntityColor ( int entity , int aColor [ 4 ] )
2016-05-08 02:46:46 +02:00
{
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 + + )
2016-08-10 21:22:14 +02:00
aColor [ i ] = GetEntData ( entity , Offset + i , 1 ) & 0xFF ;
2016-05-08 02:46:46 +02:00
}