lots of changes
This commit is contained in:
@@ -12,7 +12,6 @@ bool g_bHasSomebodyToHide[MAXPLAYERS + 1];
|
||||
|
||||
/* INTEGERS */
|
||||
int g_iHideRange[MAXPLAYERS+1];
|
||||
int g_iLeader = 0;
|
||||
int g_iHideCapacity = 8;
|
||||
|
||||
/* HANDLES */
|
||||
@@ -203,7 +202,7 @@ public Action UpdateHide(Handle timer)
|
||||
{
|
||||
GetClientAbsOrigin(target, fOriginTarget);
|
||||
//PrintToChatAll("%N--%N::::::%f", client, target, GetVectorDistance(fOriginTarget, fOriginClient, false));
|
||||
if((GetVectorDistance(fOriginTarget, fOriginClient, true) <= float(g_iHideRange[client])) && (g_iLeader != target))
|
||||
if((GetVectorDistance(fOriginTarget, fOriginClient, true) <= float(g_iHideRange[client])) && !Leader_Is(target))
|
||||
{
|
||||
g_bHidePlayers[client][target] = true;
|
||||
g_bHasSomebodyToHide[client] = true;
|
||||
@@ -219,7 +218,6 @@ public Action UpdateHide(Handle timer)
|
||||
}
|
||||
}
|
||||
}
|
||||
g_iLeader = Leader_CurrentLeader()
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,22 @@ bool g_bHasSomebodyToHide[MAXPLAYERS + 1];
|
||||
bool g_bHasTobeVisible[MAXPLAYERS + 1];
|
||||
bool g_bHidePlayers[MAXPLAYERS + 1][MAXPLAYERS + 1];
|
||||
|
||||
/* PER-TICK CACHED PLAYER STATE, refreshed at the top of UpdateHide so the pair loops are plain array reads */
|
||||
bool g_bInGame[MAXPLAYERS + 1];
|
||||
bool g_bFake[MAXPLAYERS + 1];
|
||||
bool g_bAlive[MAXPLAYERS + 1];
|
||||
bool g_bHuman[MAXPLAYERS + 1];
|
||||
bool g_bZombie[MAXPLAYERS + 1];
|
||||
bool g_bLeader[MAXPLAYERS + 1];
|
||||
bool g_bHasItem[MAXPLAYERS + 1];
|
||||
bool g_bHooked[MAXPLAYERS + 1];
|
||||
bool g_bTargetEligible[MAXPLAYERS + 1];
|
||||
float g_fOrigin[MAXPLAYERS + 1][3];
|
||||
|
||||
/* INTEGERS */
|
||||
int g_iHideRange[MAXPLAYERS+1];
|
||||
int g_iLeader = 0;
|
||||
int g_iTierHide = 0;
|
||||
int g_iNextClient = 1;
|
||||
|
||||
/* HANDLES */
|
||||
Handle g_hTimer;
|
||||
@@ -48,6 +60,12 @@ public Plugin myinfo =
|
||||
url = "www.unloze.com"
|
||||
};
|
||||
|
||||
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
||||
{
|
||||
MarkNativeAsOptional("GetPlayerTier_native");
|
||||
return APLRes_Success;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// Purpose:
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
@@ -73,7 +91,9 @@ public void OnPluginStart()
|
||||
|
||||
}
|
||||
SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Hide");
|
||||
g_hTimer = CreateTimer(1.0, UpdateHide, INVALID_HANDLE, TIMER_REPEAT);
|
||||
//0.1s ticks each processing a tenth of the slots: every client still refreshes about once a second,
|
||||
//but the cost is spread over ten frames instead of one spike
|
||||
g_hTimer = CreateTimer(0.1, UpdateHide, INVALID_HANDLE, TIMER_REPEAT);
|
||||
g_iTierHide = FindTierForCommandOverride("sm_hide");
|
||||
}
|
||||
|
||||
@@ -108,129 +128,166 @@ public Action UpdateHide(Handle timer)
|
||||
if (!g_hCVar_HideEnabled.BoolValue)
|
||||
return Plugin_Continue;
|
||||
|
||||
g_iLeader = Leader_CurrentLeader();
|
||||
|
||||
for (int client = 1; client <= MaxClients; client++)
|
||||
//early-out when nobody has hide enabled and no hide state is left to clean up
|
||||
bool bAnyWork = false;
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
if (!IsValidClient(client) || IsClientSourceTV(client) || IsFakeClient(client))
|
||||
if ((g_iHideRange[i] != DISABLED || g_bHasSomebodyToHide[i]) && IsClientInGame(i))
|
||||
{
|
||||
bAnyWork = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!bAnyWork)
|
||||
return Plugin_Continue;
|
||||
|
||||
//cache the per-player state once per tick. everything the pair loops need depends on a single
|
||||
//player, so this costs natives once per player instead of once per pair.
|
||||
for (int i = 1; i <= MaxClients; i++)
|
||||
{
|
||||
g_bInGame[i] = IsClientInGame(i) && !IsClientSourceTV(i);
|
||||
if (!g_bInGame[i])
|
||||
{
|
||||
g_bTargetEligible[i] = false;
|
||||
continue;
|
||||
}
|
||||
g_bFake[i] = IsFakeClient(i);
|
||||
g_bHooked[i] = TransmitManager_IsEntityHooked(i);
|
||||
g_bAlive[i] = IsPlayerAlive(i);
|
||||
g_bHuman[i] = g_bAlive[i] && ZR_IsClientHuman(i);
|
||||
g_bZombie[i] = g_bAlive[i] && ZR_IsClientZombie(i);
|
||||
g_bLeader[i] = Leader_Is(i);
|
||||
g_bHasItem[i] = EW_ClientHasItem(i);
|
||||
if (g_bAlive[i])
|
||||
GetClientAbsOrigin(i, g_fOrigin[i]);
|
||||
|
||||
if (g_iHideRange[client] == DISABLED) //client just disabled hide right now. the bool will pass once until they enabled hide again.
|
||||
{
|
||||
if (g_bHasSomebodyToHide[client] && TransmitManager_IsEntityHooked(client))
|
||||
{
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (IsValidClient(target) && client != target && TransmitManager_IsEntityHooked(target))
|
||||
{
|
||||
TransmitManager_SetEntityState(target, client, true); //client can see all players again
|
||||
g_bHidePlayers[client][target] = false;
|
||||
}
|
||||
}
|
||||
g_bHasSomebodyToHide[client] = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
//the target is not the leader, has no item, is alive and is a human. so consider him for the distance check.
|
||||
g_bTargetEligible[i] = g_bHuman[i] && !g_bLeader[i] && !g_bHasItem[i];
|
||||
}
|
||||
|
||||
//lazy fix for invisible zm
|
||||
if (TransmitManager_IsEntityHooked(client))
|
||||
{
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (IsValidClient(target) && client != target && g_bHidePlayers[client][target]
|
||||
&& IsPlayerAlive(target) && ZR_IsClientZombie(target) && TransmitManager_IsEntityHooked(target))
|
||||
{
|
||||
g_bHidePlayers[client][target] = false;
|
||||
TransmitManager_SetEntityState(target, client, true); //client can see player again because the player is a zm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientIsAlive = IsPlayerAlive(client);
|
||||
bool ClientIsHuman = false;
|
||||
if (ClientIsAlive)
|
||||
{
|
||||
ClientIsHuman = ZR_IsClientHuman(client);
|
||||
}
|
||||
bool ClientHasItem = EW_ClientHasItem(client);
|
||||
|
||||
//player is leader, has an item, is not alive or is not human, set the transmit state once via the bool so all can see the player.
|
||||
if (g_iLeader == client || ClientHasItem || !ClientIsAlive || !ClientIsHuman)
|
||||
{
|
||||
if (!g_bHasTobeVisible[client] && TransmitManager_IsEntityHooked(client))
|
||||
{
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (IsValidClient(target) && client != target && TransmitManager_IsEntityHooked(target))
|
||||
{
|
||||
//all must see the leader, the zombie and the item user.
|
||||
TransmitManager_SetEntityState(client, target, true); //all can see the player again
|
||||
|
||||
//if the player is dead or not human they must see all players again
|
||||
if (!ClientIsAlive || !ClientIsHuman)
|
||||
{
|
||||
TransmitManager_SetEntityState(target, client, true); //client can see all players again
|
||||
}
|
||||
}
|
||||
}
|
||||
g_bHasTobeVisible[client] = true;
|
||||
}
|
||||
//but the human leader and human item users may still want to hide the remaining human players.
|
||||
if (ClientIsAlive && ClientIsHuman && (g_iLeader == client || ClientHasItem))
|
||||
{
|
||||
DoTheTargetCheck(client);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
g_bHasTobeVisible[client] = false;
|
||||
|
||||
//all the remaining checks for clients with hide enabled that are alive humans and not leaders or item users.
|
||||
DoTheTargetCheck(client);
|
||||
//process a tenth of the slots per tick; combined with the 0.1s interval every client is
|
||||
//refreshed about once a second, like the old 1.0s full scan, without the frame spike.
|
||||
int iSlice = (MaxClients + 9) / 10;
|
||||
for (int n = 0; n < iSlice; n++)
|
||||
{
|
||||
int client = g_iNextClient;
|
||||
g_iNextClient = (g_iNextClient % MaxClients) + 1;
|
||||
ProcessHideClient(client);
|
||||
}
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
void ProcessHideClient(int client)
|
||||
{
|
||||
if (!g_bInGame[client] || g_bFake[client])
|
||||
return;
|
||||
|
||||
if (g_iHideRange[client] == DISABLED) //client just disabled hide right now. the bool will pass once until they enabled hide again.
|
||||
{
|
||||
if (g_bHasSomebodyToHide[client] && g_bHooked[client])
|
||||
{
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (client != target && g_bInGame[target] && g_bHooked[target])
|
||||
{
|
||||
TransmitManager_SetEntityState(target, client, true); //client can see all players again
|
||||
g_bHidePlayers[client][target] = false;
|
||||
}
|
||||
}
|
||||
g_bHasSomebodyToHide[client] = false;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
//lazy fix for invisible zm
|
||||
if (g_bHooked[client])
|
||||
{
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (g_bHidePlayers[client][target] && client != target && g_bInGame[target]
|
||||
&& g_bZombie[target] && g_bHooked[target])
|
||||
{
|
||||
g_bHidePlayers[client][target] = false;
|
||||
TransmitManager_SetEntityState(target, client, true); //client can see player again because the player is a zm
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ClientIsAlive = g_bAlive[client];
|
||||
bool ClientIsHuman = g_bHuman[client];
|
||||
bool ClientIsLeader = g_bLeader[client];
|
||||
bool ClientHasItem = g_bHasItem[client];
|
||||
|
||||
//player is leader, has an item, is not alive or is not human, set the transmit state once via the bool so all can see the player.
|
||||
if (ClientIsLeader || ClientHasItem || !ClientIsAlive || !ClientIsHuman)
|
||||
{
|
||||
if (!g_bHasTobeVisible[client] && g_bHooked[client])
|
||||
{
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (client != target && g_bInGame[target] && g_bHooked[target])
|
||||
{
|
||||
//all must see the leader, the zombie and the item user.
|
||||
TransmitManager_SetEntityState(client, target, true); //all can see the player again
|
||||
|
||||
//if the player is dead or not human they must see all players again
|
||||
if (!ClientIsAlive || !ClientIsHuman)
|
||||
{
|
||||
TransmitManager_SetEntityState(target, client, true); //client can see all players again
|
||||
}
|
||||
}
|
||||
}
|
||||
g_bHasTobeVisible[client] = true;
|
||||
}
|
||||
//but the human leader and human item users may still want to hide the remaining human players.
|
||||
if (ClientIsAlive && ClientIsHuman && (ClientIsLeader || ClientHasItem))
|
||||
{
|
||||
DoTheTargetCheck(client);
|
||||
}
|
||||
return;
|
||||
}
|
||||
g_bHasTobeVisible[client] = false;
|
||||
|
||||
//all the remaining checks for clients with hide enabled that are alive humans and not leaders or item users.
|
||||
DoTheTargetCheck(client);
|
||||
}
|
||||
|
||||
public void DoTheTargetCheck(int client)
|
||||
{
|
||||
float fOriginClient[3];
|
||||
float fOriginTarget[3];
|
||||
GetClientAbsOrigin(client, fOriginClient);
|
||||
g_bHasSomebodyToHide[client] = false;
|
||||
|
||||
float fRangeSquared = float(g_iHideRange[client]);
|
||||
float fClientX = g_fOrigin[client][0];
|
||||
float fClientY = g_fOrigin[client][1];
|
||||
float fClientZ = g_fOrigin[client][2];
|
||||
bool bClientHooked = g_bHooked[client];
|
||||
|
||||
for (int target = 1; target <= MaxClients; target++)
|
||||
{
|
||||
if (!IsValidClient(target) || IsClientSourceTV(target))
|
||||
if (target == client || !g_bTargetEligible[target])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
//the target is not the leader, has no item, is alive and is a human. so consider him for the distance check.
|
||||
if (g_iLeader != target && !EW_ClientHasItem(target) && IsPlayerAlive(target) && ZR_IsClientHuman(target) && target != client)
|
||||
float fDeltaX = g_fOrigin[target][0] - fClientX;
|
||||
float fDeltaY = g_fOrigin[target][1] - fClientY;
|
||||
float fDeltaZ = g_fOrigin[target][2] - fClientZ;
|
||||
|
||||
if (fDeltaX * fDeltaX + fDeltaY * fDeltaY + fDeltaZ * fDeltaZ <= fRangeSquared)
|
||||
{
|
||||
GetClientAbsOrigin(target, fOriginTarget);
|
||||
if (GetVectorDistance(fOriginTarget, fOriginClient, true) <= float(g_iHideRange[client]))
|
||||
//we only have to check the hook when the state of the hidePlayers boolean changed
|
||||
if (!g_bHidePlayers[client][target] && bClientHooked && g_bHooked[target])
|
||||
{
|
||||
//we only have to check the hook when the state of the hidePlayers boolean changed
|
||||
if (!g_bHidePlayers[client][target] && TransmitManager_IsEntityHooked(client) && TransmitManager_IsEntityHooked(target))
|
||||
{
|
||||
//the client here cannot be a fakeclient. thats already checked.
|
||||
TransmitManager_SetEntityState(target, client, false); //the player is hiding the teammate due to distance
|
||||
g_bHidePlayers[client][target] = true;
|
||||
//LogMessage("client: %N is %s. target: %N is %s", client, ZR_IsClientHuman(client) ? "Human" : "Zombie", target, ZR_IsClientHuman(target) ? "Human" : "Zombie");
|
||||
}
|
||||
g_bHasSomebodyToHide[client] = true; //theres at least one target to hide for the player, the teammate
|
||||
}
|
||||
else
|
||||
{
|
||||
//we only have to check the hook when the state of the hidePlayers boolean changed
|
||||
if (g_bHidePlayers[client][target] && TransmitManager_IsEntityHooked(client) && TransmitManager_IsEntityHooked(target))
|
||||
{
|
||||
TransmitManager_SetEntityState(target, client, true); //the player is seeing the teammate due to distance
|
||||
g_bHidePlayers[client][target] = false;
|
||||
}
|
||||
//the client here cannot be a fakeclient. thats already checked.
|
||||
TransmitManager_SetEntityState(target, client, false); //the player is hiding the teammate due to distance
|
||||
g_bHidePlayers[client][target] = true;
|
||||
}
|
||||
g_bHasSomebodyToHide[client] = true; //theres at least one target to hide for the player, the teammate
|
||||
}
|
||||
else if (g_bHidePlayers[client][target] && bClientHooked && g_bHooked[target])
|
||||
{
|
||||
TransmitManager_SetEntityState(target, client, true); //the player is seeing the teammate due to distance
|
||||
g_bHidePlayers[client][target] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -393,10 +450,13 @@ stock int FindTierForCommandOverride(const char[] command)
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen)
|
||||
{
|
||||
int client_tier = GetPlayerTier_native(client);
|
||||
if (g_iTierHide > client_tier)
|
||||
if (GetFeatureStatus(FeatureType_Native, "GetPlayerTier_native") == FeatureStatus_Available)
|
||||
{
|
||||
return;
|
||||
int client_tier = GetPlayerTier_native(client);
|
||||
if (g_iTierHide > client_tier)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
switch(action)
|
||||
{
|
||||
@@ -452,7 +512,6 @@ public void OnClientCookiesCached(int client)
|
||||
|
||||
stock bool IsValidClient(int client)
|
||||
{
|
||||
if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client))
|
||||
return true;
|
||||
return false;
|
||||
//IsClientInGame implies IsClientConnected
|
||||
return (client > 0 && client <= MaxClients && IsClientInGame(client));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user