Files
sm-plugins/Leader3/scripting/leader3/menu.sp
T
2026-10-22 16:17:56 +01:00

366 lines
9.3 KiB
SourcePawn

//----------------------------------------------------------------------------------------------------
// Leader3 menus. Opened with !leader or the flashlight key (impulse 100).
//----------------------------------------------------------------------------------------------------
bool CanManageLeaders(int client)
{
return IsPrimaryLeader(client) || CheckCommandAccess(client, "sm_admin", ADMFLAG_GENERIC, false);
}
void AddMarkerMenuItem(Menu menu, int client, const char[] info, const char[] name, int skin)
{
char title[128], display[160];
if (Marker_GetTitle(client, skin, title, sizeof(title)))
{
Format(display, sizeof(display), "%s: %s", name, title);
menu.AddItem(info, display);
}
else
{
menu.AddItem(info, name);
}
}
void ShowLeaderMenu(int client)
{
if (!IsLeader(client))
return;
Menu menu = new Menu(MenuHandler_Main);
menu.SetTitle("Leader Menu (%s)\nBeacon: %s | Xray: %s",
IsPrimaryLeader(client) ? "PRIMARY" : "SUB-LEADER",
(g_iEffectFlags[client] & EFFECT_BEACON) ? "On" : "Off",
(g_iEffectFlags[client] & EFFECT_XRAY) ? "On" : "Off");
AddMarkerMenuItem(menu, client, "skull", "Skull", SKIN_SKULL);
AddMarkerMenuItem(menu, client, "cross", "Cross", SKIN_CROSS);
AddMarkerMenuItem(menu, client, "moon", "Moon", SKIN_MOON);
AddMarkerMenuItem(menu, client, "star", "Star", SKIN_STAR);
menu.AddItem("clear", "Clear markers");
char buf[32];
switch (g_iSpriteChoice[client])
{
case SPRITE_CHOICE_FOLLOW: buf = "Sprite: Follow me";
case SPRITE_CHOICE_DEFEND: buf = "Sprite: Defend here";
default: buf = "Sprite: Off";
}
menu.AddItem("sprite", buf);
menu.AddItem("settings", "Settings");
menu.ExitButton = true;
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_Main(Menu menu, MenuAction action, int client, int position)
{
if (action == MenuAction_End)
{
delete menu;
return 0;
}
if (action != MenuAction_Select || !IsLeader(client))
return 0;
char info[32];
menu.GetItem(position, info, sizeof(info));
// Zombie leaders may still use the settings menu and clear their own markers;
// the other main-menu items act in the world, so don't act and just let the menu close.
if (IsLivingZombie(client) && !StrEqual(info, "settings") && !StrEqual(info, "clear"))
{
PrintToChat(client, "%sYou cannot use this as a zombie.", PREFIX);
return 0;
}
int skin = SkinFromName(info);
if (skin != -1)
{
Marker_Place(client, skin);
ShowLeaderMenu(client);
}
else if (StrEqual(info, "clear"))
{
Marker_ClearByOwner(client);
ShowLeaderMenu(client);
}
else if (StrEqual(info, "sprite"))
{
// Rotate Off -> Follow me -> Defend here -> Off.
switch (g_iSpriteChoice[client])
{
case SPRITE_NONE: Sprite_Set(client, SPRITE_CHOICE_FOLLOW);
case SPRITE_CHOICE_FOLLOW: Sprite_Set(client, SPRITE_CHOICE_DEFEND);
default: Sprite_Set(client, SPRITE_NONE);
}
ShowLeaderMenu(client);
}
else if (StrEqual(info, "settings"))
{
ShowSettingsMenu(client);
}
return 0;
}
//----------------------------------------------------------------------------------------------------
// Settings / Extra
//----------------------------------------------------------------------------------------------------
void ShowSettingsMenu(int client)
{
Menu menu = new Menu(MenuHandler_Settings);
menu.SetTitle("Leader Settings");
char buf[64];
Format(buf, sizeof(buf), "Beacon: %s", (g_iEffectFlags[client] & EFFECT_BEACON) ? "On" : "Off");
menu.AddItem("beacon", buf);
Format(buf, sizeof(buf), "Xray: %s", (g_iEffectFlags[client] & EFFECT_XRAY) ? "On" : "Off");
menu.AddItem("xray", buf);
switch (g_iTracerMode[client])
{
case TRACER_MODE_TAP: buf = "Tracer: Hold + Tap-toggle";
case TRACER_MODE_HOLD: buf = "Tracer: Hold only";
default: buf = "Tracer: Off";
}
menu.AddItem("tracer", buf);
menu.AddItem("resign", "Resign from Leader");
if (CanManageLeaders(client))
{
menu.AddItem("manage", "Manage Leaders");
menu.AddItem("clearall", "Clear ALL Markers");
Format(buf, sizeof(buf), "Force-Mute: %s", g_bForceLeaderMute ? "On" : "Off");
menu.AddItem("forcemute", buf);
}
menu.ExitBackButton = true;
menu.ExitButton = true;
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_Settings(Menu menu, MenuAction action, int client, int position)
{
if (action == MenuAction_End)
{
delete menu;
return 0;
}
if (action == MenuAction_Cancel && position == MenuCancel_ExitBack)
{
ShowLeaderMenu(client);
return 0;
}
if (action != MenuAction_Select || !IsLeader(client))
return 0;
char info[32];
menu.GetItem(position, info, sizeof(info));
if (StrEqual(info, "beacon"))
{
Beacon_Toggle(client);
ShowSettingsMenu(client);
}
else if (StrEqual(info, "xray"))
{
Xray_Toggle(client);
ShowSettingsMenu(client);
}
else if (StrEqual(info, "tracer"))
{
Tracer_CycleMode(client);
ShowSettingsMenu(client);
}
else if (StrEqual(info, "resign"))
{
RemoveLeaderClient(client, "resigned");
}
else if (StrEqual(info, "manage") && CanManageLeaders(client))
{
ShowManageMenu(client);
}
else if (StrEqual(info, "clearall") && CanManageLeaders(client))
{
Markers_ClearAll();
PrintToChatAll("%sAll markers have been cleared by \x04%N\x01.", PREFIX, client);
ShowSettingsMenu(client);
}
else if (StrEqual(info, "forcemute") && CanManageLeaders(client))
{
// Enabling is reserved for whitelisted leaders; disabling is not.
if (!g_bForceLeaderMute && !Whitelist_IsWhitelisted(client))
{
PrintToChat(client, "%sOnly players on the leader whitelist can enable force mute.", PREFIX);
}
else
{
g_bForceLeaderMute = !g_bForceLeaderMute;
PrintToChatAll("%s\x04%N\x01 %s force mute while a leader is speaking!", PREFIX, client,
g_bForceLeaderMute ? "activated" : "deactivated");
}
ShowSettingsMenu(client);
}
return 0;
}
//----------------------------------------------------------------------------------------------------
// Manage leaders (primary leader or admin)
//----------------------------------------------------------------------------------------------------
void ShowManageMenu(int client)
{
Menu menu = new Menu(MenuHandler_Manage);
menu.SetTitle("Manage Leaders\n[P] primary, [L] sub-leader");
char info[12], display[MAX_NAME_LENGTH + 8];
bool any = false;
// Active leaders first, in roster order (index 0 = primary).
for (int i = 0; i < g_alLeaders.Length; i++)
{
int leader = GetClientOfUserId(g_alLeaders.Get(i));
if (leader <= 0)
continue;
any = true;
IntToString(GetClientUserId(leader), info, sizeof(info));
Format(display, sizeof(display), "[%s] %N", i == 0 ? "P" : "L", leader);
menu.AddItem(info, display);
}
// Then everyone else who could become one.
for (int i = 1; i <= MaxClients; i++)
{
if (g_bIsLeader[i] || !IsClientInGame(i) || IsFakeClient(i))
continue;
if (!IsLivingHuman(i))
continue;
any = true;
IntToString(GetClientUserId(i), info, sizeof(info));
Format(display, sizeof(display), "%N", i);
menu.AddItem(info, display);
}
if (!any)
menu.AddItem("", "No players available", ITEMDRAW_DISABLED);
menu.ExitBackButton = true;
menu.ExitButton = true;
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_Manage(Menu menu, MenuAction action, int client, int position)
{
if (action == MenuAction_End)
{
delete menu;
return 0;
}
if (action == MenuAction_Cancel && position == MenuCancel_ExitBack)
{
ShowSettingsMenu(client);
return 0;
}
if (action != MenuAction_Select || !CanManageLeaders(client))
return 0;
char info[12];
menu.GetItem(position, info, sizeof(info));
int target = GetClientOfUserId(StringToInt(info));
if (target == 0)
{
PrintToChat(client, "%sThat player is no longer available.", PREFIX);
ShowManageMenu(client);
return 0;
}
ShowManageActionMenu(client, target);
return 0;
}
void ShowManageActionMenu(int client, int target)
{
Menu menu = new Menu(MenuHandler_ManageAction);
menu.SetTitle("Manage: %N", target);
char info[16];
IntToString(GetClientUserId(target), info, sizeof(info));
if (g_bIsLeader[target])
{
if (!IsPrimaryLeader(target))
menu.AddItem(info, "Make Primary Leader");
menu.AddItem(info, "Demote (remove leader)");
}
else
{
menu.AddItem(info, "Promote to Sub-Leader");
}
menu.ExitBackButton = true;
menu.ExitButton = true;
menu.Display(client, MENU_TIME_FOREVER);
}
public int MenuHandler_ManageAction(Menu menu, MenuAction action, int client, int position)
{
if (action == MenuAction_End)
{
delete menu;
return 0;
}
if (action == MenuAction_Cancel && position == MenuCancel_ExitBack)
{
ShowManageMenu(client);
return 0;
}
if (action != MenuAction_Select || !CanManageLeaders(client))
return 0;
char info[16], display[64];
int style;
menu.GetItem(position, info, sizeof(info), style, display, sizeof(display));
int target = GetClientOfUserId(StringToInt(info));
if (target == 0)
{
PrintToChat(client, "%sThat player is no longer available.", PREFIX);
ShowManageMenu(client);
return 0;
}
if (StrContains(display, "Primary") != -1)
{
Core_MakePrimary(target, client);
}
else if (StrContains(display, "Demote") != -1)
{
char reason[80];
Format(reason, sizeof(reason), "demoted by \x04%N\x01", client);
RemoveLeaderClient(target, reason);
}
else if (StrContains(display, "Promote") != -1)
{
if (!IsLivingHuman(target))
PrintToChat(client, "%sThat player has to be a living human.", PREFIX);
else
AddLeader(target, false, client);
}
ShowManageMenu(client);
return 0;
}