Added basic class API: ZR_IsValidClassIndex, ZR_GetActiveClass, ZR_SelectClientClass, ZR_GetClassByName, ZR_GetClassDisplayName
This commit is contained in:
		| @@ -33,3 +33,4 @@ | ||||
|  | ||||
| #include <zr/infect.zr> | ||||
| #include <zr/respawn.zr> | ||||
| #include <zr/class.zr> | ||||
|   | ||||
							
								
								
									
										109
									
								
								src/include/zr/class.zr.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/include/zr/class.zr.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * ============================================================================ | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @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); | ||||
							
								
								
									
										177
									
								
								src/testsuite/zr/classapitest.sp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								src/testsuite/zr/classapitest.sp
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * ============================================================================ | ||||
|  */ | ||||
|  | ||||
| #pragma semicolon 1 | ||||
| #include <sourcemod> | ||||
| #include <zombiereloaded> | ||||
|  | ||||
| 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 <class index>"); | ||||
|     RegConsoleCmd("zrtest_get_active_class", GetActiveClassCommand, "Gets the current class the specified player is using. Usage: zrtest_get_active_class <target>"); | ||||
|     RegConsoleCmd("zrtest_select_class", SelectClassCommand, "Selects a class for a player. Usage: zrtest_select_class <target> <class index>"); | ||||
|     RegConsoleCmd("zrtest_get_class_by_name", GetClassCommand, "Gets class index by class name. Usage: zrtest_get_class_by_name <class name>"); | ||||
|     RegConsoleCmd("zrtest_get_class_display_name", GetNameCommand, "Gets class display name. Usage: zrtest_get_class_display_name <class index>"); | ||||
| } | ||||
|  | ||||
| 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 <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 <target>"); | ||||
|         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 <target> <class index> [<apply if possible> <save if enabled>]"); | ||||
|         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 <class 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 <class index>"); | ||||
|         return Plugin_Handled; | ||||
|     } | ||||
|      | ||||
|     ZR_GetClassDisplayName(classIndex, displayName, sizeof(displayName)); | ||||
|     ReplyToCommand(client, "Display name of class %d: \"%s\"", classIndex, displayName); | ||||
|      | ||||
|     return Plugin_Handled; | ||||
| } | ||||
| @@ -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. | ||||
|   | ||||
							
								
								
									
										167
									
								
								src/zr/api/class.api.inc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								src/zr/api/class.api.inc
									
									
									
									
									
										Normal file
									
								
							| @@ -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 <http://www.gnu.org/licenses/>. | ||||
|  * | ||||
|  * ============================================================================ | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * 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; | ||||
| } | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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: | ||||
|         { | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
| @@ -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. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user