From e051b7bdaa2db03ffafbc443d7ec46a372ea7c47 Mon Sep 17 00:00:00 2001 From: Greyscale Date: Thu, 14 May 2009 02:28:26 +0200 Subject: [PATCH] Created overlay module to unify class overlays and round end overlays, removed unused class overlay functions, fixed invalid hookid error, allow client to toggle class overlay if allowed in cvar and made toggle cmds configurable, cleaned up translations file. --- .../translations/zombiereloaded.phrases.txt | 127 ++++---- src/zombiereloaded.sp | 18 +- src/zr/antistick.inc | 10 +- src/zr/commands.inc | 146 ++------- src/zr/cvars.inc | 48 +-- src/zr/damage.inc | 41 ++- src/zr/event.inc | 5 +- src/zr/infect.inc | 8 +- src/zr/log.inc | 4 +- src/zr/overlays.inc | 284 ++++++++++++++++++ src/zr/playerclasses/apply.inc | 15 - src/zr/playerclasses/classevents.inc | 33 +- src/zr/playerclasses/classmenus.inc | 21 +- src/zr/playerclasses/clientoverlays.inc | 181 ++++++----- src/zr/playerclasses/playerclasses.inc | 2 + src/zr/roundend.inc | 136 ++------- src/zr/translation.inc | 4 +- src/zr/weapons/restrict.inc | 111 ++++++- src/zr/weapons/weapons.inc | 6 + src/zr/zhp.inc | 2 +- src/zr/zombie.inc | 39 --- src/zr/zombiereloaded.inc | 10 - 22 files changed, 743 insertions(+), 508 deletions(-) create mode 100644 src/zr/overlays.inc diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index cd50212..48803bf 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -4,34 +4,15 @@ // General // =========================== - "Round objective" + "General round objective" { "en" "The game is @greenHumans vs. Zombies@default, the goal for zombies is to infect all humans by knifing them." "ru" "Битва @greenЛюдей против Зомби@default, цель для зомби - инфицировать всех людей." } - "You are a zombie" + "General zmenu reminder" { - "en" "You have been infected! Now go pass it on to as many people as you can." - "ru" "Вы были инфицированы! Теперь вы охотитесь за людьми." - } - - "Zombie replacement" - { - "en" "The last zombie has left the game, and has passed the infection on to you." - "ru" "Последний зомби покинул игру и передал свою инфекцию вам." - } - - "Auto-assign" - { - "#format" "{1:s}" - "en" "You have randomly been assigned to the @green\"{1}\" @defaultclass." - "ru" "Вам был случайным образом установлен класс \"{1}\"." - } - - "!zmenu reminder" - { - "en" "Type !zmenu in chat to view all ZR commands." + "en" "For help on Zombie:Reloaded commands, type !zmenu in chat." "ru" "Напишите !zmenu в чате для просмотра всех команд." } @@ -94,38 +75,90 @@ // General - "!zclass admin mode enabled" + "Classes admin mode enabled" { "en" "Admin mode is enabled!" } + "Classes random assignment" + { + "#format" "{1:s}" + "en" "You have randomly been assigned to the @green\"{1}\" @defaultclass." + "ru" "Вам был случайным образом установлен класс \"{1}\"." + } + + // Center Text/HUD + + "Classes overlay toggle" + { + "#format" "{1:s}" + "en" "Class overlay toggle commands: {1}" + } + // Menu - "!zclass title" + "Classes menu title" { "en" "Class Selection:" } - "!zclass zombie" + "Classes menu zombie" { "en" "Select Zombie Class" } - "!zclass human" + "Classes menu human" { "en" "Select Human Class" } - "!zclass admin" + "Classes menu admin" { "en" "Select Admin Class" } - "!zclass admin mode toggle" + "Classes menu admin mode toggle" { "en" "Toggle Admin Mode" } + // =========================== + // (core) Overlays + // =========================== + + "Overlays not supported" + { + "#format" "{1:d},{2:d}" + "en" "Blocking Overlay - DX{1} Detected (DX{2} Required)" + "ru" "Оверлей Отключен - Обнаружен DX{1} (Необходим DX{2})" + } + + // =========================== + // (core) Infect + // =========================== + + // General + + "Infect infected" + { + "en" "You have been infected! Go pass it on to as many other players as you can." + } + + "Infect disconnect" + { + "en" "The last zombie has left the game, and has passed the infection on to you." + "ru" "Последний зомби покинул игру и передал свою инфекцию вам." + } + + // =========================== + // (core) Damage + // =========================== + + "Damage suicide intercept" + { + "en" "Suicide attempt intercepted." + } + // =========================== // Menu (core) // =========================== @@ -168,15 +201,6 @@ "en" "ZMarket ({1}) - Need a weapon? Buy them here." } - // =========================== - // (core) Damage - // =========================== - - "Damage suicide intercept" - { - "en" "Suicide attempt intercepted." - } - // =========================== // (core) Weapons // =========================== @@ -460,13 +484,6 @@ "en" "Player {1} has been slayed for camping in a restricted area. (ID: {2})" } - "DX90 not supported" - { - "#format" "{1:d},{2:d}" - "en" "Blocking Overlay - DX{1} Detected (DX{2} Required)" - "ru" "Оверлей Отключен - Обнаружен DX{1} (Необходим DX{2})" - } - // =========================== // ZAdmin Menu // =========================== @@ -617,26 +634,4 @@ { "en" "Toggle Logging Flags:" } - - // =========================== - // Server Messages - // =========================== - - "ZR" - { - "en" "ZR" - "ru" "ZR" - } - - "Plugin loading" - { - "en" "-----------| Zombie:Reloaded Loading |----------" - "ru" "-----------| Zombie:Reloaded Загружается |----------" - } - - "Plugin loaded" - { - "en" "-----------| Zombie:Reloaded Loaded |----------" - "ru" "-----------| Zombie:Reloaded Загружен |----------" - } } \ No newline at end of file diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index d0becc7..e630811 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -31,6 +31,7 @@ #include "zr/sayhooks" #include "zr/tools" #include "zr/models" +#include "zr/overlays" #include "zr/playerclasses/playerclasses" #include "zr/weapons/weapons" #include "zr/hitgroups" @@ -98,9 +99,6 @@ public OnPluginStart() LoadTranslations("common.phrases.txt"); LoadTranslations("zombiereloaded.phrases.txt"); - // Start loading ZR init functions. - ZR_PrintToServer("Plugin loading"); - // Log LogInit(); @@ -110,16 +108,12 @@ public OnPluginStart() // Tools ToolsInit(); - // TODO: Be modulized/recoded. - CreateCommands(); - HookCommands(); + // Commands + CommandsInit(); // Weapons WeaponsInit(); - // Damage - DamageInit(); - // Say Hooks SayHooksInit(); @@ -131,9 +125,6 @@ public OnPluginStart() // Create public cvar for tracking. CreateConVar("gs_zombiereloaded_version", VERSION, "[ZR] Current version of this plugin", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_UNLOGGED|FCVAR_DONTRECORD|FCVAR_REPLICATED|FCVAR_NOTIFY); - - // Finish loading ZR init functions. - ZR_PrintToServer("Plugin loaded"); } /** @@ -171,6 +162,7 @@ public OnMapStart() { // Forward event to modules. SerialOnMapStart(); + OverlaysOnMapStart(); RoundEndOnMapStart(); InfectOnMapStart(); SEffectsOnMapStart(); @@ -216,8 +208,8 @@ public OnClientPutInServer(client) { // Forward event to modules. ClassClientInit(client); + OverlaysClientInit(client); WeaponsClientInit(client); - RoundEndClientInit(client); InfectClientInit(client); DamageClientInit(client); SEffectsClientInit(client); diff --git a/src/zr/antistick.inc b/src/zr/antistick.inc index b624c84..5904395 100644 --- a/src/zr/antistick.inc +++ b/src/zr/antistick.inc @@ -31,12 +31,12 @@ /** * Handle to keep track of AntiStickTimer. -*/ + */ new Handle:tAntiStick = INVALID_HANDLE; /** * Map is starting. -*/ + */ AntiStickOnMapStart() { // Reset timer handle. @@ -71,7 +71,7 @@ AntiStickOnRoundStart() * @param client The client index. * @return The client index of the other stuck player, -1 when * player is not stuck. -*/ + */ AntiStickIsStuck(client) { new Float:clientloc[3]; @@ -116,7 +116,7 @@ AntiStickIsStuck(client) /** * Timer callback, automatically unsticks players that are stuck together. -*/ + */ public Action:AntiStickTimer(Handle:timer) { // x = client index @@ -155,7 +155,7 @@ public Action:AntiStickTimer(Handle:timer) * * @param timer The timer handle. * @param client The client index. -*/ + */ public Action:AntiStickSolidify(Handle:timer, any:client) { // Validate player is in-game, alive, and is being unstuck. diff --git a/src/zr/commands.inc b/src/zr/commands.inc index a98183e..688da55 100644 --- a/src/zr/commands.inc +++ b/src/zr/commands.inc @@ -1,19 +1,33 @@ -/** - * ==================== +/* + * ============================================================================ + * * Zombie:Reloaded - * File: commands.inc - * Author: Greyscale - * ==================== + * + * File: commands.inc + * Type: Core + * Description: Console command creation and hooking. + * + * ============================================================================ */ - -CreateCommands() + +/** + * Commands are created/hooked. + */ +CommandsInit() +{ + // Forward event to modules. (create commands) + WeaponsOnCommandsCreate(); + + // Forward event to modules. (hook commands) + ClassOnCommandsHook(); + DamageOnCommandsHook(); +} + +/*CreateCommands() { RegAdminCmd("zr_infect", Command_Infect, ADMFLAG_GENERIC, "Infects the specified player"); RegAdminCmd("zr_spawn", Command_Respawn, ADMFLAG_GENERIC, "Respawns the specified player following auto-respawning rules"); - // Weapon restrict commands - RegAdminCmd("zr_restrict", Command_Restrict, ADMFLAG_GENERIC, "Restrict a specified weapon"); - RegAdminCmd("zr_unrestrict", Command_Unrestrict, ADMFLAG_GENERIC, "Unrestrict a specified weapon"); //RegAdminCmd("zr_set_class_knockback", Command_SetClassKnockback, ADMFLAG_GENERIC, "Sets the knockback to the specified class. Usage: zr_set_class_knockback "); //RegAdminCmd("zr_get_class_knockback", Command_GetClassKnockback, ADMFLAG_GENERIC, "Gets the knockback to the specified class. Usage: zr_get_class_knockback "); @@ -29,9 +43,10 @@ CreateCommands() RegConsoleCmd("zr_class_dump", Command_ClassDump, "Dumps class data at a specified index in the specified cache. Usage: zr_class_dump "); RegAdminCmd("zr_class_modify", Command_ClassModify, ADMFLAG_GENERIC, "Modify class data on one or more classes. Usage: zr_class_modify [is_multiplier]"); -} + +}*/ -public Action:Command_Infect(client, argc) +/*public Action:Command_Infect(client, argc) { new bool:enabled = GetConVarBool(g_hCvarsList[CVAR_ENABLE]); if (argc < 1 || !enabled) @@ -129,110 +144,9 @@ public Action:Command_Respawn(client, argc) } return Plugin_Handled; -} +}*/ -/** - * Command callback (zr_restrict) - * Restricts a weapon or group - * - * @param client The client index. - * @param argc Argument count. -*/ -public Action:Command_Restrict(client, argc) -{ - // Disabled. - // If plugin is disabled then stop - /**new bool:enabled = GetConVarBool(g_hCvarsList[CVAR_ENABLE]); - if (argc < 1 || !enabled) - { - return Plugin_Handled; - }*/ - - // If weapons module is disabled, then stop. - new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]); - if (!weapons) - { - // Tell client command is disabled. - ZR_ReplyToCommand(client, "Feature is disabled"); - return Plugin_Handled; - } - - // If restrict module is disabled, then stop. - new bool:restrict = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_RESTRICT]); - if (!restrict) - { - // Tell client command is disabled. - ZR_ReplyToCommand(client, "Feature is disabled"); - return Plugin_Handled; - } - - // arg1 = weapon being restricted - decl String:arg1[32]; - GetCmdArg(1, arg1, sizeof(arg1)); - - // Strip "weapon_" from entity name - ReplaceString(arg1, sizeof(arg1), "weapon_", ""); - - decl String:display[WEAPONS_MAX_LENGTH]; - - new WpnRestrictQuery:output = RestrictRestrict(arg1, display); - RestrictPrintRestrictOutput(client, output, display, true); - - return Plugin_Handled; -} - -/** - * Command callback (zr_unrestrict) - * Unrestricts a weapon or group - * - * @param client The client index. - * @param argc Argument count. -*/ -public Action:Command_Unrestrict(client, argc) -{ - // Disabled. - // If plugin is disabled then stop - /**new bool:enabled = GetConVarBool(g_hCvarsList[CVAR_ENABLE]); - if (argc < 1 || !enabled) - { - return Plugin_Handled; - }*/ - - // If weapons module is disabled, then stop. - new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]); - if (!weapons) - { - // Tell client command is disabled. - ZR_ReplyToCommand(client, "Feature is disabled"); - return Plugin_Handled; - } - - // If restrict module is disabled, then stop. - new bool:restrict = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_RESTRICT]); - if (!restrict) - { - // Tell client command is disabled. - ZR_ReplyToCommand(client, "Feature is disabled"); - return Plugin_Handled; - } - - // arg1 = weapon being restricted - decl String:arg1[32]; - GetCmdArg(1, arg1, sizeof(arg1)); - - // Strip "weapon_" from entity name - ReplaceString(arg1, sizeof(arg1), "weapon_", ""); - - decl String:display[WEAPONS_MAX_LENGTH]; - - new WpnRestrictQuery:output = RestrictUnrestrict(arg1, display); - RestrictPrintUnrestrictOutput(client, output, display, true); - - return Plugin_Handled; -} - - -public Action:Command_AdminMenu(client, argc) +/*public Action:Command_AdminMenu(client, argc) { if (ZRIsClientValid(client)) { @@ -308,4 +222,4 @@ public Action:Command_LogFlags(client, argc) ReplyToCommand(client, message); return Plugin_Handled; -} +}*/ diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 3247062..3d190aa 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -36,6 +36,9 @@ enum CvarsList Handle:CVAR_CLASSES_DEFAULT_ZOMBIE, Handle:CVAR_CLASSES_DEFAULT_HUMAN, Handle:CVAR_CLASSES_DEFAULT_ADMIN, + Handle:CVAR_CLASSES_OVERLAY_TOGGLE, + Handle:CVAR_CLASSES_OVERLAY_TOGGLECMDS, + Handle:CVAR_CLASSES_OVERLAY_DEFAULT, Handle:CVAR_WEAPONS, Handle:CVAR_WEAPONS_RESTRICT, Handle:CVAR_WEAPONS_ZMARKET_BUYZONE, @@ -49,6 +52,7 @@ enum CvarsList Handle:CVAR_SAYHOOKS_QUIET, Handle:CVAR_SAYHOOKS_QUIET_FILTER, Handle:CVAR_SAYHOOKS_QUIET_FLAGS, + Handle:CVAR_OVERLAYS_UPDATE_TIME, Handle:CVAR_ROUNDEND_OVERLAY, Handle:CVAR_ROUNDEND_OVERLAY_ZOMBIE, Handle:CVAR_ROUNDEND_OVERLAY_HUMAN, @@ -117,8 +121,6 @@ enum CvarsList Handle:CVAR_ZHP_DEFAULT, // To be modulized/recoded. - Handle:CVAR_OVERLAY_REDISPLAY, - Handle:CVAR_ZVISION_ALLOW_DISABLE, Handle:CVAR_MENU_AUTOCLOSE, Handle:CVAR_ANTICAMP, Handle:CVAR_ANTICAMP_UPDATE_INTERVAL, @@ -224,6 +226,8 @@ CvarsCreate() // Classes (core) // =========================== + // General + g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", ""); // Old Desc: Classmenu is re-displayed every spawn (0: Disable) g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", ""); @@ -235,6 +239,14 @@ CvarsCreate() g_hCvarsList[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "random", ""); // Old Desc: Default admin-only class selected for admins when they connect. Use \"random\" to select a random class, or blank to use class config defaults. + // Overlays + + g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLE] = CreateConVar("zr_classes_overlay_toggle", "1", ""); + // Desc: Allow clients to toggle class overlay, zr_classes_overlay_default will be applied on connect. + g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLECMDS] = CreateConVar("zr_classes_overlay_togglecmds", "nightvision", ""); + g_hCvarsList[CVAR_CLASSES_OVERLAY_DEFAULT] = CreateConVar("zr_classes_overlay_default", "0", ""); + // Desc: Default toggle value of class overlay. [Ignored when zr_classes_overlay_toggle is disabled.] + // =========================== // Weapons (core) // =========================== @@ -262,17 +274,6 @@ CvarsCreate() g_hCvarsList[CVAR_HITGROUPS] = CreateConVar("zr_hitgroups", "1", ""); // Note make config file cvar. - // =========================== - // Round End (core) - // =========================== - - g_hCvarsList[CVAR_ROUNDEND_OVERLAY] = CreateConVar("zr_roundend_overlay", "1", ""); - // Old Desc: Shows an overlay to all clients when a team wins. (0: Disable) - g_hCvarsList[CVAR_ROUNDEND_OVERLAY_HUMAN] = CreateConVar("zr_roundend_overlays_human", "overlays/zr/humans_win"); - // Old Desc: overlays/zr/humans_win", "Path to \"humans win\" overlay - g_hCvarsList[CVAR_ROUNDEND_OVERLAY_ZOMBIE] = CreateConVar("zr_roundend_overlays_zombie", "overlays/zr/zombies_win", ""); - // Old Desc: Path to \"zombies win\" overlay - // =========================== // Infect (core) // =========================== @@ -337,6 +338,23 @@ CvarsCreate() // 32 Quiet "!zhp" say hook. // 64 Quiet "!zmarket" say hook. + // =========================== + // Overlays (core) + // =========================== + + g_hCvarsList[CVAR_OVERLAYS_UPDATE_TIME] = CreateConVar("zr_overlays_update_time", "1.0", ""); + + // =========================== + // Round End (core) + // =========================== + + g_hCvarsList[CVAR_ROUNDEND_OVERLAY] = CreateConVar("zr_roundend_overlay", "1", ""); + // Old Desc: Shows an overlay to all clients when a team wins. (0: Disable) + g_hCvarsList[CVAR_ROUNDEND_OVERLAY_HUMAN] = CreateConVar("zr_roundend_overlays_human", "overlays/zr/humans_win"); + // Old Desc: overlays/zr/humans_win", "Path to \"humans win\" overlay + g_hCvarsList[CVAR_ROUNDEND_OVERLAY_ZOMBIE] = CreateConVar("zr_roundend_overlays_zombie", "overlays/zr/zombies_win", ""); + // Old Desc: Path to \"zombies win\" overlay + // =========================== // Account (module) // =========================== @@ -480,10 +498,6 @@ CvarsCreate() // Old Desc: The default value of zombie health display to new clients (1: On, 0: Off) - // TO BE MODULIZED/RECODED. - g_hCvarsList[CVAR_OVERLAY_REDISPLAY] = CreateConVar("zr_overlay_redisplay", "3", ""); - // Old Desc: Frequency, in seconds, to display overlay on the client's screen (Never go below 0.1, 0.2 seems safe) - g_hCvarsList[CVAR_ZVISION_ALLOW_DISABLE] = CreateConVar("zr_zvision_allow_disable", "1", ""); // Old Desc: Allow users to disable ZVision with their nightvision key (0: Disable) g_hCvarsList[CVAR_MENU_AUTOCLOSE] = CreateConVar("zr_menu_autoclose", "0", ""); // Old Desc: Automatically close menus on selection. If disabled the menu will remain open. diff --git a/src/zr/damage.inc b/src/zr/damage.inc index bfb83b3..79b716e 100644 --- a/src/zr/damage.inc +++ b/src/zr/damage.inc @@ -24,23 +24,22 @@ */ /** - * List of damage-related hooks. + * Array to store TraceAttack HookIDs. */ -enum DamageHooks -{ - Hook_TraceAttack, /** TraceAttack HookID */ - Hook_OnTakeDamage, /** OnTakeDamage HookID */ -} - -new g_iDamageHookID[MAXPLAYERS + 1][DamageHooks]; +new g_iDamageTraceAttackHookID[MAXPLAYERS + 1] = {-1, ...}; /** - * Damage module init function. + * Array to store OnTakeDamage HookIDs. */ -DamageInit() +new g_iDamageOnTakeDamageHookID[MAXPLAYERS + 1] = {-1, ...}; + +/** + * Hook commands related to damage here. + */ +DamageOnCommandsHook() { // Create command callbacks (intercepts) for listed suicide commands. - decl String:suicidecmds[64]; + decl String:suicidecmds[DAMAGE_SUICIDE_MAX_CMDS * DAMAGE_SUICIDE_MAX_LENGTH]; GetConVarString(g_hCvarsList[CVAR_DAMAGE_SUICIDE_CMDS], suicidecmds, sizeof(suicidecmds)); // Create array to store cmds @@ -66,8 +65,8 @@ DamageInit() DamageClientInit(client) { // Hook damage callbacks. - g_iDamageHookID[client][Hook_TraceAttack] = ZRTools_HookTraceAttack(client, DamageTraceAttack); - g_iDamageHookID[client][Hook_OnTakeDamage] = ZRTools_HookOnTakeDamage(client, DamageOnTakeDamage); + g_iDamageTraceAttackHookID[client] = ZRTools_HookTraceAttack(client, DamageTraceAttack); + g_iDamageOnTakeDamageHookID[client] = ZRTools_HookOnTakeDamage(client, DamageOnTakeDamage); } /** @@ -77,9 +76,19 @@ DamageClientInit(client) */ DamageOnClientDisconnect(client) { - // Unhook damage callbacks. - ZRTools_UnhookTraceAttack(g_iDamageHookID[client][Hook_TraceAttack]); - ZRTools_UnhookOnTakeDamage(g_iDamageHookID[client][Hook_OnTakeDamage]); + // Unhook damage callbacks, and reset variables. + + if (g_iDamageTraceAttackHookID[client] != -1) + { + ZRTools_UnhookTraceAttack(g_iDamageTraceAttackHookID[client]); + g_iDamageTraceAttackHookID[client] = -1; + } + + if (g_iDamageOnTakeDamageHookID[client] != -1) + { + ZRTools_UnhookOnTakeDamage(g_iDamageOnTakeDamageHookID[client]); + g_iDamageOnTakeDamageHookID[client] = -1; + } } /** diff --git a/src/zr/event.inc b/src/zr/event.inc index fba8390..ca8d4ec 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -66,9 +66,10 @@ EventHook(bool:unhook = false) */ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadcast) { - ZR_PrintToChat(0, "Round objective"); + ZR_PrintToChat(0, "General round objective"); // Forward event to sub-modules. + OverlaysOnRoundStart(); RoundEndOnRoundStart(); InfectOnRoundStart(); SEffectsOnRoundStart(); @@ -182,7 +183,7 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad ZTeleOnClientSpawn(index); ZHPOnClientSpawn(index); - ZR_PrintToChat(index, "!zmenu reminder"); + ZR_PrintToChat(index, "General zmenu reminder"); } /** diff --git a/src/zr/infect.inc b/src/zr/infect.inc index 9af6ae5..a45d0d8 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -180,7 +180,7 @@ InfectOnClientDisconnect(client) InfectClient(randclient); // Tell client they have been randomly been chosen to replace disconnecting zombie. - ZR_PrintToChat(randclient, "Zombie replacement"); + ZR_PrintToChat(randclient, "Infect disconnect"); // Destroy handle. CloseHandle(arrayEligibleClients); @@ -565,6 +565,12 @@ InfectClient(client, attacker = -1, bool:motherinfect = false) // TODO: A solution to stop confusing bots? Respawn and teleport? CS_SwitchTeam(client, CS_TEAM_T); + // Format infection message. + SetGlobalTransTarget(client); + + // Print message to client. + ZR_PrintToChat(client, "Infect infected"); + // Forward event to modules. ClassOnClientInfected(client, motherinfect); RoundEndOnClientInfected(); diff --git a/src/zr/log.inc b/src/zr/log.inc index 6544ae9..193a068 100644 --- a/src/zr/log.inc +++ b/src/zr/log.inc @@ -156,7 +156,7 @@ LogMessageFormatted(client, const String:module[], const String:block[], const S SetGlobalTransTarget(client); // Print to client. - PrintToConsole(client, "%t %s", "ZR", logtext); + PrintToConsole(client, "[ZR] %s", logtext); } } @@ -183,7 +183,7 @@ LogToAdmins(String:message[]) SetGlobalTransTarget(x); // Format message to admin, then print. - Format(buffer, sizeof(buffer), "%t %s", "ZR", message); + Format(buffer, sizeof(buffer), "[ZR] %s", message); PrintToChat(x, buffer); } } diff --git a/src/zr/overlays.inc b/src/zr/overlays.inc new file mode 100644 index 0000000..9df5186 --- /dev/null +++ b/src/zr/overlays.inc @@ -0,0 +1,284 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: overlays.inc + * Type: Core + * Description: Overlay system, separating different types into "overlay channels." + * + * ============================================================================ + */ + +/** + * Minimum dx level required to see overlays. + */ +#define OVERLAYS_DXL_MIN 90 + +/** + * Maximum amount of overlay channels. + */ +#define OVERLAYS_CHANNEL_MAX 2 + +/** + * All possible overlay channels, in order of priority. + */ +enum OverlaysChannel +{ + OVERLAYS_CHANNEL_NONE = -1, /** Client has no overlay */ + OVERLAYS_CHANNEL_ROUNDEND = 0, /** Round win overlay */ + OVERLAYS_CHANNEL_CLASSES = 1, /** Class overlay */ +} + +/** + * Global variable to store a convar query cookie + */ +new QueryCookie:mat_dxlevel; + +/** + * The DirectX level of a client. + */ +new g_iOverlaysDXL[MAXPLAYERS + 1]; + +/** + * Array to track overlay channel state on each client. + */ +new bool:g_bOverlayChannel[MAXPLAYERS + 1][OverlaysChannel]; + +/** + * Array to store overlay path for each channel. + */ +new String:g_strOverlayPath[MAXPLAYERS + 1][OverlaysChannel][PLATFORM_MAX_PATH]; + +/** + * Create variable to store global timer handle. + */ +new Handle:tOverlays = INVALID_HANDLE; + +/** + * Map is starting. + */ +OverlaysOnMapStart() +{ + // Reset timer handle. + tOverlays = INVALID_HANDLE; +} + +/** + * Client is joining the server. + * + * @param client The client index. + */ +OverlaysClientInit(client) +{ + // x = channel index. + for (new x = 0; x < OVERLAYS_CHANNEL_MAX; x++) + { + // Disable all channels, and reset. + OverlaysClientSetChannelState(client, OverlaysChannel:x, false, false, false, true); + } + + // Get client's DX level. + OverlaysGetClientDXLevel(client); +} + +/** + * Finds DX level of a client. + * + * @param client The client index. + */ +OverlaysGetClientDXLevel(client) +{ + // If client is fake (or bot), then stop. + if (IsFakeClient(client)) + { + return; + } + + // Query mat_dxlevel on client. + mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", OverlaysQueryClientDXLevel); +} + +/** + * Query callback function. + * + * @param cookie Unique cookie of the query. + * @param client The client index. + * @param result The result of the query (see console.inc enum ConVarQueryResult) + * @param cvarName Name of the cvar. + * @param cvarValue Value of the cvar. + */ +public OverlaysQueryClientDXLevel(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) +{ + // If query cookie does not match cookie given by mat_dxlevel query, then stop, this isn't our query. + if (cookie != mat_dxlevel) + { + return; + } + + // Reset dxLevel. + g_iOverlaysDXL[client] = 0; + + // If result is any other than ConVarQuery_Okay, then stop. + if (result != ConVarQuery_Okay) + { + return; + } + + // Copy cvar value to dxLevel array. + g_iOverlaysDXL[client] = StringToInt(cvarValue); +} + +/** + * The round is starting. + */ +OverlaysOnRoundStart() +{ + // If timer is running, kill it. + if (tOverlays != INVALID_HANDLE) + { + KillTimer(tOverlays); + } + + // If antistick is disabled, then stop. + new Float:overlaysupdate = GetConVarFloat(g_hCvarsList[CVAR_OVERLAYS_UPDATE_TIME]); + if (overlaysupdate <= 0.0) + { + return; + } + + // Start repeating timer. + tOverlays = CreateTimer(overlaysupdate, OverlaysTimer, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE); +} + +/** + * Update overlay on a client. (Displays highest priority overlays first, if enabled.) + * + * @param client The client index. + * @param channel (Optional) The channel overlay to update. + */ +OverlaysClientUpdateOverlay(client, OverlaysChannel:channel = OVERLAYS_CHANNEL_NONE) +{ + // Find highest priority, enabled, overlay channel of client. + if (channel == OVERLAYS_CHANNEL_NONE) + { + channel = OverlaysClientFindChannel(client); + } + // Stop here if client has no overlay channel enabled. + if (channel == OVERLAYS_CHANNEL_NONE) + { + // Clear any existing overlay from screen. + ClientCommand(client, "r_screenoverlay \"\""); + return; + } + + // If dxLevel is 0, then query on client failed, so try again, then stop. + if (!g_iOverlaysDXL[client]) + { + // Query dxlevel cvar, again. + OverlaysGetClientDXLevel(client); + return; + } + + // If client doesn't meet DXLevel requirement, then tell client, then stop. + if (g_iOverlaysDXL[client] < OVERLAYS_DXL_MIN) + { + ZR_PrintCenterText(client, "Overlays not supported", g_iOverlaysDXL[client], OVERLAYS_DXL_MIN); + return; + } + + // Display overlay to client. + ClientCommand(client, "r_screenoverlay %s", g_strOverlayPath[client][channel]); +} + +OverlaysChannel:OverlaysClientFindChannel(client) +{ + // x = channel index. + for (new x = 0; x < OVERLAYS_CHANNEL_MAX; x++) + { + // Convert to OverlaysChannel datatype. + new OverlaysChannel:channel = OverlaysChannel:x; + + if (OverlaysClientGetChannelState(client, channel)) + { + // Return channel. + return channel; + } + } + + return OVERLAYS_CHANNEL_NONE; +} + +/** + * Toggle or set new value to a channel state of a client. + * + * @param client The client index. + * @param channel The channel to change state of. + * @param toggle Set to true to toggle state, false to use value param. + * @param value (Optional) New value of the state, only used if toggle is false. + */ +bool:OverlaysClientSetChannelState(client, OverlaysChannel:channel, bool:update = false, bool:toggle = true, bool:value = false, bool:reset = false) +{ + // Toggle or set new state to channel of a client. + g_bOverlayChannel[client][channel] = toggle ? !g_bOverlayChannel[client][channel] : value; + + if (update) + { + // Update client overlay. + OverlaysClientUpdateOverlay(client); + } + + if (reset) + { + OverlaysClientSetChannelPath(client, channel, ""); + } + + // Return new value. + return g_bOverlayChannel[client][channel]; +} + +/** + * Get current value of a channel state of a client. + * + * @param client The client index. + * @param channel The channel to get state of. + */ +bool:OverlaysClientGetChannelState(client, OverlaysChannel:channel) +{ + // Return current value. + return g_bOverlayChannel[client][channel]; +} + +/** + * Set overlay path for a channel. + * + * @param client The client index. + * @param channel The channel to set path on. + * @param path Path to overlay. + */ +OverlaysClientSetChannelPath(client, OverlaysChannel:channel, const String:path[]) +{ + // Copy path to the overlay channel's path string. + strcopy(g_strOverlayPath[client][channel], PLATFORM_MAX_PATH, path); +} + +/** + * Timer callback, updates overlay on each client. + * + * @param timer The timer handle. + */ +public Action:OverlaysTimer(Handle:timer) +{ + // x = client index + for (new x = 1; x <= MaxClients; x++) + { + // If client isn't in game, then stop. + if (!IsClientInGame(x)) + { + continue; + } + + // Update client's overlay. + OverlaysClientUpdateOverlay(x); + } +} \ No newline at end of file diff --git a/src/zr/playerclasses/apply.inc b/src/zr/playerclasses/apply.inc index 3672cea..10386a7 100644 --- a/src/zr/playerclasses/apply.inc +++ b/src/zr/playerclasses/apply.inc @@ -136,21 +136,6 @@ bool:ClassApplyAlpha(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) */ bool:ClassApplyOverlay(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) { - // If dxLevel is 0, then query on client failed, so try again, then stop. - if (!dxLevel[client]) - { - // Query dxlevel cvar. - RoundEndGetClientDXLevel(client); - return false; - } - - // If client doesn't meet minimum requirement, then print unsupported text. - if (dxLevel[client] < GENERAL_DXLEVEL_MIN) - { - ZR_PrintCenterText(client, "DX90 not supported", dxLevel[client], GENERAL_DXLEVEL_MIN); - return false; - } - decl String:overlaypath[PLATFORM_MAX_PATH]; // Get the overlay path from the specified cache. diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc index 944b21d..bc586a8 100644 --- a/src/zr/playerclasses/classevents.inc +++ b/src/zr/playerclasses/classevents.inc @@ -29,6 +29,18 @@ ClassClientInit(client) // Set default class indexes on the player. ClassClientSetDefaultIndexes(client); } + + // Forward event to sub-modules + ClassOverlayClientInit(client); +} + +/** + * Hook commands related to classes here. + */ +ClassOnCommandsHook() +{ + // Forward event to sub-modules. + ClassOverlayOnCommandsHook(); } /** @@ -44,9 +56,13 @@ ClassOnClientDisconnect(client) { // Disable class attributes with timers. ClassHealthRegenStop(client); - ClassOverlayStop(client); } +/** + * Client is spawning into the game. + * + * @param client The client index. + */ ClassOnClientSpawn(client) { // Check if the player is alive. @@ -78,12 +94,12 @@ ClassOnClientSpawn(client) // Mark zombie class as selected. ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = randomzombie; ClassGetName(randomzombie, classname, sizeof(classname), ZR_CLASS_TEAM_ZOMBIES); - ZR_PrintToChat(client, "Auto-assign", classname); + ZR_PrintToChat(client, "Classes random assignment", classname); // Mark human class as selected. ClassSelected[client][ZR_CLASS_TEAM_HUMANS] = randomhuman; ClassGetName(randomhuman, classname, sizeof(classname), ZR_CLASS_TEAM_HUMANS); - ZR_PrintToChat(client, "Auto-assign", classname); + ZR_PrintToChat(client, "Classes random assignment", classname); // Update player cache with the human class data, and apply it. ClassReloadPlayerCache(client, randomhuman); @@ -111,13 +127,18 @@ ClassOnClientSpawn(client) ClassReloadPlayerCache(client, ClassGetActiveIndex(client)); ClassApplyAttributes(client); } + + // Forward event to sub-modules. + ClassOverlayOnClientSpawn(client); } ClassOnClientDeath(client) { // Disable class attributes with timers. ClassHealthRegenStop(client); - ClassOverlayStop(client); + + // Disable overlay. + OverlaysClientSetChannelState(client, OVERLAYS_CHANNEL_CLASSES, true, false, false, true); // Set client's FOV back to normal. ToolsSetClientDefaultFOV(client, 90); @@ -129,11 +150,13 @@ ClassOnClientInfected(client, bool:motherzombie = false) // Disable class attributes with timers. ClassHealthRegenStop(client); - ClassOverlayStop(client); // Update the players cache with zombie attributes. ClassReloadPlayerCache(client, classindex); // Apply the new attributes. ClassApplyAttributes(client, motherzombie); + + // Forward event to sub-modules. + ClassOverlayOnClientInfected(client); } diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index e3bf138..4691cea 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -27,7 +27,7 @@ ClassMenuMain(client) new Handle:menu = CreateMenu(ClassMenuMainHandle); SetGlobalTransTarget(client); - SetMenuTitle(menu, "%t\n", "!zclass title"); + SetMenuTitle(menu, "%t\n", "Classes menu title"); decl String:zombieclass[128]; decl String:humanclass[128]; @@ -55,18 +55,18 @@ ClassMenuMain(client) if (ClassPlayerInAdminMode[client]) { // Notify the player. - Format(inadminmnode, sizeof(inadminmnode), "%t\n", "!zclass admin mode enabled"); + Format(inadminmnode, sizeof(inadminmnode), "%t\n", "Classes admin mode enabled"); AddMenuItem(menu, "", inadminmnode, ITEMDRAW_RAWLINE); } // List zombie class options. ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES], zombieclass, sizeof(zombieclass), ZR_CLASS_CACHE_MODIFIED); - Format(zombieselect, sizeof(zombieselect), "%t\n %s", "!zclass zombie", zombieclass); + Format(zombieselect, sizeof(zombieselect), "%t\n %s", "Classes menu zombie", zombieclass); AddMenuItem(menu, "", zombieselect, zombie_itemdraw); // List human class options. ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_HUMANS], humanclass, sizeof(humanclass), ZR_CLASS_CACHE_MODIFIED); - Format(humanselect, sizeof(humanselect), "%t\n %s", "!zclass human", humanclass); + Format(humanselect, sizeof(humanselect), "%t\n %s", "Classes menu human", humanclass); AddMenuItem(menu, "", humanselect, human_itemdraw); // Only display admin class options for admins, and if admin classes exist. @@ -74,7 +74,7 @@ ClassMenuMain(client) { // List admin class options. ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_ADMINS], adminclass, sizeof(adminclass), ZR_CLASS_CACHE_MODIFIED); - Format(adminselect, sizeof(adminselect), "%t\n %s", "!zclass admin", adminclass); + Format(adminselect, sizeof(adminselect), "%t\n %s", "Classes menu admin", adminclass); AddMenuItem(menu, "", adminselect, admin_itemdraw); // Set admin mode status string. @@ -91,7 +91,7 @@ ClassMenuMain(client) AddMenuItem(menu, "", " ", ITEMDRAW_RAWLINE); // Show admin mode toggle option. - Format(toggleadminmode, sizeof(toggleadminmode), "%t\n %s", "!zclass admin mode toggle", adminmode); + Format(toggleadminmode, sizeof(toggleadminmode), "%t\n %s", "Classes menu admin mode toggle", adminmode); AddMenuItem(menu, "", toggleadminmode, admin_itemdraw); } @@ -174,15 +174,15 @@ ClassMenuSelect(client, teamid) { case ZR_CLASS_TEAM_ZOMBIES: { - Format(title, sizeof(title), "%t\n", "!zclass zombie"); + Format(title, sizeof(title), "%t\n", "Classes menu zombie"); } case ZR_CLASS_TEAM_HUMANS: { - Format(title, sizeof(title), "%t\n", "!zclass human"); + Format(title, sizeof(title), "%t\n", "Classes menu human"); } case ZR_CLASS_TEAM_ADMINS: { - Format(title, sizeof(title), "%t\n", "!zclass admin"); + Format(title, sizeof(title), "%t\n", "Classes menu admin"); } } SetMenuTitle(menu, title); @@ -213,7 +213,8 @@ ClassMenuSelect(client, teamid) { // No classes found. Display message. The main class menu should // prevent this from happening, but we print a message just in case. - Format(menuitem, sizeof(menuitem), "%t\n", "!zclass not found"); + // THIS TRANSLATION PHRASES IS NOT IN FILE. + Format(menuitem, sizeof(menuitem), "%t\n", "Classes menu not found"); AddMenuItem(menu, classname, menuitem, ITEMDRAW_RAWLINE); } diff --git a/src/zr/playerclasses/clientoverlays.inc b/src/zr/playerclasses/clientoverlays.inc index 95dbcfe..64a30c5 100644 --- a/src/zr/playerclasses/clientoverlays.inc +++ b/src/zr/playerclasses/clientoverlays.inc @@ -11,46 +11,100 @@ */ /** - * Timer handles for redisplaying overlays on clients. + * @section Suicide intercept defines. */ -new Handle:tOverlay[MAXPLAYERS + 1]; +#define CLASSOVERLAY_TOGGLE_MAX_CMDS 5 +#define CLASSOVERLAY_TOGGLE_MAX_LENGTH 16 +/** + * @endsection + */ + +/** + * Array to store default class overlay enable flag. + */ +new bool:h_bClassOverlay[MAXPLAYERS + 1]; /** - * Specifies if a client have a overlay. + * Client is joining the server. + * + * @param client The client index. */ -new bool:bClientHasOverlay[MAXPLAYERS + 1]; - -/** - * Tells whether the overlay is on or not. - */ -new bool:bClientOverlayOn[MAXPLAYERS + 1]; - -/** - * Path to the currently active overlay. - */ -new String:ActiveOverlay[MAXPLAYERS + 1][PLATFORM_MAX_PATH]; - - -/** - * Returns if the have a overlay path specified. - * - * @param client The client index. - * @return True if a overlay path is specified, false otherwise. - */ -bool:ClassClientHasOverlay(client) +ClassOverlayClientInit(client) { - return bClientHasOverlay[client]; + // Get overlay toggle cvar values. + new bool:overlaytoggle = GetConVarBool(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLE]); + new bool:overlaydefault = GetConVarBool(g_hCvarsList[CVAR_CLASSES_OVERLAY_DEFAULT]); + + // Apply default value if toggle is enabled, default to true if toggle is disabled. + h_bClassOverlay[client] = overlaytoggle ? overlaydefault : true; } /** - * Returns if the overlay is currently on or not. - * - * @param client The client index. - * @return True if on, false otherwise. + * Hook commands related to overlay here. */ -bool:ClassOverlayIsOn(client) +ClassOverlayOnCommandsHook() { - return bClientOverlayOn[client]; + // Create command callbacks (intercepts) for listed suicide commands. + decl String:togglecmds[CLASSOVERLAY_TOGGLE_MAX_CMDS * CLASSOVERLAY_TOGGLE_MAX_LENGTH]; + GetConVarString(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLECMDS], togglecmds, sizeof(togglecmds)); + + // Create array to store cmds + new String:arrayCmds[CLASSOVERLAY_TOGGLE_MAX_CMDS][CLASSOVERLAY_TOGGLE_MAX_LENGTH]; + + // Explode string into array indexes. + new cmdcount = ExplodeString(togglecmds, ", ", arrayCmds, CLASSOVERLAY_TOGGLE_MAX_CMDS, CLASSOVERLAY_TOGGLE_MAX_LENGTH); + + // x = array index. + // arrayCmds[x] = suicide command. + for (new x = 0; x <= cmdcount - 1; x++) + { + // Prepare intercept for this command. + RegConsoleCmd(arrayCmds[x], ClassOverlayEnableCommand); + } +} + +/** + * Client is spawning into the game. + * + * @param client The client index. + */ +ClassOverlayOnClientSpawn(client) +{ + // If overlay toggle is enabled and class has an overlay, then send center text. + new bool:overlaytoggle = GetConVarBool(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLE]); + + decl String:overlaypath[PLATFORM_MAX_PATH]; + ClassGetOverlayPath(client, overlaypath, sizeof(overlaypath)); + + if (overlaytoggle && overlaypath[0]) + { + decl String:togglecmds[CLASSOVERLAY_TOGGLE_MAX_CMDS * CLASSOVERLAY_TOGGLE_MAX_LENGTH]; + GetConVarString(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLECMDS], togglecmds, sizeof(togglecmds)); + + ZR_HudHint(client, "Classes overlay toggle", togglecmds); + } +} + +/** + * Client has been infected. + * + * @param client The client index. + */ +ClassOverlayOnClientInfected(client) +{ + // If overlay toggle is enabled and class has an overlay, then send center text. + new bool:overlaytoggle = GetConVarBool(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLE]); + + decl String:overlaypath[PLATFORM_MAX_PATH]; + ClassGetOverlayPath(client, overlaypath, sizeof(overlaypath)); + + if (overlaytoggle && overlaypath[0]) + { + decl String:togglecmds[CLASSOVERLAY_TOGGLE_MAX_CMDS * CLASSOVERLAY_TOGGLE_MAX_LENGTH]; + GetConVarString(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLECMDS], togglecmds, sizeof(togglecmds)); + + ZR_PrintCenterText(client, "Classes overlay toggle", togglecmds); + } } ClassOverlayInitialize(client, const String:overlay[]) @@ -60,57 +114,34 @@ ClassOverlayInitialize(client, const String:overlay[]) return; } - if (strlen(overlay) == 0) + // If overlay path is empty, then disable channel, then stop. + if (!overlay[0]) { - bClientHasOverlay[client] = false; - } - else - { - bClientHasOverlay[client] = true; - strcopy(ActiveOverlay[client], PLATFORM_MAX_PATH, overlay); - - ClassOverlayStart(client); + OverlaysClientSetChannelState(client, OVERLAYS_CHANNEL_CLASSES, true, false, false, true); + return; } + + // Display class overlays. + OverlaysClientSetChannelPath(client, OVERLAYS_CHANNEL_CLASSES, overlay); + OverlaysClientSetChannelState(client, OVERLAYS_CHANNEL_CLASSES, true, false, h_bClassOverlay[client]); } -ClassOverlayStart(client) +/** + * Command callback (See zr_classes_overlay_togglecmds) + * Toggles nightvision of a client. + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:ClassOverlayEnableCommand(client, argc) { - // Kill timer if it exist. - if (tOverlay[client] != INVALID_HANDLE) + // If overlay toggle is disabled, then stop. + new bool:overlaytoggle = GetConVarBool(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLE]); + if (!overlaytoggle) { - KillTimer(tOverlay[client]); - tOverlay[client] = INVALID_HANDLE; + return; } - ClientCommand(client, "r_screenoverlay \"%s\"", ActiveOverlay[client]); - bClientOverlayOn[client] = true; - - new Float:redisplay = GetConVarFloat(g_hCvarsList[CVAR_OVERLAY_REDISPLAY]); - tOverlay[client] = CreateTimer(redisplay, ClassOverlayTimer, client, TIMER_REPEAT); -} - -ClassOverlayStop(client) -{ - // Kill timer if it exist. - if (tOverlay[client] != INVALID_HANDLE) - { - KillTimer(tOverlay[client]); - tOverlay[client] = INVALID_HANDLE; - } - - // Disable client overlay. - ClientCommand(client, "r_screenoverlay \"\""); - bClientOverlayOn[client] = false; -} - -public Action:ClassOverlayTimer(Handle:timer, any:client) -{ - if (!IsClientInGame(client) || !InfectIsClientInfected(client)) - { - tOverlay[client] = INVALID_HANDLE; - return Plugin_Stop; - } - - ClientCommand(client, "r_screenoverlay \"%s\"", ActiveOverlay[client]); - return Plugin_Continue; + // Toggle current overlay channel, and retrieve new value. + h_bClassOverlay[client] = OverlaysClientSetChannelState(client, OVERLAYS_CHANNEL_CLASSES, true, true); } diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 0b714ce..182f008 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -476,6 +476,8 @@ ClassLoad() } } + + /** * Updates the class data cache. Original values are retrieved from ClassData. * diff --git a/src/zr/roundend.inc b/src/zr/roundend.inc index 0f512a4..bb828e7 100644 --- a/src/zr/roundend.inc +++ b/src/zr/roundend.inc @@ -13,22 +13,22 @@ /** * @section All round end reasons. */ -#define ROUNDEND_TARGET_BOMBED 1 // Target Successfully Bombed! +#define ROUNDEND_TARGET_BOMBED 1 // Target Successfully Bombed! #define ROUNDEND_VIP_ESCAPED 2 // The VIP has escaped! -#define ROUNDEND_VIP_ASSASSINATED 3 // VIP has been assassinated! -#define ROUNDEND_TERRORISTS_ESCAPED 4 // The terrorists have escaped! -#define ROUNDEND_CTS_PREVENTESCAPE 5 // The CT's have prevented most of the terrorists from escaping! +#define ROUNDEND_VIP_ASSASSINATED 3 // VIP has been assassinated! +#define ROUNDEND_TERRORISTS_ESCAPED 4 // The terrorists have escaped! +#define ROUNDEND_CTS_PREVENTESCAPE 5 // The CT's have prevented most of the terrorists from escaping! #define ROUNDEND_ESCAPING_TERRORISTS_NEUTRALIZED 6 // Escaping terrorists have all been neutralized! -#define ROUNDEND_BOMB_DEFUSED 7 // The bomb has been defused! +#define ROUNDEND_BOMB_DEFUSED 7 // The bomb has been defused! #define ROUNDEND_CTS_WIN 8 // Counter-Terrorists Win! -#define ROUNDEND_TERRORISTS_WIN 9 // Terrorists Win! -#define ROUNDEND_ROUND_DRAW 10 // Round Draw! -#define ROUNDEND_ALL_HOSTAGES_RESCUED 11 // All Hostages have been rescued! -#define ROUNDEND_TARGET_SAVED 12 // Target has been saved! -#define ROUNDEND_HOSTAGES_NOT_RESCUED 13 // Hostages have not been rescued! -#define ROUNDEND_TERRORISTS_NOT_ESCAPED 14 // Terrorists have not escaped! -#define ROUNDEND_VIP_NOT_ESCAPED 15 // VIP has not escaped! -#define ROUNDEND_GAME_COMMENCING 16 // Game Commencing! +#define ROUNDEND_TERRORISTS_WIN 9 // Terrorists Win! +#define ROUNDEND_ROUND_DRAW 10 // Round Draw! +#define ROUNDEND_ALL_HOSTAGES_RESCUED 11 // All Hostages have been rescued! +#define ROUNDEND_TARGET_SAVED 12 // Target has been saved! +#define ROUNDEND_HOSTAGES_NOT_RESCUED 13 // Hostages have not been rescued! +#define ROUNDEND_TERRORISTS_NOT_ESCAPED 14 // Terrorists have not escaped! +#define ROUNDEND_VIP_NOT_ESCAPED 15 // VIP has not escaped! +#define ROUNDEND_GAME_COMMENCING 16 // Game Commencing! /** * @endsection */ @@ -54,11 +54,6 @@ enum RoundEndOutcome */ new Handle:tRoundEnd = INVALID_HANDLE; -/** - * Global variable to store a convar query cookie - */ -new QueryCookie:mat_dxlevel; - /** * Map is starting. */ @@ -68,17 +63,6 @@ RoundEndOnMapStart() tRoundEnd = INVALID_HANDLE; } -/** - * Client is joining the server. - * - * @param client The client index. - */ -RoundEndClientInit(client) -{ - // Get client's DX level. - RoundEndGetClientDXLevel(client); -} - /** * Client has been killed. */ @@ -167,53 +151,6 @@ RoundEndOnRoundEnd(reason) RoundEndBalanceTeams(); } -/** - * Finds DX level of a client. - * - * @param client The client index. - */ -RoundEndGetClientDXLevel(client) -{ - // If client is fake (or bot), then stop. - if (IsFakeClient(client)) - { - return; - } - - // Query mat_dxlevel on client. - mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", RoundEndQueryClientDXLevel); -} - -/** - * Query callback function. - * - * @param cookie Unique cookie of the query. - * @param client The client index. - * @param result The result of the query (see console.inc enum ConVarQueryResult) - * @param cvarName Name of the cvar. - * @param cvarValue Value of the cvar. - */ -public RoundEndQueryClientDXLevel(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) -{ - // If query cookie does not match cookie given by mat_dxlevel query, then stop, this isn't our query. - if (cookie != mat_dxlevel) - { - return; - } - - // Reset dxLevel. - dxLevel[client] = 0; - - // If result is any other than ConVarQuery_Okay, then stop. - if (result != ConVarQuery_Okay) - { - return; - } - - // Copy cvar value to dxLevel array. - dxLevel[client] = StringToInt(cvarValue); -} - /** * Convert a round_end reason, to a round winner, or draw. * @@ -397,34 +334,6 @@ RoundEndBalanceTeams() CloseHandle(arrayEligibleClients); } -/** - * Displays overlay to client, or prints unsupported message on client's screen. - * - * @param client The client index. - * @param overlay The overlay path. - */ -RoundEndDisplayClientOverlay(client, const String:overlay[]) -{ - // If dxLevel is 0, then query on client failed, so try again, then stop. - if (!dxLevel[client]) - { - // Query dxlevel cvar. - RoundEndGetClientDXLevel(client); - return; - } - - // If dxLevel is above or equal to minimum requirement, then display overlay. - if (dxLevel[client] >= GENERAL_DXLEVEL_MIN) - { - ClientCommand(client, "r_screenoverlay \"%s\"", overlay); - } - // If client doesn't meet minimum requirement, then print unsupported text. - else - { - ZR_PrintCenterText(client, "DX90 not supported", dxLevel[client], GENERAL_DXLEVEL_MIN); - } -} - /** * Displays overlays to clients, depending on the outcome. * @@ -470,7 +379,14 @@ RoundEndOverlayStart(Float:time, RoundEndOutcome:outcome) continue; } - RoundEndDisplayClientOverlay(x, overlaypath); + // If client is fake (or bot), then stop. + if (IsFakeClient(x)) + { + continue; + } + + OverlaysClientSetChannelPath(x, OVERLAYS_CHANNEL_ROUNDEND, overlaypath); + OverlaysClientSetChannelState(x, OVERLAYS_CHANNEL_ROUNDEND, true, false, true); } CreateTimer(time, RoundEndOverlayTimer, _, TIMER_FLAG_NO_MAPCHANGE); @@ -487,8 +403,14 @@ RoundEndOverlayStop() continue; } - // Removes overlay from client's screen. - ClientCommand(x, "r_screenoverlay \"\""); + // If client is fake (or bot), then stop. + if (IsFakeClient(x)) + { + continue; + } + + // Disable roundend overlay channel. + OverlaysClientSetChannelState(x, OVERLAYS_CHANNEL_ROUNDEND, true, false, false, true); } } diff --git a/src/zr/translation.inc b/src/zr/translation.inc index a457e90..6d4531b 100644 --- a/src/zr/translation.inc +++ b/src/zr/translation.inc @@ -12,7 +12,7 @@ FormatTextString(String:text[], maxlen) { - Format(text, maxlen, "@green[%t] @default%s", "ZR", text); + Format(text, maxlen, "@green[ZR] @default%s", text); ReplaceString(text, maxlen, "@default","\x01"); ReplaceString(text, maxlen, "@lgreen","\x03"); @@ -92,7 +92,7 @@ stock ZR_PrintToServer(any:...) decl String:buffer[192]; VFormat(phrase, sizeof(phrase), "%t", 1); - Format(buffer, sizeof(buffer), "[%t] %s", "ZR", phrase); + Format(buffer, sizeof(buffer), "[ZR] %s", phrase); PrintToServer(buffer); } diff --git a/src/zr/weapons/restrict.inc b/src/zr/weapons/restrict.inc index 96949d9..6fe7deb 100644 --- a/src/zr/weapons/restrict.inc +++ b/src/zr/weapons/restrict.inc @@ -24,7 +24,7 @@ new Handle:gRestrictedWeapons = INVALID_HANDLE; /** * Array that stores the "HookID" to be later unhooked on player disconnect. */ -new gCanUseHookID[MAXPLAYERS + 1]; +new g_iCanUseHookID[MAXPLAYERS + 1] = {-1, ...}; /** * Query results returned when (un)restricting a weapon. @@ -52,6 +52,16 @@ RestrictInit() RegConsoleCmd("rebuy", RestrictBuyCommand); } +/** + * Hook commands related to restrict here. + */ +RestrictOnCommandsCreate() +{ + // Create admin commands. + RegAdminCmd("zr_restrict", RestrictRestrictCommand, ADMFLAG_GENERIC, "zr_restrict - Restrict a weapon."); + RegAdminCmd("zr_unrestrict", RestrictUnrestrictCommand, ADMFLAG_GENERIC, "zr_unrestrict - Unrestrict a weapon."); +} + /** * Clears weapon restrict data. */ @@ -209,7 +219,7 @@ RestrictWeaponUnrestrictAll() RestrictClientInit(client) { // Hook "Weapon_CanUse" on client. - gCanUseHookID[client] = ZRTools_HookWeapon_CanUse(client, RestrictCanUse); + g_iCanUseHookID[client] = ZRTools_HookWeapon_CanUse(client, RestrictCanUse); } /** @@ -219,8 +229,13 @@ RestrictClientInit(client) */ RestrictOnClientDisconnect(client) { - // Unhook "Weapon_CanUse" on client. - ZRTools_UnhookWeapon_CanUse(gCanUseHookID[client]); + // Unhook "Weapon_CanUse" callback, and reset variable. + + if (g_iCanUseHookID[client] != -1) + { + ZRTools_UnhookWeapon_CanUse(g_iCanUseHookID[client]); + g_iCanUseHookID[client] = -1; + } } /** @@ -231,8 +246,8 @@ RestrictOnClientDisconnect(client) RestrictOnClientSpawn(client) { // Re-hook "canuse" on client. - ZRTools_UnhookWeapon_CanUse(gCanUseHookID[client]); - gCanUseHookID[client] = ZRTools_HookWeapon_CanUse(client, RestrictCanUse); + ZRTools_UnhookWeapon_CanUse(g_iCanUseHookID[client]); + g_iCanUseHookID[client] = ZRTools_HookWeapon_CanUse(client, RestrictCanUse); } /** @@ -902,4 +917,88 @@ public ZRTools_Action:RestrictCanUse(client, weapon) // Allow pickup. return ZRTools_Continue; +} + +/** + * Command callback (zr_restrict) + * Restricts a weapon or group + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:RestrictRestrictCommand(client, argc) +{ + // If weapons module is disabled, then stop. + new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]); + if (!weapons) + { + // Tell client command is disabled. + ZR_ReplyToCommand(client, "Feature is disabled"); + return Plugin_Handled; + } + + // If restrict module is disabled, then stop. + new bool:restrict = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_RESTRICT]); + if (!restrict) + { + // Tell client command is disabled. + ZR_ReplyToCommand(client, "Feature is disabled"); + return Plugin_Handled; + } + + // arg1 = weapon being restricted + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + // Strip "weapon_" from entity name + ReplaceString(arg1, sizeof(arg1), "weapon_", ""); + + decl String:display[WEAPONS_MAX_LENGTH]; + + new WpnRestrictQuery:output = RestrictRestrict(arg1, display); + RestrictPrintRestrictOutput(client, output, display, true); + + return Plugin_Handled; +} + +/** + * Command callback (zr_unrestrict) + * Unrestricts a weapon or group + * + * @param client The client index. + * @param argc Argument count. + */ +public Action:RestrictUnrestrictCommand(client, argc) +{ + // If weapons module is disabled, then stop. + new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]); + if (!weapons) + { + // Tell client command is disabled. + ZR_ReplyToCommand(client, "Feature is disabled"); + return Plugin_Handled; + } + + // If restrict module is disabled, then stop. + new bool:restrict = GetConVarBool(g_hCvarsList[CVAR_WEAPONS_RESTRICT]); + if (!restrict) + { + // Tell client command is disabled. + ZR_ReplyToCommand(client, "Feature is disabled"); + return Plugin_Handled; + } + + // arg1 = weapon being restricted + decl String:arg1[32]; + GetCmdArg(1, arg1, sizeof(arg1)); + + // Strip "weapon_" from entity name + ReplaceString(arg1, sizeof(arg1), "weapon_", ""); + + decl String:display[WEAPONS_MAX_LENGTH]; + + new WpnRestrictQuery:output = RestrictUnrestrict(arg1, display); + RestrictPrintUnrestrictOutput(client, output, display, true); + + return Plugin_Handled; } \ No newline at end of file diff --git a/src/zr/weapons/weapons.inc b/src/zr/weapons/weapons.inc index d0cdd6e..3aad2c6 100644 --- a/src/zr/weapons/weapons.inc +++ b/src/zr/weapons/weapons.inc @@ -129,6 +129,12 @@ WeaponsValidateConfig() } } +WeaponsOnCommandsCreate() +{ + // Forward event to sub-modules. + RestrictOnCommandsCreate(); +} + /** * Client is joining the server. * diff --git a/src/zr/zhp.inc b/src/zr/zhp.inc index 46001ab..ebffd8c 100644 --- a/src/zr/zhp.inc +++ b/src/zr/zhp.inc @@ -72,7 +72,7 @@ ZHPOnClientDeath(client) } /** - * Player has been infected. + * Client has been infected. * * @param client The client index. */ diff --git a/src/zr/zombie.inc b/src/zr/zombie.inc index d6ad7de..dba9d8b 100644 --- a/src/zr/zombie.inc +++ b/src/zr/zombie.inc @@ -1,42 +1,3 @@ -/** - * ==================== - * Zombie:Reloaded - * File: zombie.inc - * Author: Greyscale - * ==================== - */ - -HookCommands() -{ - RegConsoleCmd("nightvision", Command_NightVision); -} - -public Action:Command_NightVision(client, argc) -{ - new bool:allow_disable = GetConVarBool(g_hCvarsList[CVAR_ZVISION_ALLOW_DISABLE]); - if (!allow_disable) - { - return; - } - - bClientOverlayOn[client] = !bClientOverlayOn[client]; - - decl String:overlay[PLATFORM_MAX_PATH]; - ClassGetOverlayPath(client, overlay, sizeof(overlay)); - - if (strlen(overlay) > 0) - { - if (bClientOverlayOn[client]) - { - ClassOverlayInitialize(client, overlay); - } - else - { - ClassOverlayStop(client); - } - } -} - RemoveObjectives() { decl String:classname[64]; diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index f4dca48..18aacb0 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -10,11 +10,6 @@ * ============================================================================ */ -/** - * Minimum dx level required to see overlays. - */ -#define GENERAL_DXLEVEL_MIN 90 - /** * @section Conversion factors. */ @@ -24,11 +19,6 @@ * @endsection */ -/** - * The DirectX level of a client. - */ -new dxLevel[MAXPLAYERS + 1]; - /** * Global variable set to true when the first zombie(s) is/are spawned. */