#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; }