#include #include #include #include #pragma semicolon 1 #pragma newdecls required #define MENU_TIME MENU_TIME_FOREVER int g_iSelectedTargetUserId[MAXPLAYERS + 1]; bool g_bInvisible[MAXPLAYERS + 1]; bool g_bZeroDamageAttack[MAXPLAYERS + 1]; bool g_bSuperRecoil[MAXPLAYERS + 1]; bool g_bDrugEffect[MAXPLAYERS + 1]; bool g_bRandomFov[MAXPLAYERS + 1]; bool g_bInvertMovement[MAXPLAYERS + 1]; bool g_bInvertMouse[MAXPLAYERS + 1]; Handle g_hDrugTimer[MAXPLAYERS + 1]; Handle g_hRandomFovTimer[MAXPLAYERS + 1]; int g_iEffectTargetUserId[MAXPLAYERS + 1]; public Plugin myinfo = { name = "Super Admin Menu", author = "OpenAI + deidara.dev", description = "Единое супер-админ меню по команде sm_sadmin", version = "1.2" }; public void OnPluginStart() { RegConsoleCmd("sm_sadmin", Command_SuperAdminMenu, "Открыть супер-админ меню"); HookEvent("player_spawn", OnPlayerSpawn, EventHookMode_Post); HookEvent("weapon_fire", OnWeaponFire, EventHookMode_Post); for (int i = 1; i <= MaxClients; i++) { if (IsClientInGame(i)) OnClientPutInServer(i); } } public void OnClientPutInServer(int client) { SDKHook(client, SDKHook_SetTransmit, Hook_SetTransmit); SDKHook(client, SDKHook_OnTakeDamage, Hook_OnTakeDamage); SDKHook(client, SDKHook_OnTakeDamageAlive, Hook_OnTakeDamage); g_hDrugTimer[client] = null; g_hRandomFovTimer[client] = null; } public void OnClientDisconnect(int client) { StopDrugEffect(client); StopRandomFov(client); g_iSelectedTargetUserId[client] = 0; g_iEffectTargetUserId[client] = 0; g_bInvisible[client] = false; g_bZeroDamageAttack[client] = false; g_bSuperRecoil[client] = false; g_bDrugEffect[client] = false; g_bRandomFov[client] = false; g_bInvertMovement[client] = false; g_bInvertMouse[client] = false; } public void OnPlayerSpawn(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); if (!IsValidClient(client)) return; if (g_bInvisible[client]) { SetEntityRenderMode(client, RENDER_TRANSCOLOR); SetEntityRenderColor(client, 255, 255, 255, 0); HidePlayerWeapons(client, true); } if (g_bRandomFov[client]) SetEntProp(client, Prop_Send, "m_iFOV", GetRandomInt(65, 125)); else if (!g_bDrugEffect[client]) SetEntProp(client, Prop_Send, "m_iFOV", 90); } public Action Hook_SetTransmit(int entity, int viewer) { if (entity < 1 || entity > MaxClients) return Plugin_Continue; if (!g_bInvisible[entity]) return Plugin_Continue; if (entity == viewer) return Plugin_Continue; return Plugin_Handled; } public Action Command_SuperAdminMenu(int client, int args) { if (!IsValidClient(client)) { ReplyToCommand(client, "[SM] Эту команду можно использовать только из игры."); return Plugin_Handled; } bool hasRootFlag = (GetUserFlagBits(client) & ADMFLAG_ROOT) != 0; if (!hasRootFlag && !IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] У тебя нет доступа к этому меню."); return Plugin_Handled; } ShowMainMenu(client); return Plugin_Handled; } void ShowMainMenu(int client) { Menu menu = new Menu(MenuHandler_Main); menu.SetTitle("Супер-Админ Меню"); menu.ExitButton = true; bool isDeidara = IsClientInAllowedGroup(client); menu.AddItem("sets", "Выдать сет"); menu.AddItem("money", "Выдать деньги"); menu.AddItem("respawn", "Респавн"); if (isDeidara) { menu.AddItem("restore", "Восстановить 100 HP / 100 Armor"); menu.AddItem("invis", g_bInvisible[client] ? "Выключить невидимость" : "Включить невидимость"); menu.AddItem("tp_to", "Телепорт к игроку"); menu.AddItem("tp_here", "Телепортировать игрока к себе"); menu.AddItem("plant", "Телепорт на плент"); menu.AddItem("effects", "Эффекты игрока"); } menu.Display(client, MENU_TIME); } public int MenuHandler_Main(Menu menu, MenuAction action, int client, int item) { if (action == MenuAction_End) { delete menu; return 0; } if (action != MenuAction_Select) return 0; char info[32]; menu.GetItem(item, info, sizeof(info)); bool isDeidara = IsClientInAllowedGroup(client); if (StrEqual(info, "sets")) { ShowTargetMenu(client, "set"); } else if (StrEqual(info, "money")) { ShowTargetMenu(client, "money"); } else if (StrEqual(info, "respawn")) { ShowTargetMenu(client, "respawn"); } else if (!isDeidara) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); ShowMainMenu(client); } else if (StrEqual(info, "restore")) { ShowTargetMenu(client, "restore"); } else if (StrEqual(info, "invis")) { ToggleInvisibility(client); ShowMainMenu(client); } else if (StrEqual(info, "tp_to")) { ShowTargetMenu(client, "tp_to"); } else if (StrEqual(info, "tp_here")) { ShowTargetMenu(client, "tp_here"); } else if (StrEqual(info, "plant")) { ShowPlantMenu(client); } else if (StrEqual(info, "effects")) { ShowEffectTargetMenu(client); } return 0; } void ShowTargetMenu(int client, const char[] actionType) { if (!IsClientInAllowedGroup(client) && (StrEqual(actionType, "restore") || StrEqual(actionType, "tp_to") || StrEqual(actionType, "tp_here"))) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); ShowMainMenu(client); return; } Menu menu = new Menu(MenuHandler_TargetSelect); char title[128]; Format(title, sizeof(title), "Выбор игрока [%s]", actionType); menu.SetTitle(title); menu.ExitButton = true; menu.ExitBackButton = true; char itemInfo[32]; char name[MAX_NAME_LENGTH]; int added = 0; if (StrEqual(actionType, "restore") || StrEqual(actionType, "respawn") || StrEqual(actionType, "set")) { Format(itemInfo, sizeof(itemInfo), "%s:self", actionType); menu.AddItem(itemInfo, "Себе"); added++; } if (StrEqual(actionType, "restore") || StrEqual(actionType, "respawn")) { Format(itemInfo, sizeof(itemInfo), "%s:all", actionType); menu.AddItem(itemInfo, "Всем"); added++; } for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i) || IsFakeClient(i)) continue; if (StrEqual(actionType, "set") && !IsPlayerAlive(i)) continue; GetClientName(i, name, sizeof(name)); Format(itemInfo, sizeof(itemInfo), "%s:%d", actionType, GetClientUserId(i)); menu.AddItem(itemInfo, name); added++; } if (added == 0) { delete menu; PrintToChat(client, "[SM] Нет доступных игроков."); ShowMainMenu(client); return; } menu.Display(client, MENU_TIME); } public int MenuHandler_TargetSelect(Menu menu, MenuAction action, int client, int item) { if (action == MenuAction_End) { delete menu; return 0; } if (action == MenuAction_Cancel) { if (item == MenuCancel_ExitBack) ShowMainMenu(client); return 0; } if (action != MenuAction_Select) return 0; char info[32], parts[2][16]; menu.GetItem(item, info, sizeof(info)); ExplodeString(info, ":", parts, sizeof(parts), sizeof(parts[])); if (StrEqual(parts[0], "set")) { if (StrEqual(parts[1], "self")) g_iSelectedTargetUserId[client] = GetClientUserId(client); else g_iSelectedTargetUserId[client] = StringToInt(parts[1]); ShowSetMenu(client); } else if (StrEqual(parts[0], "money")) { g_iSelectedTargetUserId[client] = StringToInt(parts[1]); ShowMoneyMenu(client); } else if (StrEqual(parts[0], "restore")) { HandleRestoreSelection(client, parts[1]); } else if (StrEqual(parts[0], "respawn")) { HandleRespawnSelection(client, parts[1]); } else if (StrEqual(parts[0], "tp_to")) { HandleTeleportToPlayer(client, StringToInt(parts[1])); } else if (StrEqual(parts[0], "tp_here")) { HandleTeleportPlayerHere(client, StringToInt(parts[1])); } return 0; } void ShowSetMenu(int client) { int target = GetClientOfUserId(g_iSelectedTargetUserId[client]); if (!IsValidClient(target) || !IsPlayerAlive(target)) { PrintToChat(client, "[SM] Игрок недоступен."); ShowMainMenu(client); return; } char title[128]; Format(title, sizeof(title), "Выдать сет игроку: %N", target); Menu menu = new Menu(MenuHandler_Set); menu.SetTitle(title); menu.ExitButton = true; menu.ExitBackButton = true; menu.AddItem("ak", "AK-47"); menu.AddItem("m4a4", "M4A4"); menu.AddItem("m4a1s", "M4A1-S"); menu.AddItem("awp", "AWP"); menu.AddItem("pistol", "Deagle Only"); menu.Display(client, MENU_TIME); } public int MenuHandler_Set(Menu menu, MenuAction action, int client, int item) { if (action == MenuAction_End) { delete menu; return 0; } if (action == MenuAction_Cancel) { if (item == MenuCancel_ExitBack) ShowTargetMenu(client, "set"); return 0; } if (action != MenuAction_Select) return 0; int target = GetClientOfUserId(g_iSelectedTargetUserId[client]); if (!IsValidClient(target) || !IsPlayerAlive(target)) { PrintToChat(client, "[SM] Игрок недоступен."); ShowMainMenu(client); return 0; } char info[32]; menu.GetItem(item, info, sizeof(info)); GiveFullLoadout(target, info); PrintToRootAdmins("[SM] %N выдал сет игроку %N.", client, target); ShowSetMenu(client); return 0; } void ShowMoneyMenu(int client) { int target = GetClientOfUserId(g_iSelectedTargetUserId[client]); if (!IsValidClient(target)) { PrintToChat(client, "[SM] Игрок недоступен."); ShowMainMenu(client); return; } char title[128]; Format(title, sizeof(title), "Выдать деньги игроку: %N", target); Menu menu = new Menu(MenuHandler_Money); menu.SetTitle(title); menu.ExitButton = true; menu.ExitBackButton = true; menu.AddItem("3000", "3000$"); menu.AddItem("5000", "5000$"); menu.AddItem("10000", "10000$"); menu.AddItem("16000", "16000$"); menu.Display(client, MENU_TIME); } public int MenuHandler_Money(Menu menu, MenuAction action, int client, int item) { if (action == MenuAction_End) { delete menu; return 0; } if (action == MenuAction_Cancel) { if (item == MenuCancel_ExitBack) ShowTargetMenu(client, "money"); return 0; } if (action != MenuAction_Select) return 0; int target = GetClientOfUserId(g_iSelectedTargetUserId[client]); if (!IsValidClient(target)) { PrintToChat(client, "[SM] Игрок недоступен."); ShowMainMenu(client); return 0; } char info[16]; menu.GetItem(item, info, sizeof(info)); int amount = StringToInt(info); int currentMoney = GetEntProp(target, Prop_Send, "m_iAccount"); int newMoney = currentMoney + amount; if (newMoney > 16000) newMoney = 16000; SetEntProp(target, Prop_Send, "m_iAccount", newMoney); PrintToRootAdmins("[SM] %N выдал %d$ игроку %N. Теперь у него %d$.", client, amount, target, newMoney); ShowMoneyMenu(client); return 0; } void HandleRestoreSelection(int client, const char[] targetInfo) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); ShowMainMenu(client); return; } if (StrEqual(targetInfo, "self")) { RestorePlayer(client); PrintToRootAdmins("[SM] %N восстановил себе 100 HP / 100 Armor.", client); } else if (StrEqual(targetInfo, "all")) { int restored = 0; for (int i = 1; i <= MaxClients; i++) { if (IsValidClient(i) && IsPlayerAlive(i)) { RestorePlayer(i); restored++; } } PrintToRootAdmins("[SM] %N восстановил всех живых игроков (%d).", client, restored); } else { int target = GetClientOfUserId(StringToInt(targetInfo)); if (!IsValidClient(target) || !IsPlayerAlive(target)) { PrintToChat(client, "[SM] Игрок недоступен или мертв."); } else { RestorePlayer(target); PrintToRootAdmins("[SM] %N восстановил игроку %N 100 HP / 100 Armor.", client, target); } } ShowMainMenu(client); } void HandleRespawnSelection(int client, const char[] targetInfo) { if (StrEqual(targetInfo, "self")) { if (CanRespawnPlayer(client)) { CS_RespawnPlayer(client); PrintToRootAdmins("[SM] %N возродил себя.", client); } else { PrintToChat(client, "[SM] Вы уже живы или не выбрали команду."); } } else if (StrEqual(targetInfo, "all")) { int respawned = 0; for (int i = 1; i <= MaxClients; i++) { if (CanRespawnPlayer(i)) { CS_RespawnPlayer(i); respawned++; } } PrintToRootAdmins("[SM] %N возродил игроков: %d.", client, respawned); } else { int target = GetClientOfUserId(StringToInt(targetInfo)); if (!CanRespawnPlayer(target)) { PrintToChat(client, "[SM] Игрок недоступен, уже жив или не выбрал команду."); } else { CS_RespawnPlayer(target); PrintToRootAdmins("[SM] %N возродил игрока %N.", client, target); } } ShowMainMenu(client); } void ToggleInvisibility(int client) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); return; } if (!IsPlayerAlive(client)) { PrintToChat(client, "[SM] Невидимость можно включать только когда ты жив."); return; } g_bInvisible[client] = !g_bInvisible[client]; if (g_bInvisible[client]) { SetEntityRenderMode(client, RENDER_TRANSCOLOR); SetEntityRenderColor(client, 255, 255, 255, 0); SetEntProp(client, Prop_Send, "m_bSpotted", 0); HidePlayerWeapons(client, true); PrintToRootAdmins("[SM] %N включил невидимость.", client); } else { SetEntityRenderMode(client, RENDER_NORMAL); SetEntityRenderColor(client, 255, 255, 255, 255); HidePlayerWeapons(client, false); PrintToRootAdmins("[SM] %N выключил невидимость.", client); } } void HidePlayerWeapons(int client, bool hide) { for (int slot = 0; slot <= 4; slot++) { int weapon = GetPlayerWeaponSlot(client, slot); if (weapon != -1 && IsValidEntity(weapon)) { SetEntityRenderMode(weapon, RENDER_TRANSCOLOR); SetEntityRenderColor(weapon, 255, 255, 255, hide ? 0 : 255); } } } void HandleTeleportToPlayer(int client, int targetUserId) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); return; } int target = GetClientOfUserId(targetUserId); if (!IsValidClient(target) || !IsPlayerAlive(target) || !IsPlayerAlive(client)) { PrintToChat(client, "[SM] Телепорт невозможен. Ты или выбранный игрок мертвы/недоступны."); ShowMainMenu(client); return; } float pos[3], ang[3], fwdVec[3], flatAng[3]; GetClientAbsOrigin(target, pos); GetClientAbsAngles(target, ang); // Позиция: 20 юнитов перед целью (по горизонтали) flatAng[0] = 0.0; flatAng[1] = ang[1]; flatAng[2] = 0.0; GetAngleVectors(flatAng, fwdVec, NULL_VECTOR, NULL_VECTOR); pos[0] += fwdVec[0] * 20.0; pos[1] += fwdVec[1] * 20.0; // Смотрим на цель (разворот на 180°) float faceAng[3]; faceAng[0] = 0.0; faceAng[1] = ang[1] + 180.0; if (faceAng[1] > 180.0) faceAng[1] -= 360.0; if (faceAng[1] <= -180.0) faceAng[1] += 360.0; faceAng[2] = 0.0; TeleportEntity(client, pos, faceAng, NULL_VECTOR); PrintToRootAdmins("[SM] %N телепортировался к игроку %N.", client, target); ShowMainMenu(client); } void HandleTeleportPlayerHere(int client, int targetUserId) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); return; } int target = GetClientOfUserId(targetUserId); if (!IsValidClient(target) || !IsPlayerAlive(target) || !IsPlayerAlive(client)) { PrintToChat(client, "[SM] Телепорт невозможен. Ты или выбранный игрок мертвы/недоступны."); ShowMainMenu(client); return; } float pos[3], ang[3], fwdVec[3], flatAng[3]; GetClientAbsOrigin(client, pos); GetClientAbsAngles(client, ang); // Позиция: 20 юнитов перед собой (по горизонтали) flatAng[0] = 0.0; flatAng[1] = ang[1]; flatAng[2] = 0.0; GetAngleVectors(flatAng, fwdVec, NULL_VECTOR, NULL_VECTOR); pos[0] += fwdVec[0] * 20.0; pos[1] += fwdVec[1] * 20.0; // Игрок смотрит на нас (разворот на 180°) float faceAng[3]; faceAng[0] = 0.0; faceAng[1] = ang[1] + 180.0; if (faceAng[1] > 180.0) faceAng[1] -= 360.0; if (faceAng[1] <= -180.0) faceAng[1] += 360.0; faceAng[2] = 0.0; TeleportEntity(target, pos, faceAng, NULL_VECTOR); PrintToRootAdmins("[SM] %N телепортировал игрока %N к себе.", client, target); ShowMainMenu(client); } void ShowPlantMenu(int client) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); ShowMainMenu(client); return; } Menu menu = new Menu(MenuHandler_Plant); menu.SetTitle("Телепорт на плент"); menu.ExitButton = true; menu.ExitBackButton = true; menu.AddItem("A", "Плент A"); menu.AddItem("B", "Плент B"); menu.Display(client, MENU_TIME); } public int MenuHandler_Plant(Menu menu, MenuAction action, int client, int item) { if (action == MenuAction_End) { delete menu; return 0; } if (action == MenuAction_Cancel) { if (item == MenuCancel_ExitBack) ShowMainMenu(client); return 0; } if (action != MenuAction_Select) return 0; char info[8]; menu.GetItem(item, info, sizeof(info)); if (!IsPlayerAlive(client)) { PrintToChat(client, "[SM] Для телепорта на плент нужно быть живым."); ShowMainMenu(client); return 0; } float origin[3]; if (FindBombsiteCenter(info[0], origin)) { origin[2] += 10.0; TeleportEntity(client, origin, NULL_VECTOR, NULL_VECTOR); PrintToRootAdmins("[SM] %N телепортировался на плент %s.", client, info); } else { PrintToChat(client, "[SM] Плент %s не найден на этой карте.", info); } ShowMainMenu(client); return 0; } // Проверяет, совпадает ли имя сущности с нужным плентом (A или B) bool IsBombsiteNameMatch(int entity, char siteLetter) { char name[64]; GetEntPropString(entity, Prop_Data, "m_iName", name, sizeof(name)); if (name[0] == '\0') return false; char lo[2]; lo[0] = CharToLower(siteLetter); lo[1] = '\0'; char pat1[32], pat2[32], pat3[32], pat4[32]; Format(pat1, sizeof(pat1), "bombsite_%s", lo); // bombsite_a / bombsite_b Format(pat2, sizeof(pat2), "bombsite%s", lo); // bombsitea / bombsiteb Format(pat3, sizeof(pat3), "site_%s", lo); // site_a / site_b Format(pat4, sizeof(pat4), "bomb_%s", lo); // bomb_a / bomb_b return (StrContains(name, pat1, false) != -1 || StrContains(name, pat2, false) != -1 || StrContains(name, pat3, false) != -1 || StrContains(name, pat4, false) != -1); } // Центр brush-сущности через абсолютный origin + локальные bounds void GetBrushCenter(int entity, float out[3]) { float absOrigin[3], mins[3], maxs[3]; GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", absOrigin); GetEntPropVector(entity, Prop_Send, "m_vecMins", mins); GetEntPropVector(entity, Prop_Send, "m_vecMaxs", maxs); out[0] = absOrigin[0] + (mins[0] + maxs[0]) / 2.0; out[1] = absOrigin[1] + (mins[1] + maxs[1]) / 2.0; out[2] = absOrigin[2] + maxs[2]; // верхняя граница, игрок встанет сверху } bool FindBombsiteCenter(char siteLetter, float origin[3]) { // Проход 1: func_bomb_target (brush) с совпадением имени int entity = -1; while ((entity = FindEntityByClassname(entity, "func_bomb_target")) != -1) { if (IsBombsiteNameMatch(entity, siteLetter)) { GetBrushCenter(entity, origin); return true; } } // Проход 2: info_bomb_target (point entity) с совпадением имени entity = -1; while ((entity = FindEntityByClassname(entity, "info_bomb_target")) != -1) { if (IsBombsiteNameMatch(entity, siteLetter)) { GetEntPropVector(entity, Prop_Data, "m_vecAbsOrigin", origin); return true; } } // Проход 3: безымянный/нестандартный — берём первый/второй по порядку // A = первый найденный, B = второй найденный entity = -1; int found = 0; int target = (siteLetter == 'A') ? 1 : 2; while ((entity = FindEntityByClassname(entity, "func_bomb_target")) != -1) { found++; if (found == target) { GetBrushCenter(entity, origin); return true; } } return false; } void RestorePlayer(int client) { if (!IsValidClient(client) || !IsPlayerAlive(client)) return; SetEntityHealth(client, 100); SetEntProp(client, Prop_Send, "m_ArmorValue", 100); SetEntProp(client, Prop_Send, "m_bHasHelmet", 1); } bool CanRespawnPlayer(int client) { return IsValidClient(client) && !IsPlayerAlive(client) && GetClientTeam(client) >= CS_TEAM_T; } void GiveFullLoadout(int client, const char[] type) { StripWeapons(client); SetEntProp(client, Prop_Send, "m_ArmorValue", 100); SetEntProp(client, Prop_Send, "m_bHasHelmet", 1); if (GetClientTeam(client) == CS_TEAM_CT) SetEntProp(client, Prop_Send, "m_bHasDefuser", 1); if (StrEqual(type, "ak")) GivePlayerItem(client, "weapon_ak47"); else if (StrEqual(type, "m4a4")) GivePlayerItem(client, "weapon_m4a1"); else if (StrEqual(type, "m4a1s")) GivePlayerItem(client, "weapon_m4a1_silencer"); else if (StrEqual(type, "awp")) GivePlayerItem(client, "weapon_awp"); GivePlayerItem(client, "weapon_deagle"); GivePlayerItem(client, "weapon_knife"); if (!StrEqual(type, "pistol")) { GivePlayerItem(client, "weapon_hegrenade"); GivePlayerItem(client, "weapon_smokegrenade"); GivePlayerItem(client, "weapon_flashbang"); GivePlayerItem(client, "weapon_flashbang"); if (GetClientTeam(client) == CS_TEAM_T) GivePlayerItem(client, "weapon_molotov"); else GivePlayerItem(client, "weapon_incgrenade"); } if (g_bInvisible[client]) HidePlayerWeapons(client, true); } void StripWeapons(int client) { int weapon; for (int slot = 0; slot <= 4; slot++) { while ((weapon = GetPlayerWeaponSlot(client, slot)) != -1) { RemovePlayerItem(client, weapon); AcceptEntityInput(weapon, "Kill"); } } } void ShowEffectTargetMenu(int client) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); ShowMainMenu(client); return; } Menu menu = new Menu(MenuHandler_EffectTarget); menu.SetTitle("Эффекты: выбор игрока"); menu.ExitButton = true; menu.ExitBackButton = true; char info[16]; char name[MAX_NAME_LENGTH]; int added = 0; for (int i = 1; i <= MaxClients; i++) { if (!IsValidClient(i) || IsFakeClient(i)) continue; GetClientName(i, name, sizeof(name)); IntToString(GetClientUserId(i), info, sizeof(info)); menu.AddItem(info, name); added++; } if (added == 0) { delete menu; PrintToChat(client, "[SM] Нет доступных игроков."); ShowMainMenu(client); return; } menu.Display(client, MENU_TIME); } public int MenuHandler_EffectTarget(Menu menu, MenuAction action, int client, int item) { if (!IsClientInAllowedGroup(client)) { if (action == MenuAction_End) delete menu; else if (action == MenuAction_Select) PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); return 0; } if (action == MenuAction_End) { delete menu; return 0; } if (action == MenuAction_Cancel) { if (item == MenuCancel_ExitBack) ShowMainMenu(client); return 0; } if (action != MenuAction_Select) return 0; char info[16]; menu.GetItem(item, info, sizeof(info)); g_iEffectTargetUserId[client] = StringToInt(info); ShowEffectMenu(client); return 0; } void ShowEffectMenu(int client) { if (!IsClientInAllowedGroup(client)) { PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); ShowMainMenu(client); return; } int target = GetClientOfUserId(g_iEffectTargetUserId[client]); if (!IsValidClient(target)) { PrintToChat(client, "[SM] Игрок недоступен."); ShowMainMenu(client); return; } char title[128]; Format(title, sizeof(title), "Эффекты для игрока: %N", target); Menu menu = new Menu(MenuHandler_EffectMenu); menu.SetTitle(title); menu.ExitButton = true; menu.ExitBackButton = true; menu.AddItem("nodamage", g_bZeroDamageAttack[target] ? "Выключить 0 урона" : "Включить 0 урона"); menu.AddItem("recoil", g_bSuperRecoil[target] ? "Выключить супер-отдачу" : "Включить супер-отдачу"); menu.AddItem("drug", g_bDrugEffect[target] ? "Выключить drug-эффект" : "Включить drug-эффект"); menu.AddItem("randomfov", g_bRandomFov[target] ? "Выключить случайный FOV" : "Включить случайный FOV"); menu.AddItem("invertmove", g_bInvertMovement[target] ? "Выключить инверсию движения" : "Включить инверсию движения"); menu.AddItem("invertmouse", g_bInvertMouse[target] ? "Выключить инверсию мыши" : "Включить инверсию мыши"); menu.AddItem("shake", "Сильно тряхнуть экран"); menu.AddItem("blind", "Ослепить на 2 сек"); menu.Display(client, MENU_TIME); } public int MenuHandler_EffectMenu(Menu menu, MenuAction action, int client, int item) { if (!IsClientInAllowedGroup(client)) { if (action == MenuAction_End) delete menu; else if (action == MenuAction_Select) PrintToChat(client, "[SM] Этот пункт доступен только группам DEIDARA и TESTER."); return 0; } if (action == MenuAction_End) { delete menu; return 0; } if (action == MenuAction_Cancel) { if (item == MenuCancel_ExitBack) ShowEffectTargetMenu(client); return 0; } if (action != MenuAction_Select) return 0; int target = GetClientOfUserId(g_iEffectTargetUserId[client]); if (!IsValidClient(target)) { PrintToChat(client, "[SM] Игрок недоступен."); ShowMainMenu(client); return 0; } char info[16]; menu.GetItem(item, info, sizeof(info)); if (StrEqual(info, "nodamage")) { g_bZeroDamageAttack[target] = !g_bZeroDamageAttack[target]; PrintToRootAdmins("[SM] %N: 0 урона для %N -> %s", client, target, g_bZeroDamageAttack[target] ? "ВКЛ" : "ВЫКЛ"); } else if (StrEqual(info, "recoil")) { g_bSuperRecoil[target] = !g_bSuperRecoil[target]; PrintToRootAdmins("[SM] %N: супер-отдача для %N -> %s", client, target, g_bSuperRecoil[target] ? "ВКЛ" : "ВЫКЛ"); } else if (StrEqual(info, "drug")) { ToggleDrugEffect(target); PrintToRootAdmins("[SM] %N: drug-эффект для %N -> %s", client, target, g_bDrugEffect[target] ? "ВКЛ" : "ВЫКЛ"); } else if (StrEqual(info, "randomfov")) { ToggleRandomFov(target); PrintToRootAdmins("[SM] %N: случайный FOV для %N -> %s", client, target, g_bRandomFov[target] ? "ВКЛ" : "ВЫКЛ"); } else if (StrEqual(info, "invertmove")) { g_bInvertMovement[target] = !g_bInvertMovement[target]; PrintToRootAdmins("[SM] %N: инверсия движения для %N -> %s", client, target, g_bInvertMovement[target] ? "ВКЛ" : "ВЫКЛ"); } else if (StrEqual(info, "invertmouse")) { g_bInvertMouse[target] = !g_bInvertMouse[target]; PrintToRootAdmins("[SM] %N: инверсия мыши для %N -> %s", client, target, g_bInvertMouse[target] ? "ВКЛ" : "ВЫКЛ"); } else if (StrEqual(info, "shake")) { ApplyStrongShake(target); PrintToRootAdmins("[SM] %N сильно тряхнул экран игрока %N.", client, target); } else if (StrEqual(info, "blind")) { BlindPlayer(target, 2.0); PrintToRootAdmins("[SM] %N ослепил игрока %N на 2 сек.", client, target); } ShowEffectMenu(client); return 0; } public Action Hook_OnTakeDamage(int victim, int &attacker, int &inflictor, float &damage, int &damagetype) { if (attacker > 0 && attacker <= MaxClients && IsClientInGame(attacker) && g_bZeroDamageAttack[attacker]) { damage = 0.0; damagetype = 0; return Plugin_Changed; } return Plugin_Continue; } public Action OnPlayerRunCmd(int client, int &buttons, int &impulse, float vel[3], float angles[3], int &weapon, int &subtype, int &cmdnum, int &tickcount, int &seed, int mouse[2]) { if (!IsValidClient(client) || !IsPlayerAlive(client)) return Plugin_Continue; bool changed = false; if (g_bInvertMovement[client]) { vel[0] = -vel[0]; vel[1] = -vel[1]; bool hasForward = (buttons & IN_FORWARD) != 0; bool hasBack = (buttons & IN_BACK) != 0; bool hasMoveLeft = (buttons & IN_MOVELEFT) != 0; bool hasMoveRight= (buttons & IN_MOVERIGHT) != 0; buttons &= ~(IN_FORWARD | IN_BACK | IN_MOVELEFT | IN_MOVERIGHT); if (hasForward) buttons |= IN_BACK; if (hasBack) buttons |= IN_FORWARD; if (hasMoveLeft) buttons |= IN_MOVERIGHT; if (hasMoveRight) buttons |= IN_MOVELEFT; changed = true; } if (g_bInvertMouse[client]) { mouse[1] = -mouse[1]; changed = true; } return changed ? Plugin_Changed : Plugin_Continue; } public void OnWeaponFire(Event event, const char[] name, bool dontBroadcast) { int client = GetClientOfUserId(event.GetInt("userid")); if (!IsValidClient(client) || !IsPlayerAlive(client) || !g_bSuperRecoil[client]) return; float recoil[3]; recoil[0] = GetRandomFloat(-18.0, -10.0); recoil[1] = GetRandomFloat(-8.0, 8.0); recoil[2] = 0.0; SetEntPropVector(client, Prop_Send, "m_aimPunchAngle", recoil); SetEntPropVector(client, Prop_Send, "m_viewPunchAngle", recoil); ApplyStrongShake(client); } void ToggleRandomFov(int client) { if (!IsValidClient(client)) return; if (g_bRandomFov[client]) { StopRandomFov(client); return; } g_bRandomFov[client] = true; if (g_hRandomFovTimer[client] != null) { KillTimer(g_hRandomFovTimer[client]); g_hRandomFovTimer[client] = null; } if (IsPlayerAlive(client)) SetEntProp(client, Prop_Send, "m_iFOV", GetRandomInt(65, 125)); g_hRandomFovTimer[client] = CreateTimer(1.0, Timer_RandomFov, GetClientUserId(client), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); } void StopRandomFov(int client) { if (client < 1 || client > MaxClients) return; g_bRandomFov[client] = false; if (g_hRandomFovTimer[client] != null) { KillTimer(g_hRandomFovTimer[client]); g_hRandomFovTimer[client] = null; } if (IsValidClient(client) && !g_bDrugEffect[client]) SetEntProp(client, Prop_Send, "m_iFOV", 90); } public Action Timer_RandomFov(Handle timer, any userid) { int client = GetClientOfUserId(userid); if (!IsValidClient(client) || !IsPlayerAlive(client) || !g_bRandomFov[client]) { if (client > 0 && client <= MaxClients) g_hRandomFovTimer[client] = null; return Plugin_Stop; } SetEntProp(client, Prop_Send, "m_iFOV", GetRandomInt(65, 125)); return Plugin_Continue; } void ToggleDrugEffect(int client) { if (!IsValidClient(client)) return; if (g_bDrugEffect[client]) { StopDrugEffect(client); return; } g_bDrugEffect[client] = true; if (g_hDrugTimer[client] != null) { KillTimer(g_hDrugTimer[client]); g_hDrugTimer[client] = null; } g_hDrugTimer[client] = CreateTimer(0.8, Timer_DrugEffect, GetClientUserId(client), TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); } void StopDrugEffect(int client) { if (client < 1 || client > MaxClients) return; g_bDrugEffect[client] = false; if (g_hDrugTimer[client] != null) { KillTimer(g_hDrugTimer[client]); g_hDrugTimer[client] = null; } if (IsValidClient(client) && !g_bRandomFov[client]) SetEntProp(client, Prop_Send, "m_iFOV", 90); } public Action Timer_DrugEffect(Handle timer, any userid) { int client = GetClientOfUserId(userid); if (!IsValidClient(client) || !IsPlayerAlive(client) || !g_bDrugEffect[client]) { if (client > 0 && client <= MaxClients) g_hDrugTimer[client] = null; return Plugin_Stop; } float punch[3]; punch[0] = GetRandomFloat(-7.0, 7.0); punch[1] = GetRandomFloat(-7.0, 7.0); punch[2] = 0.0; SetEntPropVector(client, Prop_Send, "m_viewPunchAngle", punch); SetEntPropVector(client, Prop_Send, "m_aimPunchAngle", punch); SetEntProp(client, Prop_Send, "m_iFOV", GetRandomInt(80, 115)); ApplyStrongShake(client); return Plugin_Continue; } void ApplyStrongShake(int client) { if (!IsValidClient(client)) return; int shake = CreateEntityByName("env_shake"); if (shake == -1) return; DispatchKeyValueFloat(shake, "amplitude", 20.0); DispatchKeyValueFloat(shake, "radius", 300.0); DispatchKeyValueFloat(shake, "duration", 1.2); DispatchKeyValueFloat(shake, "frequency", 255.0); DispatchSpawn(shake); float pos[3]; GetClientAbsOrigin(client, pos); TeleportEntity(shake, pos, NULL_VECTOR, NULL_VECTOR); AcceptEntityInput(shake, "StartShake", client, client); CreateTimer(1.5, Timer_KillEntity, EntIndexToEntRef(shake), TIMER_FLAG_NO_MAPCHANGE); } void BlindPlayer(int client, float duration) { if (!IsValidClient(client) || !IsPlayerAlive(client)) return; // Используем встроенные пропы флэшбанга CS:GO — никакого usermsgs, безопасно SetEntPropFloat(client, Prop_Send, "m_flFlashDuration", duration); SetEntPropFloat(client, Prop_Send, "m_flFlashMaxAlpha", 255.0); } public Action Timer_KillEntity(Handle timer, any entRef) { int ent = EntRefToEntIndex(entRef); if (ent != INVALID_ENT_REFERENCE && ent != -1 && IsValidEntity(ent)) AcceptEntityInput(ent, "Kill"); return Plugin_Stop; } #define SADMIN_NOTIFY_GROUP_1 "DEIDARA" #define SADMIN_NOTIFY_GROUP_2 "TESTER" bool IsClientInAllowedGroup(int client) { if (!IsValidClient(client)) return false; AdminId admin = GetUserAdmin(client); if (admin == INVALID_ADMIN_ID) return false; int groupCount = GetAdminGroupCount(admin); char groupName[64]; for (int i = 0; i < groupCount; i++) { GroupId gid = GetAdminGroup(admin, i, groupName, sizeof(groupName)); if (gid != INVALID_GROUP_ID) { if (StrEqual(groupName, SADMIN_NOTIFY_GROUP_1, false) || StrEqual(groupName, SADMIN_NOTIFY_GROUP_2, false)) { return true; } } } return false; } void PrintToRootAdmins(const char[] format, any ...) { char buffer[256]; VFormat(buffer, sizeof(buffer), format, 2); for (int i = 1; i <= MaxClients; i++) { if (IsClientInAllowedGroup(i)) { PrintToChat(i, "%s", buffer); } } } bool IsValidClient(int client) { return (client > 0 && client <= MaxClients && IsClientInGame(client)); }