From 8bec3be02dfa788e2229deed7bb997b6f076afda Mon Sep 17 00:00:00 2001 From: Richard Helgeby Date: Sat, 8 Sep 2012 22:34:31 +0200 Subject: [PATCH] Added basic class API: ZR_IsValidClassIndex, ZR_GetActiveClass, ZR_SelectClientClass, ZR_GetClassByName, ZR_GetClassDisplayName --- src/include/zombiereloaded.inc | 1 + src/include/zr/class.zr.inc | 109 +++++++++++++++ src/testsuite/zr/classapitest.sp | 177 +++++++++++++++++++++++++ src/zr/api/api.inc | 4 + src/zr/api/class.api.inc | 167 +++++++++++++++++++++++ src/zr/playerclasses/attributes.inc | 2 +- src/zr/playerclasses/classmenus.inc | 67 +--------- src/zr/playerclasses/filtertools.inc | 12 +- src/zr/playerclasses/playerclasses.inc | 90 +++++++++++++ src/zr/zombiereloaded.inc | 1 + 10 files changed, 562 insertions(+), 68 deletions(-) create mode 100644 src/include/zr/class.zr.inc create mode 100644 src/testsuite/zr/classapitest.sp create mode 100644 src/zr/api/class.api.inc diff --git a/src/include/zombiereloaded.inc b/src/include/zombiereloaded.inc index afbd748..7797a44 100644 --- a/src/include/zombiereloaded.inc +++ b/src/include/zombiereloaded.inc @@ -33,3 +33,4 @@ #include #include +#include diff --git a/src/include/zr/class.zr.inc b/src/include/zr/class.zr.inc new file mode 100644 index 0000000..3b16fb4 --- /dev/null +++ b/src/include/zr/class.zr.inc @@ -0,0 +1,109 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: class.zr.inc + * Type: Include + * Description: Player class API. + * + * Copyright (C) 2009-2012 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ============================================================================ + */ + +/** + * @section Internal class cache types. Specifies which class data to access. + */ +#define ZR_CLASS_CACHE_ORIGINAL 0 /** Original class data loaded from file. */ +#define ZR_CLASS_CACHE_MODIFIED 1 /** Default cache. Class data modified by eventual multipliers, map configs, commands, etc. */ +#define ZR_CLASS_CACHE_PLAYER 2 /** Current player class attributes. The class index parameter is used as client index when reading from this cache. */ +/** + * @endsection + */ + +/** + * Results when selecting a class for a player. + */ +enum ClassSelectResult +{ + ClassSelected_NoChange, /** No class change was necessary (class already selected). */ + ClassSelected_Instant, /** Class was instantly changed. */ + ClassSelected_NextSpawn /** Class will be used next spawn. */ +} + +/** + * Returns whether a class index is valid or not. + * + * @param classIndex Class index to validate. + * + * @return True if valid, false otherwise. + */ +native bool:ZR_IsValidClassIndex(classIndex); + +/** + * Gets the currently active class index that the player is using. + * + * @param client The client index. + * + * @return The active class index. + */ +native bool:ZR_GetActiveClass(client); + +/** + * Selects a class for a player. + * + * Human class attribute may be instantly applied if player is alive, human and + * instant class change is enabled. Otherwise only the selected index will be + * updated for next spawn. + * + * Class selection will be saved in client cookies if enabled. + * + * @param client Client index. + * @param classIndex Class index. + * @param applyIfPossible Optional. Apply class attributes if conditions allow + * it. Default is true. + * @param saveIfEnabled Optional. Save class selection in client cookies if + * enabled. Default is true. + * + * @return Class selection result. See enum ClassSelectResult. + */ +native ClassSelectResult:ZR_SelectClientClass(client, classIndex, bool:applyIfPossible = true, bool:saveIfEnabled = true); + +/** + * Gets the class index of the class with the specified name. + * + * Note: This search is linear and probably won't perform well in large loops. + * + * @param className Class name to search for. + * @param cacheType Optional. Specifies which class cache to read from, + * except player cache. + * + * @return Class index, or -1 if none found. + */ +native ZR_GetClassByName(const String:className[], cacheType = ZR_CLASS_CACHE_MODIFIED); + +/** + * Gets the class name displayed in the class menu. + * + * @param index Index of the class in a class cache or a client index, + * depending on the cache type specified. + * @param buffer The destination string buffer. + * @param maxlen The length of the destination string buffer. + * @param cacheType Optional. Specifies which class cache to read from. + * @return Number of cells written. -1 on error. + */ +native ZR_GetClassDisplayName(index, String:buffer[], maxlen, cacheType = ZR_CLASS_CACHE_MODIFIED); diff --git a/src/testsuite/zr/classapitest.sp b/src/testsuite/zr/classapitest.sp new file mode 100644 index 0000000..0183ec9 --- /dev/null +++ b/src/testsuite/zr/classapitest.sp @@ -0,0 +1,177 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: classapitest.sp + * Type: Test plugin + * Description: Tests the class API. + * + * Copyright (C) 2009-2012 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ============================================================================ + */ + +#pragma semicolon 1 +#include +#include + +public Plugin:myinfo = +{ + name = "Zombie:Reloaded Class API Test", + author = "Greyscale | Richard Helgeby", + description = "Tests the class API for ZR", + version = "1.0.0", + url = "http://code.google.com/p/zombiereloaded/" +}; + +public OnPluginStart() +{ + LoadTranslations("common.phrases"); + + RegConsoleCmd("zrtest_is_valid_class_index", IsValidClassCommand, "Returns whether the specified class index is valid or not. Usage: zrtest_is_valid_class_index "); + RegConsoleCmd("zrtest_get_active_class", GetActiveClassCommand, "Gets the current class the specified player is using. Usage: zrtest_get_active_class "); + RegConsoleCmd("zrtest_select_class", SelectClassCommand, "Selects a class for a player. Usage: zrtest_select_class "); + RegConsoleCmd("zrtest_get_class_by_name", GetClassCommand, "Gets class index by class name. Usage: zrtest_get_class_by_name "); + RegConsoleCmd("zrtest_get_class_display_name", GetNameCommand, "Gets class display name. Usage: zrtest_get_class_display_name "); +} + +public Action:IsValidClassCommand(client, argc) +{ + new classIndex = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + classIndex = StringToInt(valueString); + } + else + { + ReplyToCommand(client, "Returns whether the specified class index is valid or not. Usage: zrtest_is_valid_class_index "); + return Plugin_Handled; + } + + ReplyToCommand(client, "Class %d is valid: %d", classIndex, ZR_IsValidClassIndex(classIndex)); + + return Plugin_Handled; +} + +public Action:GetActiveClassCommand(client, argc) +{ + new target = -1; + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + } + else + { + ReplyToCommand(client, "Gets the current class the specified player is using. Usage: zrtest_get_active_class "); + return Plugin_Handled; + } + + ReplyToCommand(client, "Active class of client %d: %d", target, ZR_GetActiveClass(target)); + + return Plugin_Handled; +} + +public Action:SelectClassCommand(client, argc) +{ + new target = -1; + new classIndex = -1; + new bool:applyIfPossible = true; + new bool:saveIfEnabled = true; + + new String:valueString[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + target = FindTarget(client, valueString); + + GetCmdArg(2, valueString, sizeof(valueString)); + classIndex = StringToInt(valueString); + + if (argc >= 4) + { + GetCmdArg(3, valueString, sizeof(valueString)); + applyIfPossible = bool:StringToInt(valueString); + + GetCmdArg(4, valueString, sizeof(valueString)); + saveIfEnabled = bool:StringToInt(valueString); + } + } + else + { + ReplyToCommand(client, "Selects a class for a player. Usage: zrtest_select_class [ ]"); + return Plugin_Handled; + } + + ReplyToCommand(client, "Selected class %d for client %d. Result: %d", classIndex, target, ZR_SelectClientClass(target, classIndex, applyIfPossible, saveIfEnabled)); + + return Plugin_Handled; +} + +public Action:GetClassCommand(client, argc) +{ + new String:className[64]; + + if (argc >= 1) + { + GetCmdArg(1, className, sizeof(className)); + } + else + { + ReplyToCommand(client, "Gets class index by class name. Usage: zrtest_get_class_by_name "); + return Plugin_Handled; + } + + ReplyToCommand(client, "Class index of \"%s\": %d", className, ZR_GetClassByName(className)); + + return Plugin_Handled; +} + +public Action:GetNameCommand(client, argc) +{ + new classIndex = -1; + new String:valueString[64]; + new String:displayName[64]; + + if (argc >= 1) + { + GetCmdArg(1, valueString, sizeof(valueString)); + classIndex = StringToInt(valueString); + + if (!ZR_IsValidClassIndex(classIndex)) + { + ReplyToCommand(client, "Invalid class index: %d", classIndex); + return Plugin_Handled; + } + } + else + { + ReplyToCommand(client, "Gets class display name. Usage: zrtest_get_class_display_name "); + return Plugin_Handled; + } + + ZR_GetClassDisplayName(classIndex, displayName, sizeof(displayName)); + ReplyToCommand(client, "Display name of class %d: \"%s\"", classIndex, displayName); + + return Plugin_Handled; +} diff --git a/src/zr/api/api.inc b/src/zr/api/api.inc index 4bb4cea..a2cf6f5 100644 --- a/src/zr/api/api.inc +++ b/src/zr/api/api.inc @@ -43,6 +43,7 @@ #include "zr/api/infect.api" #include "zr/api/respawn.api" +#include "zr/api/class.api" /** * Initializes all main natives and forwards. @@ -52,6 +53,7 @@ APIInit() // Forward event to sub-modules. APIInfectInit(); APIRespawnInit(); + APIClassInit(); } /** @@ -68,12 +70,14 @@ stock APIValidateClientIndex(client, EligibleCondition:alive = Condition_Either) if (client < 1 || client > MaxClients) { ThrowNativeError(SP_ERROR_NATIVE, "Invalid client index. (%d)", client); + return; } // Verify that the client is connected. if (!IsClientConnected(client)) { ThrowNativeError(SP_ERROR_NATIVE, "Client %d is not connected.", client); + return; } // Check if the player must be dead or alive. diff --git a/src/zr/api/class.api.inc b/src/zr/api/class.api.inc new file mode 100644 index 0000000..6167dde --- /dev/null +++ b/src/zr/api/class.api.inc @@ -0,0 +1,167 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: class.api.inc + * Type: Core + * Description: Native handlers for the ZR API. (Class module) + * + * Copyright (C) 2009-2012 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ============================================================================ + */ + +/** + * Initializes all natives and forwards related to infection. + */ +APIClassInit() +{ + // Class module natives/forwards (class.zr.inc) + + // Natives + CreateNative("ZR_IsValidClassIndex", APIIsValidClassIndex); + CreateNative("ZR_GetActiveClass", APIGetActiveClass); + CreateNative("ZR_SelectClientClass", APISelectClientClass); + CreateNative("ZR_GetClassByName", APIGetClassByName); + CreateNative("ZR_GetClassDisplayName", APIGetClassDisplayName); +} + +/** + * Native call function (ZR_IsValidClassIndex) + * + * bool:ZR_IsValidClassIndex(classIndex); + */ +public APIIsValidClassIndex(Handle:plugin, numParams) +{ + new classIndex = GetNativeCell(1); + + return ClassValidateIndex(classIndex); +} + +/** + * Native call function (ZR_GetActiveClass) + * + * native bool:ZR_GetActiveClass(client); + */ +public APIGetActiveClass(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + + // Validate the client index. Player must be alive. + APIValidateClientIndex(client, Condition_True); + + return ClassGetActiveIndex(client); +} + +/** + * Native call function (ZR_SelectClientClass) + * + * native ClassSelectResult:ZR_SelectClientClass(client, classIndex, bool:applyIfPossible = true, bool:saveIfEnabled = true) + */ +public APISelectClientClass(Handle:plugin, numParams) +{ + new client = GetNativeCell(1); + new classIndex = GetNativeCell(2); + new bool:applyIfPossible = bool:GetNativeCell(3); + new bool:saveIfEnabled = bool:GetNativeCell(4); + + // Validate the client index. + APIValidateClientIndex(client, Condition_Either); + + // Validate class index. + if (!ClassValidateIndex(classIndex)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Invalid class index. (%d)", classIndex); + return -1; + } + + return _:ClassSelectClientClass(client, classIndex, applyIfPossible, saveIfEnabled); +} + +/** + * Native call function (ZR_GetClassByName) + * + * native ZR_GetClassByName(const String:className[], cacheType = ZR_CLASS_CACHE_MODIFIED); + */ +public APIGetClassByName(Handle:plugin, numParams) +{ + decl String:className[64]; + className[0] = 0; + + // Get class name. + if (GetNativeString(1, className, sizeof(className)) != SP_ERROR_NONE) + { + ThrowNativeError(SP_ERROR_NATIVE, "Unexpected error when reading className parameter. Possibly corrupt or missing data."); + return -1; + } + + new cacheType = GetNativeCell(2); + if (cacheType == ZR_CLASS_CACHE_PLAYER) + { + ThrowNativeError(SP_ERROR_NATIVE, "Invalid cache type. Player cache is not allowed in this function."); + return -1; + } + + return ClassGetIndex(className, cacheType); +} + +/** + * Native call function (ZR_GetClassDisplayName) + * + * native ZR_GetClassDisplayName(classIndex, String:buffer[], maxlen, cacheType = ZR_CLASS_CACHE_MODIFIED); + */ +public APIGetClassDisplayName(Handle:plugin, numParams) +{ + new index = GetNativeCell(1); + new maxlen = GetNativeCell(3); + new cacheType = GetNativeCell(4); + + if (maxlen <= 0) + { + // No buffer size. + return 0; + } + + // Validate index. + if (cacheType == ZR_CLASS_CACHE_PLAYER) + { + // Client index. + APIValidateClientIndex(index, Condition_Either); + } + else + { + // Class index. + if (!ClassValidateIndex(index)) + { + ThrowNativeError(SP_ERROR_NATIVE, "Invalid class index. (%d)", index); + return 0; + } + } + + decl String:displayName[maxlen]; + + new bytes = ClassGetName(index, displayName, maxlen, cacheType); + if (bytes <= 0) + { + // The class doesn't have a name for some reason. Make sure the buffer is empty. + displayName[0] = 0; + } + + SetNativeString(2, displayName, maxlen); + + return bytes; +} diff --git a/src/zr/playerclasses/attributes.inc b/src/zr/playerclasses/attributes.inc index 5fee22f..c16471f 100644 --- a/src/zr/playerclasses/attributes.inc +++ b/src/zr/playerclasses/attributes.inc @@ -235,7 +235,7 @@ stock ClassGetGroup(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_P } /** - * Gets the class name to be displayed in the class menu. + * Gets the class name displayed in the class menu. * * @param index Index of the class in a class cache or a client index, * depending on the cache type specified. diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index bd609b6..53685db 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -340,77 +340,22 @@ ClassMenuSelect(client, teamid) */ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot) { - decl String:classname[MENU_LINE_REG_LENGTH]; - new classindex; - new teamid; + decl String:className[MENU_LINE_REG_LENGTH]; + new classIndex; new bool:autoclose = GetConVarBool(g_hCvarsList[CVAR_CLASSES_MENU_AUTOCLOSE]); - new bool:iszombie = InfectIsClientInfected(client); switch (action) { case MenuAction_Select: { // Get class name from the information string. - GetMenuItem(menu, slot, classname, sizeof(classname)); + GetMenuItem(menu, slot, className, sizeof(className)); // Solve class index from the name. - classindex = ClassGetIndex(classname); + classIndex = ClassGetIndex(className); - // Solve teamid from the class index. - teamid = ClassGetTeamID(classindex, ZR_CLASS_CACHE_MODIFIED); - - // Allow instant class change if enabled and both class and player is human. - if (ClassAllowInstantChange[client] && !iszombie && teamid == ZR_CLASS_TEAM_HUMANS) - { - // Directly change the selected class index. - ClassSelected[client][teamid] = classindex; - - // Update cache and apply attributes. - ClassReloadPlayerCache(client, classindex); - ClassApplyAttributes(client); - } - else - { - // Check if the player is alive. - if (IsPlayerAlive(client)) - { - // Set next spawn index if the player is changing the class on - // his active team. - if ((iszombie && teamid == ZR_CLASS_TEAM_ZOMBIES) || - (!iszombie && teamid == ZR_CLASS_TEAM_HUMANS) || - (ClassPlayerInAdminMode[client] && teamid == ZR_CLASS_TEAM_ADMINS)) - { - // Check if player selected the same class that he already is. - if (ClassSelected[client][teamid] == classindex) - { - // Player is already the specified class. Disable - // next class for the specified team. - ClassSelectedNext[client][teamid] = -1; - } - else - { - // Set class to be used on next spawn. - ClassSelectedNext[client][teamid] = classindex; - } - } - else - { - // Directly change the selected class index. - ClassSelected[client][teamid] = classindex; - } - } - else - { - // Player isn't alive. The class can be directly changed. - ClassSelected[client][teamid] = classindex; - } - } - - // Save selected class index in cookie if enabled. - if (GetConVarBool(g_hCvarsList[CVAR_CLASSES_SAVE])) - { - CookiesSetInt(client, g_hClassCookieClassSelected[teamid], classindex + 1); - } + // Select (and eventually apply) class. + ClassSelectClientClass(client, classIndex); } case MenuAction_Cancel: { diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index f9417e2..6171d93 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -587,12 +587,12 @@ stock ClassValidateEditableAttributes(attributes[ClassEditableAttributes]) /** * Checks if the specified class index is a valid index. * - * @param classindex The class index to validate. + * @param classIndex The class index to validate. * @return True if the class exist, false otherwise. */ -stock bool:ClassValidateIndex(classindex) +stock bool:ClassValidateIndex(classIndex) { - if (classindex >= 0 && classindex < ClassCount) + if (classIndex >= 0 && classIndex < ClassCount) { return true; } @@ -660,10 +660,10 @@ stock ClassGetIndex(const String:name[], cachetype = ZR_CLASS_CACHE_MODIFIED) { decl String:current_name[64]; - // Check if there are no classes. - if (ClassCount == 0) + // Check if there are no classes, or reading from player cache. + if (ClassCount == 0 || cachetype == ZR_CLASS_CACHE_PLAYER) { - return false; + return -1; } // Loop through all classes. diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index c01c520..f3f42bf 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -377,6 +377,16 @@ enum ClassSpeedMethods ClassSpeed_Prop, /** Modifies players' max speed property(m_flMaxspeed). */ } +/** + * Results when selecting a class for a player. + */ +enum ClassSelectResult +{ + ClassSelected_NoChange, /** No class change was necessary (class already selected). */ + ClassSelected_Instant, /** Class was instantly changed. */ + ClassSelected_NextSpawn /** Class will be used next spawn. */ +} + /** * Empty filter structure. */ @@ -1196,6 +1206,86 @@ ClassClientSetDefaultIndexes(client = -1) } } +/** + * Selects a class for a player. + * + * Human class attribute may be instantly applied if player is alive, human and + * instant class change is enabled. Otherwise only the selected index will be + * updated for next spawn. + * + * Class selection will be saved in client cookies if enabled. + * + * @param client Client index. + * @param classIndex Class index. + * @param applyIfPossible Optional. Apply class attributes if conditions allow + * it. Default is true. + * @param saveIfEnabled Optional. Save class selection in client cookies if + * enabled. Default is true. + * + * @return Class selection result. See enum ClassSelectResult. + */ +ClassSelectResult:ClassSelectClientClass(client, classIndex, bool:applyIfPossible = true, bool:saveIfEnabled = true) +{ + new bool:iszombie = InfectIsClientInfected(client); + new teamid = ClassGetTeamID(classIndex, ZR_CLASS_CACHE_MODIFIED); + new ClassSelectResult:selectResult = ClassSelected_NoChange; + + // Allow instant class change if enabled and both class and player is human. + if (applyIfPossible && + ClassAllowInstantChange[client] && + !iszombie && teamid == ZR_CLASS_TEAM_HUMANS) + { + // Update selected class index. + ClassSelected[client][teamid] = classIndex; + + // Update cache and apply attributes. + ClassReloadPlayerCache(client, classIndex); + ClassApplyAttributes(client); + + selectResult = ClassSelected_Instant; + } + else + { + // Set next spawn index if the player is changing the class on + // his active team. + if (IsPlayerAlive(client) && + (iszombie && teamid == ZR_CLASS_TEAM_ZOMBIES) || + (!iszombie && teamid == ZR_CLASS_TEAM_HUMANS) || + (ClassPlayerInAdminMode[client] && teamid == ZR_CLASS_TEAM_ADMINS)) + { + // Check if selecting the same class that the player already is. + if (ClassSelected[client][teamid] == classIndex) + { + // Player is already the specified class. No need to change + // class next spawn. + ClassSelectedNext[client][teamid] = -1; + selectResult = ClassSelected_NoChange; + } + else + { + // Set class to be used on next spawn. + ClassSelectedNext[client][teamid] = classIndex; + selectResult = ClassSelected_NextSpawn; + } + } + else + { + // Directly change the selected class index. + ClassSelected[client][teamid] = classIndex; + selectResult = ClassSelected_NextSpawn; + } + } + + // Save selected class index in cookie if enabled. + // Note: Saved indexes are increased by one. + if (saveIfEnabled && GetConVarBool(g_hCvarsList[CVAR_CLASSES_SAVE])) + { + CookiesSetInt(client, g_hClassCookieClassSelected[teamid], classIndex + 1); + } + + return selectResult; +} + /** * Dump class data into a string. String buffer length should be at about 2048 * cells. diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 1407fc7..c84fd53 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -68,6 +68,7 @@ enum Game * Current game. */ new Game:g_game = Game_Unknown; +#pragma unused g_game /** * Updates g_game. Will log a warning if a unsupported game is detected.