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. */