diff --git a/_Hide/scripting/Hide_TransmitManager.sp b/_Hide/scripting/Hide_TransmitManager.sp new file mode 100644 index 0000000..274728a --- /dev/null +++ b/_Hide/scripting/Hide_TransmitManager.sp @@ -0,0 +1,402 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* BOOLS */ +bool g_bHasSomebodyToHide[MAXPLAYERS + 1]; +bool g_bHasTobeVisible[MAXPLAYERS + 1]; +bool g_bHidePlayers[MAXPLAYERS + 1][MAXPLAYERS + 1]; + +/* INTEGERS */ +int g_iHideRange[MAXPLAYERS+1]; +int g_iLeader = 0; + +/* HANDLES */ +Handle g_hTimer; + +/* CONVARS */ +ConVar g_hCVar_HideEnabled; + +/* COOKIES */ +Handle g_hCookie_HideRange; + +#define DISABLED -1 +#define SHORT_RANGE 120 +#define MEDIUM_RANGE 250 +#define LONG_RANGE 500 + +int SHORT = SHORT_RANGE * SHORT_RANGE; +int MEDIUM = MEDIUM_RANGE * MEDIUM_RANGE; +int LONG = LONG_RANGE * LONG_RANGE; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public Plugin myinfo = +{ + name = "Hide Teammates with Transmit extension", + author = "jenz, a bunch of re-used code from Neon. credits to pan for fixing it. and thx to zacade", + description = "A plugin that can !hide teammates with individual distances", + version = "1.0.0", + url = "www.unloze.com" +}; + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnPluginStart() +{ + g_hCVar_HideEnabled = CreateConVar("sm_hide_enabled", "1", "", FCVAR_NONE, true, 0.0, true, 1.0); + g_hCVar_HideEnabled.AddChangeHook(OnConVarChanged); + AutoExecConfig(true); + + g_hCookie_HideRange = RegClientCookie("hide_range_transmitext", "", CookieAccess_Private); + + RegConsoleCmd("sm_hide", OnHideSettings, "Hiding near humans"); + + for(int client = 1; client <= MaxClients; client++) + { + if(IsValidClient(client)) + { + OnClientPutInServer(client); + + if(AreClientCookiesCached(client)) + OnClientCookiesCached(client); + } + + } + SetCookieMenuItem(MenuHandler_CookieMenu, 0, "Hide"); + g_hTimer = CreateTimer(1.0, UpdateHide, INVALID_HANDLE, TIMER_REPEAT); +} + +public void OnPluginEnd() +{ + if (g_hTimer != INVALID_HANDLE) + delete g_hTimer; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue) +{ + for(int client = 1; client <= MaxClients; client++) + { + g_bHasSomebodyToHide[client] = false; + for(int target = 1; target <= MaxClients; target++) + { + g_bHidePlayers[client][target] = false; + } + } + + if(g_hCVar_HideEnabled.BoolValue) + CPrintToChatAll("{cyan}[Hide] {white}has been allowed."); + else + CPrintToChatAll("{cyan}[Hide] {white}has been disabled."); +} + +public Action UpdateHide(Handle timer) +{ + if (!g_hCVar_HideEnabled.BoolValue) + return Plugin_Continue; + + bool CheckedEachOtherDistance[MAXPLAYERS + 1][MAXPLAYERS + 1]; + g_iLeader = Leader_CurrentLeader(); + + for (int client = 1; client <= MaxClients; client++) + { + if (!IsValidClient(client) || IsClientSourceTV(client) || IsFakeClient(client)) + { + continue; + } + + 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; + } + + 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. (one direction) + if (ClientIsAlive && ClientIsHuman && (g_iLeader == client || ClientHasItem)) + { + DoTheTargetCheck(client, true, CheckedEachOtherDistance); + } + 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, false, CheckedEachOtherDistance); //(both directions) + } + return Plugin_Continue; +} + +public void DoTheTargetCheck(int client, bool OneDirectional, bool[][] CheckedEachOtherDistance) +{ + float fOriginClient[3]; + float fOriginTarget[3]; + GetClientAbsOrigin(client, fOriginClient); + g_bHasSomebodyToHide[client] = false; + + for (int target = 1; target <= MaxClients; target++) + { + if (!IsValidClient(target) || IsClientSourceTV(target)) + { + continue; + } + + if (!OneDirectional && CheckedEachOtherDistance[client][target]) + { + //the distance between these two Alive humans is already calculated. + //They both are not leader and have no items and they both have hide enabled. + 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) + { + 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] && 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; + //client it not a leader, not an item user and target has hide enabled + if (!OneDirectional && g_iHideRange[target] != DISABLED) + { + //the target here could be a fakeclient. so check that its not. + if (!IsFakeClient(target)) + { + TransmitManager_SetEntityState(client, target, false); //the teammate is hiding the player due to distance + } + g_bHidePlayers[target][client] = true; + } + } + g_bHasSomebodyToHide[client] = true; //theres at least one target to hide for the player, the teammate + //client it not a leader, not an item user and target has hide enabled + if (!OneDirectional && g_iHideRange[target] != DISABLED) + { + g_bHasSomebodyToHide[target] = true; //theres at least one target to hide for the teammate, the player + } + } + 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; + //client it not a leader, not an item user and target has hide enabled + if (!OneDirectional && g_iHideRange[target] != DISABLED) + { + TransmitManager_SetEntityState(target, client, true); //the teammate is seeing the player due to distance + g_bHidePlayers[target][client] = false; + } + } + } + + //client it not a leader, not an item user and target has hide enabled + if (!OneDirectional && g_iHideRange[target] != DISABLED) + { + CheckedEachOtherDistance[client][target] = true; + CheckedEachOtherDistance[target][client] = true; + } + } + } +} + +public Action OnHideSettings(int client, int args) +{ + ShowSettingsMenu(client); + return Plugin_Handled; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void ShowSettingsMenu(int client) +{ + Menu menu = new Menu(MenuHandler_MainMenu); + + char titlemsg[256]; + Format(titlemsg, sizeof(titlemsg), "Hide"); + menu.SetTitle(titlemsg, client); + + char sBuffer[128]; + + Format(sBuffer, sizeof(sBuffer), "Disabled%s", (g_iHideRange[client] == DISABLED) ? " [Selected]" : ""); + menu.AddItem("", sBuffer, (g_iHideRange[client] == DISABLED)); + + Format(sBuffer, sizeof(sBuffer), "Short Range%s", (g_iHideRange[client] == SHORT) ? " [Selected]" : ""); + menu.AddItem("", sBuffer, (g_iHideRange[client] == SHORT)); + + Format(sBuffer, sizeof(sBuffer), "Medium Range%s", (g_iHideRange[client] == MEDIUM) ? " [Selected]" : ""); + menu.AddItem("", sBuffer, (g_iHideRange[client] == MEDIUM)); + + Format(sBuffer, sizeof(sBuffer), "Long Range%s", (g_iHideRange[client] == LONG) ? " [Selected]" : ""); + menu.AddItem("", sBuffer, (g_iHideRange[client] == LONG)); + + if(!g_hCVar_HideEnabled.BoolValue) + menu.AddItem("", "Warning: Hide is currently disabled on the server", ITEMDRAW_DISABLED); + + menu.ExitBackButton = true; + + menu.Display(client, MENU_TIME_FOREVER); +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public int MenuHandler_MainMenu(Menu menu, MenuAction action, int client, int selection) +{ + switch(action) + { + case(MenuAction_Select): + { + switch(selection) + { + case(0): + { + g_iHideRange[client] = DISABLED + } + case(1): + { + g_iHideRange[client] = SHORT + } + case(2): + { + g_iHideRange[client] = MEDIUM + } + case(3): + { + g_iHideRange[client] = LONG + } + } + char sBuffer[16]; + Format(sBuffer, sizeof(sBuffer), "%d", g_iHideRange[client]); + SetClientCookie(client, g_hCookie_HideRange, sBuffer); + ShowSettingsMenu(client); + } + case(MenuAction_Cancel): + { + ShowCookieMenu(client); + } + case(MenuAction_End): + { + delete menu; + } + } + return 0; +} + +//---------------------------------------------------------------------------------------------------- +// Purpose: +//---------------------------------------------------------------------------------------------------- +public void MenuHandler_CookieMenu(int client, CookieMenuAction action, any info, char[] buffer, int maxlen) +{ + switch(action) + { + case(CookieMenuAction_DisplayOption): + { + Format(buffer, maxlen, "Hide", client); + } + case(CookieMenuAction_SelectOption): + { + ShowSettingsMenu(client); + } + } +} + +public void OnClientDisconnect(int client) +{ + g_iHideRange[client] = 0; + g_bHasSomebodyToHide[client] = false; + g_bHasTobeVisible[client] = false; + for(int target = 1; target <= MaxClients; target++) + { + g_bHidePlayers[client][target] = false; + } +} + +public void OnClientPutInServer(int client) +{ + if(!g_hCVar_HideEnabled.BoolValue) + return; + + g_bHasTobeVisible[client] = false; + if (!IsClientSourceTV(client)) + { + TransmitManager_AddEntityHooks(client); + } +} + +public void OnClientCookiesCached(int client) +{ + char sBuffer[16]; + GetClientCookie(client, g_hCookie_HideRange, sBuffer, sizeof(sBuffer)); + + if (sBuffer[0]) + { + g_iHideRange[client] = StringToInt(sBuffer); + if (g_iHideRange[client] != SHORT && g_iHideRange[client] != MEDIUM && g_iHideRange[client] != LONG) + g_iHideRange[client] = DISABLED; + } + else + g_iHideRange[client] = DISABLED; +} + + +stock bool IsValidClient(int client) +{ + if (client > 0 && client <= MaxClients && IsClientConnected(client) && IsClientInGame(client)) + return true; + return false; +}