From 3f08d6f72cde2a6cf01682901ec851e9ee6b3070 Mon Sep 17 00:00:00 2001 From: Greyscale Date: Thu, 25 Jun 2009 17:03:34 -0700 Subject: [PATCH] Added commands zr_zspawn_force, and zr_ztele_force. Added options to ZAdmin that allow admins to force spawn players, or force teleport players. --- .../translations/zombiereloaded.phrases.txt | 114 +++++++--- src/zr/commands.inc | 2 +- src/zr/infect.inc | 9 +- src/zr/menu.inc | 70 +++++- src/zr/playerclasses/classmenus.inc | 2 +- src/zr/weapons/menu_weapons.inc | 2 +- src/zr/zadmin.inc | 40 +++- src/zr/zspawn.inc | 202 +++++++++++++++--- src/zr/ztele.inc | 151 +++++++++++-- 9 files changed, 499 insertions(+), 93 deletions(-) diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index 79871d0..7492692 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -790,6 +790,40 @@ "en" "Zombies may now only be damaged by headshots." } + // =========================== + // ZAdmin (core) + // =========================== + + "ZAdmin main title" + { + "en" "ZAdmin\n Select Category:" + } + + "ZAdmin main class multipliers" + { + "en" "Class Multipliers" + } + + "ZAdmin main weapons" + { + "en" "Weapon Management" + } + + "ZAdmin main zombie" + { + "en" "Zombie Management" + } + + "ZAdmin main force zspawn " + { + "en" "Force ZSpawn" + } + + "ZAdmin main force ztele" + { + "en" "Force ZTele" + } + // =========================== // Spawn Protect (module) // =========================== @@ -848,6 +882,8 @@ // ZSpawn (module) // =========================== + // General + "ZSpawn double spawn" { "en" "ZSpawn can only be used if you joined late during a round in progress." @@ -859,6 +895,33 @@ "en" "The timelimit ({1} seconds), to use ZSpawn, has already expired." } + // Menu + + "ZSpawn clients title" + { + "en" "Force ZSpawn (zr_zspawn_force)\nSelect a Player:" + } + + // Commands + + "ZSpawn command force syntax" + { + "en" "Force ZSpawn on a client. Usage: zr_zspawn_force ['0' = Spawn as human | '1' = Spawn as zombie]" + + } + + "ZSpawn command force successful" + { + "#format" "{1:s}" + "en" "Player {1} was successfully ZSpawned." + } + + "ZSpawn command force unsuccessful" + { + "#format" "{1:s}" + "en" "Player {1} couldn't be ZSpawned." + } + // =========================== // ZTele (module) // =========================== @@ -906,6 +969,33 @@ "en" "Teleported back to spawn. (Count: {1}/{2})" } + // Menu + + "ZTele clients title" + { + "en" "Force ZTele (zr_ztele_force)\nSelect a Player:" + } + + // Commands + + "ZTele command force syntax" + { + "en" "Force ZTele on a client. Usage: zr_ztele_force " + + } + + "ZTele command force successful" + { + "#format" "{1:s}" + "en" "Player {1} was successfully ZTele'd." + } + + "ZTele command force unsuccessful" + { + "#format" "{1:s}" + "en" "Player {1} couldn't be ZTele'd." + } + // =========================== // ZHP (module) // =========================== @@ -944,28 +1034,4 @@ "#format" "{1:s},{2:d}" "en" "Player {1} has been slayed for camping in a restricted area. (ID: {2})" } - - // =========================== - // ZAdmin Menu - // =========================== - - "ZAdmin main title" - { - "en" "ZAdmin\n Select Category:" - } - - "ZAdmin main class multipliers" - { - "en" "Class Multipliers" - } - - "ZAdmin main weapons" - { - "en" "Weapon Management" - } - - "ZAdmin main zombie" - { - "en" "Zombie Management" - } } \ No newline at end of file diff --git a/src/zr/commands.inc b/src/zr/commands.inc index 6f343e8..7e6fdbc 100644 --- a/src/zr/commands.inc +++ b/src/zr/commands.inc @@ -173,7 +173,7 @@ public Action:Command_Respawn(client, argc) { if (ZRIsClientValid(client)) { - ZRAdminMenu(client); + ZAdminMenu(client); } else { diff --git a/src/zr/infect.inc b/src/zr/infect.inc index 9996e77..758fb67 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -861,11 +861,8 @@ public InfectMenuClientsHandle(Handle:menu_infect_clients, MenuAction:action, cl // Client selected an option. if (action == MenuAction_Select) { - decl String:clientuserid[8]; - GetMenuItem(menu_infect_clients, slot, clientuserid, sizeof(clientuserid)); - - // Get the targetted client through their userid which was set into the menu slot's info param. - new target = GetClientOfUserId(StringToInt(clientuserid)); + // Get selected client index. + new target = MenuGetClientIndex(menu_infect_clients, slot); // If target has left the server, then stop. if (!target) @@ -899,7 +896,7 @@ public InfectMenuClientsHandle(Handle:menu_infect_clients, MenuAction:action, cl if (slot == MenuCancel_ExitBack) { // Re-open admin menu. - ZRAdminMenu(client); + ZAdminMenu(client); } } // Client hit "Exit" button. diff --git a/src/zr/menu.inc b/src/zr/menu.inc index 2b17179..d3b4834 100644 --- a/src/zr/menu.inc +++ b/src/zr/menu.inc @@ -138,7 +138,7 @@ public ZMenuMainHandle(Handle:menu, MenuAction:action, client, slot) case 0: { // Copy return to resend variable. - resend = !ZRAdminMenu(client); + resend = !ZAdminMenu(client); } // Select ZClass. case 1: @@ -197,12 +197,78 @@ public ZMenuMainHandle(Handle:menu, MenuAction:action, client, slot) } } +/** + * Shows a list of all clients to a client, different handlers can be used for this, as well as title. + * + * @param client The client index. + * @param handler The menu handler. + * @param any Title is a translations phrase. + */ +stock MenuClientList(client, MenuHandler:handler, any:...) +{ + // Create menu handle. + new Handle:menu_clients = CreateMenu(handler); + + // Set client as translation target. + SetGlobalTransTarget(client); + + // Translate phrase. + decl String:translation[TRANSLATION_MAX_LENGTH_CHAT]; + VFormat(translation, sizeof(translation), "%t", 3); + + // Set menu title to the translated phrase. + SetMenuTitle(menu_clients, translation); + + decl String:clientoption[MAX_NAME_LENGTH]; + decl String:clientuserid[8]; + + // x = Client index. + for (new x = 1; x <= MaxClients; x++) + { + // If client isn't in-game, then stop. + if (!IsClientInGame(x)) + { + continue; + } + + // Get client info. + GetClientName(x, clientoption, sizeof(clientoption)); + IntToString(GetClientUserId(x), clientuserid, sizeof(clientuserid)); + + // Add option to menu. + AddMenuItem(menu_clients, clientuserid, clientoption); + } + + // Create a "Back" button to the main admin menu. + SetMenuExitBackButton(menu_clients, true); + + // Send menu. + DisplayMenu(menu_clients, client, MENU_TIME_FOREVER); +} + +/** + * Gets the client index of the selected client in the menu. + * + * @param menu The menu handle. + * @param slot The menu slot that was selected. + * @return The client index, 0 if the selected client is no longer in the server. + */ +stock MenuGetClientIndex(Handle:menu, slot) +{ + // Get menu slot's information. + decl String:clientuserid[8]; + GetMenuItem(menu, slot, clientuserid, sizeof(clientuserid)); + + // Return the targetted client through their userid which was set into the menu slot's info param. + return GetClientOfUserId(StringToInt(clientuserid)); +} + /** * Return itemdraw flag for SM menus. * * @param condition If this is true, item will be drawn normally. */ -MenuGetItemDraw(bool:condition) +stock MenuGetItemDraw(bool:condition) { return condition ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; } diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index 18130ff..f5c5d86 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -384,7 +384,7 @@ public ClassTeamSelectHandle(Handle:menu, MenuAction:action, client, slot) { if (slot == MenuCancel_ExitBack) { - ZRAdminMenu(client); + ZAdminMenu(client); } } } diff --git a/src/zr/weapons/menu_weapons.inc b/src/zr/weapons/menu_weapons.inc index d57c6fe..7bc44f5 100644 --- a/src/zr/weapons/menu_weapons.inc +++ b/src/zr/weapons/menu_weapons.inc @@ -104,7 +104,7 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client if (slot == MenuCancel_ExitBack) { // Re-open admin menu. - ZRAdminMenu(client); + ZAdminMenu(client); } } // Client hit "Exit" button. diff --git a/src/zr/zadmin.inc b/src/zr/zadmin.inc index f77bc11..db7ad09 100644 --- a/src/zr/zadmin.inc +++ b/src/zr/zadmin.inc @@ -51,7 +51,7 @@ public Action:ZAdminCommand(client, argc) } // Send admin menu. - ZRAdminMenu(client); + ZAdminMenu(client); // This stops the "Unknown command" message in client's console. return Plugin_Handled; @@ -62,7 +62,7 @@ public Action:ZAdminCommand(client, argc) * * @param client The client index. */ -bool:ZRAdminMenu(client) +bool:ZAdminMenu(client) { // If client isn't an admin, then stop. if (!ZRIsClientAdmin(client)) @@ -72,7 +72,7 @@ bool:ZRAdminMenu(client) } // Create menu handle. - new Handle:menu_zadmin = CreateMenu(ZRAdminMenuHandle); + new Handle:menu_zadmin = CreateMenu(ZAdminMenuHandle); // Set translation target as the client. SetGlobalTransTarget(client); @@ -80,8 +80,8 @@ bool:ZRAdminMenu(client) SetMenuTitle(menu_zadmin, "%t\n ", "ZAdmin main title"); decl String:classmultipliers[64]; - //decl String:zspawn[64]; - //decl String:ztele[64]; + decl String:zspawn[64]; + decl String:ztele[64]; decl String:weapons[64]; decl String:infect[64]; //decl String:logflags[64]; @@ -89,15 +89,15 @@ bool:ZRAdminMenu(client) Format(classmultipliers, sizeof(classmultipliers), "%t", "ZAdmin main class multipliers"); Format(weapons, sizeof(weapons), "%t", "ZAdmin main weapons"); Format(infect, sizeof(infect), "%t", "ZAdmin main zombie"); - //Format(zspawn, sizeof(zspawn), "%t", "!zadmin main spawn"); - //Format(ztele, sizeof(ztele), "%t", "!zadmin main tele"); + Format(zspawn, sizeof(zspawn), "%t", "ZAdmin main force zspawn"); + Format(ztele, sizeof(ztele), "%t", "ZAdmin main force ztele"); //Format(logflags, sizeof(logflags), "%t", "!zadmin main logflags"); AddMenuItem(menu_zadmin, "classmultipliers", classmultipliers); AddMenuItem(menu_zadmin, "weapons", weapons); AddMenuItem(menu_zadmin, "infect", infect); - //AddMenuItem(menu_zadmin, "zspawn", zspawn); - //AddMenuItem(menu_zadmin, "ztele", ztele, ITEMDRAW_DISABLED); + AddMenuItem(menu_zadmin, "zspawn", zspawn); + AddMenuItem(menu_zadmin, "ztele", ztele); //AddMenuItem(menu_zadmin, "logflags", logflags); // Set "Back" button. @@ -118,7 +118,7 @@ bool:ZRAdminMenu(client) * @param client The client index. * @param slot The menu slot selected. (starting from 0) */ -public ZRAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot) +public ZAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot) { if (action == MenuAction_Select) { @@ -146,12 +146,30 @@ public ZRAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot) // Send list of clients to infect. InfectMenuClients(client); } + // Force ZSpawn. + case 3: + { + // We're not resending this menu. + resend = false; + + // Send list of clients to infect. + MenuClientList(client, ZSpawnForceHandle, "ZSpawn clients title"); + } + // Force ZTele. + case 4: + { + // We're not resending this menu. + resend = false; + + // Send list of clients to infect. + MenuClientList(client, ZTeleForceHandle, "ZTele clients title"); + } } // Re-send menu if selection failed. if (resend) { - ZRAdminMenu(client); + ZAdminMenu(client); } } diff --git a/src/zr/zspawn.inc b/src/zr/zspawn.inc index f746588..bb51ef8 100644 --- a/src/zr/zspawn.inc +++ b/src/zr/zspawn.inc @@ -42,6 +42,9 @@ ZSpawnOnCommandsCreate() { // Register ZSpawn command. RegConsoleCmd(SAYHOOKS_KEYWORD_ZSPAWN, ZSpawnCommand, "Spawn into the game after joining late."); + + // Register admin command to force ZSpawn. + RegAdminCmd("zr_zspawn_force", ZSpawnForceCommand, ADMFLAG_GENERIC, "Force ZSpawn on a client. Usage: zr_zspawn_force ['0' = Spawn as human | '1' = Spawn as zombie]"); } /** @@ -162,13 +165,15 @@ ZSpawnOnRoundEnd() * Spawns a late-joining client into the game. * * @param client The client index. + * @param force (Optional) True to force spawning of the client, false to follow rules. + * @param zombie (Optional) If you are forcing spawn, you must override the team here. * @return True if successful, false otherwise. */ -bool:ZSpawnClient(client) +bool:ZSpawnClient(client, bool:force = false, bool:zombie = false) { // If zspawn is disabled, then stop. new bool:zspawn = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN]); - if (!zspawn) + if (!force && !zspawn) { TranslationPrintToChat(client, "Feature is disabled"); return false; @@ -177,60 +182,78 @@ bool:ZSpawnClient(client) // If client isn't on a team, then stop. if (!ZRIsClientOnTeam(client)) { - // Tell client the command may only be used when on a team. - TranslationPrintToChat(client, "Must be on team"); + if (!force) + { + // Tell client the command may only be used when on a team. + TranslationPrintToChat(client, "Must be on team"); + } + return false; } // If client is alive, then stop. if (IsPlayerAlive(client)) { - // Tell client the command may only be used when dead. - TranslationPrintToChat(client, "Must be dead"); + if (!force) + { + // Tell client the command may only be used when dead. + TranslationPrintToChat(client, "Must be dead"); + } + return false; } // Block if client has already played during this round. - if (SteamidCacheClientExists(g_hZSpawnSteamIDCache, client)) + if (!force && SteamidCacheClientExists(g_hZSpawnSteamIDCache, client)) { // Tell client the command may only be used when joining late. TranslationPrintToChat(client, "ZSpawn double spawn"); return false; } - // Check if zspawn override is enabled, and if so get overidden value. - new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]); - new bool:teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]); + new bool:teamzombie; - // Block is the time limit is up. - new bool:zspawntimelimit = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT]); - if (zspawntimelimit) + if (!force) { - if (tZSpawn == INVALID_HANDLE) + // Check if zspawn override is enabled, and if so get overidden value. + new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]); + teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]); + + // Block is the time limit is up. + new bool:zspawntimelimit = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT]); + if (zspawntimelimit) { - new zspawntimelimitzombie = GetConVarInt(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE]); - switch(zspawntimelimitzombie) + if (tZSpawn == INVALID_HANDLE) { - case -1: + new zspawntimelimitzombie = GetConVarInt(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE]); + switch(zspawntimelimitzombie) { - // Get timelimit - new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]); - - // Tell client the timelimit for this command has expired. - TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime)); - return false; - } - case 0: - { - teamzombie = false; - } - case 1: - { - teamzombie = true; + case -1: + { + // Get timelimit + new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]); + + // Tell client the timelimit for this command has expired. + TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime)); + return false; + } + case 0: + { + teamzombie = false; + } + case 1: + { + teamzombie = true; + } } } } } + else + { + // Use the override team in the function if were forcing the spawn. + teamzombie = zombie; + } // Tell respawn module to respawn client. RespawnSpawnClient(client, teamzombie); @@ -238,6 +261,60 @@ bool:ZSpawnClient(client) return true; } +/** + * Menu callback (zspawn_force) + * Forces ZSpawn on a client. + * + * @param menu The menu handle. + * @param action Action client is doing in menu. + * @param client The client index. + * @param slot The menu slot selected. (starting from 0) + */ +public ZSpawnForceHandle(Handle:menu_zspawn_force, MenuAction:action, client, slot) +{ + // Client selected an option. + if (action == MenuAction_Select) + { + // Get the client index of the selected client. + new target = MenuGetClientIndex(menu_zspawn_force, slot); + + // Get the target's name for future use. + decl String:targetname[MAX_NAME_LENGTH]; + GetClientName(target, targetname, sizeof(targetname)); + + // Force ZSpawn on the target. + new bool:success = ZSpawnClient(target, true); + + // Tell admin the outcome of the action. + if (success) + { + TranslationReplyToCommand(client, "ZSpawn command force successful", targetname); + } + else + { + TranslationReplyToCommand(client, "ZSpawn command force unsuccessful", targetname); + } + + // Re-send the menu. + MenuClientList(client, ZSpawnForceHandle, "ZSpawn clients title"); + } + // Client closed the menu. + if (action == MenuAction_Cancel) + { + // Client hit "Back" button. + if (slot == MenuCancel_ExitBack) + { + // Re-open admin menu. + ZAdminMenu(client); + } + } + // Client exited menu. + if (action == MenuAction_End) + { + CloseHandle(menu_zspawn_force); + } +} + /** * Command callback (zspawn) * Spawn into the game after joining late. @@ -261,6 +338,69 @@ public Action:ZSpawnCommand(client, argc) return Plugin_Handled; } +/** + * Command callback (zr_zspawn_force) + * Force ZSpawn on a client. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZSpawnForceCommand(client, argc) +{ + // If not enough arguments given, then stop. + if (argc < 1) + { + TranslationReplyToCommand(client, "ZSpawn command force syntax"); + return Plugin_Handled; + } + + decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH]; + new targets[MAXPLAYERS], bool:tn_is_ml, result; + + // Get targetname. + GetCmdArg(1, target, sizeof(target)); + + // Find a target. + result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_DEAD, targetname, sizeof(targetname), tn_is_ml); + + // Check if there was a problem finding a client. + if (result <= 0) + { + ZRReplyToTargetError(client, result); + return Plugin_Handled; + } + + // Get item to give to client. + decl String:strZombie[4]; + GetCmdArg(2, strZombie, sizeof(strZombie)); + + // Copy value of second (optional) parameter to 'zombie'. + // It will be false if the parameter wasn't specified. + new bool:zombie = bool:StringToInt(strZombie); + + // x = Client index. + for (new x = 0; x < result; x++) + { + // Give client the item. + new bool:success = ZSpawnClient(targets[x], true, zombie); + + // Tell admin the outcome of the command if only 1 client was targetted. + if (result == 1) + { + if (success) + { + TranslationReplyToCommand(client, "ZSpawn command force successful", targetname); + } + else + { + TranslationReplyToCommand(client, "ZSpawn command force unsuccessful", targetname); + } + } + } + + return Plugin_Handled; +} + /** * Timer callback, resets handle. * diff --git a/src/zr/ztele.inc b/src/zr/ztele.inc index e67118a..af9b7dd 100644 --- a/src/zr/ztele.inc +++ b/src/zr/ztele.inc @@ -55,8 +55,11 @@ new g_iZTeleTimeLeft[MAXPLAYERS + 1]; */ ZTeleOnCommandsCreate() { - // Register ZMenu command. + // Register ZTele command. RegConsoleCmd(SAYHOOKS_KEYWORD_ZTELE, ZTeleCommand, "Teleport back to spawn if you are stuck."); + + // Register admin command to force ZTele. + RegAdminCmd("zr_ztele_force", ZTeleForceCommand, ADMFLAG_GENERIC, "Force ZTele on a client. Usage: zr_ztele_force "); } /** @@ -131,9 +134,11 @@ ZTeleOnClientInfected(client) * Teleports a client back to spawn if conditions are met. * * @param client The client index. + * @param force (Optional) True to force teleporting of the client, false to follow rules. + * @param zombie (Optional) True to teleport instantly, false to use delay. * @return True if teleport was successful, false otherwise. */ -bool:ZTeleClient(client) +bool:ZTeleClient(client, bool:force = false) { // If the client is dead, then stop. if (!IsPlayerAlive(client)) @@ -145,7 +150,7 @@ bool:ZTeleClient(client) // If zombie cvar is disabled and the client is a zombie, then stop. new bool:ztelezombie = GetConVarBool(g_hCvarsList[CVAR_ZTELE_ZOMBIE]); - if (infected && !ztelezombie) + if (!force && infected && !ztelezombie) { // Tell client they must be human to use this feature. TranslationPrintToChat(client, "Must be human"); @@ -155,7 +160,7 @@ bool:ZTeleClient(client) // If zombie has spawned, get before value, get the after value otherwise. // If the cvar is disabled and the client is a human, then stop. new bool:ztelehuman = g_bZombieSpawned ? GetConVarBool(g_hCvarsList[CVAR_ZTELE_HUMAN_AFTER]) : GetConVarBool(g_hCvarsList[CVAR_ZTELE_HUMAN_BEFORE]); - if (!infected && !ztelehuman) + if (!force && !infected && !ztelehuman) { // Tell client that feature is restricted at this time. TranslationPrintToChat(client, "ZTele restricted human"); @@ -164,7 +169,7 @@ bool:ZTeleClient(client) // If the tele limit has been reached, then stop. new ztelemax = infected ? GetConVarInt(g_hCvarsList[CVAR_ZTELE_MAX_ZOMBIE]) : GetConVarInt(g_hCvarsList[CVAR_ZTELE_MAX_HUMAN]); - if (g_iZTeleCount[client] >= ztelemax) + if (!force && g_iZTeleCount[client] >= ztelemax) { // Tell client that they have already reached their limit. TranslationPrintToChat(client, "ZTele max", ztelemax); @@ -174,19 +179,26 @@ bool:ZTeleClient(client) // If teleport is already in progress, then stop. if (tZTele[client] != INVALID_HANDLE) { - TranslationPrintToChat(client, "ZTele in progress"); + if (!force) + { + TranslationPrintToChat(client, "ZTele in progress"); + } + return false; } + // If we are forcing, then teleport now and stop. + if (force) + { + // Teleport client to spawn. + ZTeleTeleportClient(client); + + return true; + } + // Get current location. GetClientAbsOrigin(client, g_vecZTeleOrigin[client]); - // If timer is running, kill it. - if (tZTele[client] != INVALID_HANDLE) - { - KillTimer(tZTele[client]); - } - // Set timeleft array to value of respective cvar. g_iZTeleTimeLeft[client] = infected ? GetConVarInt(g_hCvarsList[CVAR_ZTELE_DELAY_ZOMBIE]) : GetConVarInt(g_hCvarsList[CVAR_ZTELE_DELAY_HUMAN]); if (g_iZTeleTimeLeft[client] > 0) @@ -199,12 +211,10 @@ bool:ZTeleClient(client) } else { - // Reset timer handle. - tZTele[client] = INVALID_HANDLE; - // Teleport client to spawn. ZTeleTeleportClient(client); + // If we're forcing the ZTele, then don't increment the count or print how many teleports they have used. // Tell client they've been teleported. TranslationPrintCenterText(client, "ZTele countdown end", g_iZTeleCount[client], ztelemax); @@ -227,7 +237,116 @@ ZTeleTeleportClient(client) } /** - * Command callback (zmenu) + * Menu callback (ztele_force) + * Forces ZTele on a client. + * + * @param menu The menu handle. + * @param action Action client is doing in menu. + * @param client The client index. + * @param slot The menu slot selected. (starting from 0) + */ +public ZTeleForceHandle(Handle:menu_ztele_force, MenuAction:action, client, slot) +{ + // Client selected an option. + if (action == MenuAction_Select) + { + // Get the client index of the selected client. + new target = MenuGetClientIndex(menu_ztele_force, slot); + + // Get the target's name for future use. + decl String:targetname[MAX_NAME_LENGTH]; + GetClientName(target, targetname, sizeof(targetname)); + + // Force ZSpawn on the target. + new bool:success = ZTeleClient(target, true); + + // Tell admin the outcome of the action. + if (success) + { + TranslationReplyToCommand(client, "ZTele command force successful", targetname); + } + else + { + TranslationReplyToCommand(client, "ZTele command force unsuccessful", targetname); + } + + // Re-send the menu. + MenuClientList(client, ZTeleForceHandle, "ZTele clients title"); + } + // Client closed the menu. + if (action == MenuAction_Cancel) + { + // Client hit "Back" button. + if (slot == MenuCancel_ExitBack) + { + // Re-open admin menu. + ZAdminMenu(client); + } + } + // Client exited menu. + if (action == MenuAction_End) + { + CloseHandle(menu_ztele_force); + } +} + +/** + * Command callback (zr_ztele_force) + * Force ZSpawn on a client. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ZTeleForceCommand(client, argc) +{ + // If not enough arguments given, then stop. + if (argc < 1) + { + TranslationReplyToCommand(client, "ZTele command force syntax"); + return Plugin_Handled; + } + + decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH]; + new targets[MAXPLAYERS], bool:tn_is_ml, result; + + // Get targetname. + GetCmdArg(1, target, sizeof(target)); + + // Find a target. + result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_ALIVE, targetname, sizeof(targetname), tn_is_ml); + + // Check if there was a problem finding a client. + if (result <= 0) + { + ZRReplyToTargetError(client, result); + return Plugin_Handled; + } + + // x = Client index. + for (new x = 0; x < result; x++) + { + // Give client the item. + new bool:success = ZTeleClient(targets[x], true); + + // Tell admin the outcome of the command if only 1 client was targetted. + if (result == 1) + { + if (success) + { + TranslationReplyToCommand(client, "ZTele command force successful", targetname); + } + else + { + TranslationReplyToCommand(client, "ZTele command force unsuccessful", targetname); + } + } + } + + return Plugin_Handled; +} + +/** + * Command callback (ztele) * Teleport back to spawn if you are stuck. * * @param client The client index.