From 50a7e5ab99e69845431b078fe89f1a0871dd1268 Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 4 Aug 2009 03:41:16 +0200 Subject: [PATCH 01/16] Added new parameter parser. Not implemented or tested yet. --- src/zombiereloaded.sp | 1 + src/zr/paramparser.inc | 531 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 532 insertions(+) create mode 100644 src/zr/paramparser.inc diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index 22d9806..b0655a2 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -49,6 +49,7 @@ #include "zr/menu" #include "zr/cookies" #include "zr/paramtools" +#include "zr/paramparser" #include "zr/models" #include "zr/downloads" #include "zr/overlays" diff --git a/src/zr/paramparser.inc b/src/zr/paramparser.inc new file mode 100644 index 0000000..ea3a5cc --- /dev/null +++ b/src/zr/paramparser.inc @@ -0,0 +1,531 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: paramparser.inc + * Type: Core + * Description: Provides functions for parsing single line strings with + * flags, and parameters in key=value format. + * + * Supports quoted strings and escaped characters like "\n" + * and "\t". + * + * Examle raw string: + * "type=interval -disabled msg="Title:\n\"Example\"." + * + * Copyright (C) 2009 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 Limit settings. + */ +#define PARAM_NAME_MAXLEN 64 /** Maximum length of key name or flag name. */ +#define PARAM_VALUE_MAXLEN 256 /** Maximum length of value string. */ +/** + * @endsection + */ + +/** + * @section Parsing error codes. + */ +#define PARAM_ERROR_EMPTY 1 /** Source string is empty. */ +#define PARAM_ERROR_FULL 2 /** Destination array is full. */ +#define PARAM_ERROR_UNEXPECTED_KEY 3 /** Unexpected key name. Could not find a equation sign (=) after previous key name. */ +#define PARAM_ERROR_UNEXPECTED_END 4 /** Unexpected end of source string. */ +#define PARAM_ERROR_MISSING_QUOTE 5 /** Unexpected end of source string. Missing end quote character. */ +#define PARAM_ERROR_UNKNOWN 6 /** Unknown error. The parser got a invalid result from a search function it couldn't handle. */ +/** + * @endsection + */ + +/** + * Modes for what to do and expect when parsing. White space characters between + * modes are ignored. + */ +enum ParamModes +{ + ParamMode_TypeCheck, /** Check if it's a flag or a key. */ + ParamMode_Flag, /** Expect a flag name (starts with "-"). */ + ParamMode_Key, /** Expect a key name. */ + ParamMode_Equal, /** Expect a equation sign. */ + ParamMode_Value /** Expect a value string. */ +} + +/** + * Structure for storing a key/value pair. + */ +enum ParamParseResult +{ + bool:Param_IsFlag, /** Specifies whether it's a flag or not. */ + String:Param_Name[PARAM_NAME_MAXLEN], /** Key or flag name. */ + String:Param_Value[PARAM_VALUE_MAXLEN] /** Value. Only used if a key. */ +} + + + +/************************************** + * * + * PARAMETER FUNCTIONS * + * * + **************************************/ + +/** + * Parses a parameter string in "key=value" format and store the result in a + * ParamParseResult array. + * + * @param buffer A ParamParseResult array to store results. + * @param maxlen Maximum number of keys that can be stored (first + * dimension of buffer). + * @param paramString The source string to parse. String is trimmed before + * parsing. + * @param err Opional output: Error code if parsing error. + * @param errPos Opional output: Position in paramString where the error + * occoured. + * @return Number of keys parsed. + */ +stock ParamParseString(buffer[][ParamParseResult], maxlen, String:paramString[], &err = 0, &errPos = -1) +{ + /* + * VALIDATION OF INPUT AND BUFFERS + */ + + // Trim raw string. + TrimString(paramString); + + // Check if raw string is empty. + if (strlen(paramString) == 0) + { + err = PARAM_ERROR_EMPTY; + errPos = 0; + return 0; + } + + // Validate specified length of destination buffer. + if (maxlen == 0) + { + err = PARAM_ERROR_FULL; + errPos = 0; + return 0; + } + + + /* + * PARSE LOOP + */ + + // Get raw string length. + new rawlen = sizeof(paramString); + + // Initialize. Expect the start to be a key or a flag. + new ParamModes:mode = ParamMode_TypeCheck; + + // Counter for number of parameters parsed. + new paramcount; + + // Buffers for temp values. + new startpos; + new endpos; + new bool:quoteon; + decl String:value[PARAM_VALUE_MAXLEN]; + + // Loop through all characters in the string. Exclude null terminator. + for (new strpos = 0; strpos < rawlen - 1; strpos++) + { + // Check if there's space left in the destination buffer. + if (paramcount > maxlen) + { + // Exit loop. No more parameters can be parsed. + err = PARAM_ERROR_FULL; + errPos = strpos; + break; + } + + + /* + * MODE CHECK + */ + + // Check mode for deciding what to do. + switch (mode) + { + case ParamMode_TypeCheck: + { + // Find start position of first non white space character. + startpos = ParamFindStartPos(paramString, strpos); + + // Check if it's a flag type. + if (paramString[startpos] == '-') + { + // It's a flag, change mode. + mode = ParamMode_Flag; + + // Update current position. + strpos = startpos; + } + else + { + // Expect a key name. + mode = ParamMode_Key; + + // Update current position. Substract by one to include + // the current character in next mode. + strpos = startpos - 1; + } + } + case ParamMode_Flag: + { + // Find stop position (last non white space character). + endpos = ParamFindEndPos(paramString, strpos); + + // Extract key name. + StrExtract(value, sizeof(value), paramString, strpos, endpos); + + // Copy flag to destination buffer. + strcopy(buffer[paramcount][Param_Name], PARAM_NAME_MAXLEN, value); + + // Set flag type. + buffer[paramcount][Param_IsFlag] = true; + + // Increment parameter counter. + paramcount++; + + // Set next parse mode. + mode = ParamMode_TypeCheck; + } + case ParamMode_Key: + { + // Find stop position. + endpos = ParamFindEndPos(paramString, strpos); + + // Extract key name. + StrExtract(value, sizeof(value), paramString, strpos, endpos); + + // Copy key name to destination buffer. + strcopy(buffer[paramcount][Param_Name], PARAM_NAME_MAXLEN, value); + + // Make sure flag type is not set. + buffer[paramcount][Param_IsFlag] = false; + + // Note: Do not increment parameter counter until the + // entire key/value pair is parsed. + + // Set next parse mode. Expect a equation sign. + mode = ParamMode_Equal; + } + case ParamMode_Equal: + { + // Find start position of first non white space character. + startpos = ParamFindStartPos(paramString, strpos); + + // Validate position. + if (startpos >= 0) + { + // Check if it's a equation sign. + if (paramString[startpos] == '=') + { + // Change mode to expect a value at next position. + mode = ParamMode_Value; + + // Update current position. + strpos = startpos; + } + else + { + // Parse error. + err = PARAM_ERROR_UNEXPECTED_KEY; + errPos = startpos; + break; + } + } + else + { + // Parse error. + err = PARAM_ERROR_UNEXPECTED_END; + errPos = strpos; + break; + } + } + case ParamMode_Value: + { + // Find start position of first non white space character. + startpos = ParamFindStartPos(paramString, strpos); + + // Validate start position. + if (startpos >= 0) + { + // Reset quote and escape settings. + quoteon = false; + + // Loop through all characters starting from the current + // position. Exclude null terminator. + for (strpos = startpos; strpos < rawlen - 1; strpos++) + { + // Check if the current character is a special character. + if (paramString[startpos] == '"') + { + // Toggle quote. + quoteon = !quoteon; + + // Check quote state. + if (quoteon) + { + // Quote started, update start position. + startpos = strpos + 1; + } + else + { + // Quote end, set end position. + endpos = strpos - 1; + } + } + + // Check if it's a white space character or end of the string. + else if (!quoteon && (IsCharSpace(paramString[strpos]) || strpos == rawlen - 1)) + { + // End of value reached. Save positions. + endpos = strpos - 1; + + // Exit loop. + break; + } + } + + // Check if quote still haven't ended. + if (quoteon) + { + // Parse error. + err = PARAM_ERROR_MISSING_QUOTE; + errPos = strpos; + break; + } + + // Extract value string. + StrExtract(value, sizeof(value), paramString, startpos, endpos); + + // Unescape string (converting "\n" to newline, etc.). + StrUnescape(value); + + // Copy value string to destination buffer. + strcopy(buffer[paramcount][Param_Value], PARAM_VALUE_MAXLEN, value); + + // Make sure flag type is not set. + buffer[paramcount][Param_IsFlag] = false; + + // Increment parameter counter. + paramcount++; + + // Set next parse mode. Expect a key or a flag. + mode = ParamMode_TypeCheck; + } + else + { + // Parse error. + err = PARAM_ERROR_UNEXPECTED_END; + errPos = strpos; + break; + } + } + } + } + + // Return number of parameters parsed. + return paramcount; +} + +/** + * Finds the first key index in a parameter array matching the specified key. + * + * @param params A ParamParseResult array to search through. + * @param maxlen Size of parameter array (first dimension). + * @param key Key to find. + * @param caseSensitive Specifies whether the search is case sensitive or + * not (default). + * @return Index of the key if found, -1 otherwise. + */ +stock ParamFindKey(const params[][ParamParseResult], maxlen, const String:key[], bool:caseSensitive = false) +{ + // Loop through all parameters. + for (new index = 0; index < maxlen; index++) + { + // Check parameter type. + if (params[index][Param_IsFlag]) + { + // It's a flag type, skip index. + continue; + } + + // Match key name. + if (StrEqual(params[index][Param_Name], key, caseSensitive)) + { + // Key found, return the key index. + return index; + } + } + + return -1; +} + +/** + * Checks if the specified flag is set in a parameter array. + * + * @param params A ParamParseResult array to search through. + * @param maxlen Size of parameter array (first dimension). + * @param flag Flag to check. + * @param caseSensitive Specifies whether the search is case sensitive or + * not (default). + * @return True flag is found, false otherwise. + */ +stock bool:ParamHasFlag(const params[][ParamParseResult], maxlen, const String:flag[], bool:caseSensitive = false) +{ + // Loop through all parameters. + for (new index = 0; index < maxlen; index++) + { + // Check parameter type. + if (!params[index][Param_IsFlag]) + { + // It's a key type, skip index. + continue; + } + + // Match flag name. + if (StrEqual(params[index][Param_Name], flag, caseSensitive)) + { + // Flag found. + return true; + } + } + + return false; +} + + + +/************************************** + * * + * HELPER FUNCTIONS * + * * + **************************************/ + +/** + * Finds the position of the last non white space character from a specified start position. + * + * @param paramString Raw string search in. + * @param startPos Optional. Position to start searching from. + * @return Position of the last non white space character, or -1 + * if failed. + */ +stock ParamFindEndPos(const String:paramString[], startPos = 0) +{ + new rawlen = sizeof(paramString); + + // Validate string length. + if (rawlen == 0) + { + return -1; + } + + // Loop through all characters from the specified start position. + for (new strpos = startPos; strpos < rawlen; strpos++) + { + // Check if white space or if current position is the last + // character before the null terminator. + if (IsCharSpace(paramString[strpos]) || strpos == rawlen - 1) + { + return strpos - 1; + } + } + + // It should never reach this place. Added to satisfy compiler. + return -1; +} + +/** + * Finds the first non white space character in a string, starting from the + * specified position. + * + * @param paramString Raw string to search in. + * @param startPos Optional. Position to start searching from. + * @return Position of first character or -1 if failed. + */ +stock ParamFindStartPos(const String:paramString[], startPos = 0) +{ + new rawlen = sizeof(paramString); + + // Validate string length. + if (rawlen == 0) + { + return -1; + } + + // Loop through all characters from the specified start position. + for (new strpos = startPos; strpos < rawlen; strpos++) + { + // Check if not white space. + if (!IsCharSpace(paramString[strpos])) + { + return strpos; + } + } + + // No character found. + return -1; +} + +/** + * Extracts a area in a string between two positions. + * + * @param buffer Destination string buffer. + * @param maxlen Size of destination buffer. + * @param source Source string to extract from. + * @param startpos Start position of string to extract. + * @param endpos End position of string to extract. + * @return Number of cells written. + */ +stock StrExtract(String:buffer[], maxlen, const String:source[], startpos, endpos) +{ + new len; + + // Calculate string length. Also add space for null terminator. + len = endpos - startpos + 1; + + // Validate length. + if (len < 0) + { + return 0; + } + + // Extract string and store it in the buffer. + return strcopy(buffer, len, source[startpos]); +} + +/** + * Unescapes a string (replaces "\n" with newlines, etc.). + * + * @param str String to unescape. + */ +stock StrUnescape(String:str[]) +{ + new len = sizeof(str); + + ReplaceString(str, len, "\\n", "\n"); + ReplaceString(str, len, "\\r", "\r"); + ReplaceString(str, len, "\\t", "\t"); + ReplaceString(str, len, "\\\"", "\""); + ReplaceString(str, len, "\\\\", "\\"); +} From 06771e6d1533df8ff3ee1dc83a64206c958c6c04 Mon Sep 17 00:00:00 2001 From: richard Date: Sun, 9 Aug 2009 22:44:28 +0200 Subject: [PATCH 02/16] New feature for blocking class selection. Changes in translations. See details. Finished norwegian translation. Fixed missing quote in english translation file. Added cvars for blocking players from changing classes. Minior typo fixes in log module. Changed TranslationReplyToCommand to use the ReplyToCommand function. --- .../no/zombiereloaded.phrases.txt | 318 +++++++----------- .../translations/zombiereloaded.phrases.txt | 7 +- .../zombiereloaded/zombiereloaded.cfg | 14 +- src/zr/cvars.inc | 8 +- src/zr/log.inc | 2 +- src/zr/menu.inc | 5 +- src/zr/playerclasses/classcommands.inc | 9 +- src/zr/playerclasses/classmenus.inc | 13 +- src/zr/playerclasses/filtertools.inc | 58 ++++ src/zr/translation.inc | 9 +- 10 files changed, 234 insertions(+), 209 deletions(-) diff --git a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt index 4f59fed..208c4a9 100644 --- a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt @@ -338,6 +338,11 @@ "no" "Hoppelengde" } + "Classes Selection Not Allowed" + { + "no" "Endring av klasse er ikke tillatt." + } + // =========================== // Overlays (core) // =========================== @@ -372,49 +377,44 @@ "Infect menu clients title" { - "en" "Zombie Management\nToggle Infection:\n[] = Infected" + "no" "Spillerbehandling\nVeksle mellom zombie og menneske:\n[] = Infisert" } // Commands "Infect command infect syntax" { - "en" "Infect a client. Usage: zr_infect [respawn - 1/0]" + "no" "Infiserer en spiller. Syntaks: zr_infect [teleporter - 1/0]" } "Infect command human syntax" { - "en" "Turn a client into a human. Usage: zr_human [respawn - 1/0] [protect - 1/0]" + "no" "Gjør en spiller om til et menneske. Syntaks: zr_human [teleporter - 1/0] [beskyttelse - 1/0]" } "Infect command infect successful" { - "#format" "{1:s}" - "en" "Player @green{1} @defaulthas been successfully infected." + "no" "@green{1}@default ble vellykket infisert." } "Infect command infect mother successful" { - "#format" "{1:s}" - "en" "Player @green{1} @defaulthas been successfully infected as the mother zombie." + "no" "@green{1}@default ble vellykket infisert som moderzombie." } "Infect command infect unsuccessful" { - "#format" "{1:s}" - "en" "Player @green{1} @defaultis already a zombie." + "no" "@green{1}@default er allerede en zombie." } "Infect command human successful" { - "#format" "{1:s}" - "en" "Player @green{1} @defaulthas been successfully brought back as a human." + "no" "@green{1}@default ble vellykket gjort om til et menneske." } "Infect command human unsuccessful" { - "#format" "{1:s}" - "en" "Player @green{1} @defaultis already a human." + "no" "@green{1}@default er allerede et menneske." } // =========================== @@ -423,7 +423,7 @@ "Damage suicide intercept" { - "en" "Suicide attempt intercepted." + "no" "Selvmordsforsøk hindret." } // =========================== @@ -434,50 +434,42 @@ "Menu main title" { - "#format" "{1:s},{2:s}" - "en" "ZR Commands:\nPrefix command with \"{1}\" or \"{2}\" (quiet) when typing in chat." + "no" "ZR-kommandoer:\nStart kommandoen med \"{1}\" or \"{2}\" (skjules) i samtaleområdet." } "Menu main zadmin" { - "#format" "{1:s}" - "en" "ZAdmin - Open admin menu. (Command: {1})" + "no" "ZAdmin - Åpne administrasjonsmeny. (Kommando: {1})" } "Menu main zclass" { - "#format" "{1:s}" - "en" "ZClass - Configure class settings. (Command: {1})" + "no" "ZClass - Endre klasseinstillinger. (Kommando: {1})" } "Menu main zcookies" { - "#format" "{1:s}" - "en" "ZCookies - Toggle personal ZR settings here. (Command: {1})" + "no" "ZCookies - Endre egendefinerte instillinger. (Kommando: {1})" } "Menu main zspawn" { - "#format" "{1:s}" - "en" "ZSpawn - Join late? Spawn with this. (Command: {1})" + "no" "ZSpawn - Bli med i spillet øyeblikkelig. (Kommando: {1})" } "Menu main ztele" { - "#format" "{1:s}" - "en" "ZTele - Stuck? Teleport back to spawn. (Command: {1})" + "no" "ZTele - Teleporter til startområde. (Kommando: {1})" } "Menu main zhp" { - "#format" "{1:s}" - "en" "ZHP - Shows real HP as zombie. (Command: {1})" + "no" "ZHP - Vis nåværende helsenivå. (Kommando: {1})" } "Menu main zmarket" { - "#format" "{1:s}" - "en" "ZMarket - Customize loadouts here. (Command: {1})" + "no" "ZMarket - Endre egendefinerte våpeninstillinger. (Kommando: {1})" } // =========================== @@ -488,280 +480,252 @@ "Zombie cant use weapon" { - "en" "Zombies can't use weapons!" - "ru" "Зомби не могут использовать оружие!" + "no" "Zombier kan ikke bruke våpen." } // Restrict "Restrict weapon" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @defaulthas been restricted." + "no" "Våpenet @green\"{1}\"@default ble sperret." } "Unrestrict weapon" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @defaulthas been unrestricted." + "no" "Våpenet @green\"{1}\"@default er ikke lenger sperret." } "Restrict weapon stopped" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @defaultis already restricted." + "no" "Våpenet @green\"{1}\"@default er allerede sperret." } "Unrestrict weapon stopped" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @default has no restrictions set." + "no" "Våpenet @green\"{1}\"@default er ikke sperret." } "Restrict weapon type" { - "#format" "{1:s}" - "en" "Weapons of type @green\"{1}\" @defaulthave been restricted." + "no" "Våpentypen @green\"{1}\"@default er sperret." } "Unrestrict weapon type" { - "#format" "{1:s}" - "en" "Weapons of type @green\"{1}\" @defaulthave been unrestricted." + "no" "Våpentypen @green\"{1}\"@default er ikke lenger sperret." } "Restrict weapon type stopped" { - "#format" "{1:s}" - "en" "Weapons of type @green\"{1}\" @defaultare all already restricted." + "no" "Våpentypen @green\"{1}\"@default er allerede sperret." } "Unrestrict weapon type stopped" { - "#format" "{1:s}" - "en" "Weapons of type @green\"{1}\" @defaulthave no restrictions set." + "no" "Våpentypen @green\"{1}\"@default er ikke sperret." } "Restrict weapon untoggleable" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @defaultmay not have its restrictions toggled." + "no" "Våpenet @green\"{1}\"@default kan ikke sperres." } "Weapon invalid" { - "#format" "{1:s}" - "en" "Weapon @green\"{1}\" @defaultis an invalid weapon (type) name." + "no" "Våpenet eller våpentypen @green\"{1}\"@default er ugyldig." } "Weapon is restricted" { - "#format" "{1:s}" - "en" "Weapon @green{1} @defaultis restricted." - "ru" "Оружие @green{1} @default запрещено." + "no" "Våpenet @green{1}@default er sperret." } // ZMarket "Weapons zmarket buyzone" { - "en" "You must be in a buyzone to use ZMarket." + "no" "Du må være i en kjøpesone for å kunne bruke ZMarket." } "Weapons zmarket purchase" { - "#format" "{1:s}" - "en" "You have purchased weapon @green{1}. @defaultSelect item again to buy ammo if you are low." + "no" "Du har kjøpt våpenet @green{1}@default. Velg gjenstanden igjen for å kjøpe mer ammunisjon." } "Weapons zmarket purchase max" { - "#format" "{1:s},{2:d}" - "en" "Weapon @green{1} @defaulthas a purchase limit of @green{2}@default. Wait until you respawn to try again." + "no" "Våpenet @green{1}@default har en kjøpegrense på @green{2}@default enheter. Vent til neste runde eller gjenoppliving." } "Weapons zmarket auto-rebuy toggle on" { - "en" "Auto-rebuy has been enabled, your loadout will be automatically purchased for you each time you spawn." + "no" "Autokjøp er aktivert, dine valg vil automatisk bli kjøpt hver runde eller hver gjenoppliving." } "Weapons zmarket auto-rebuy toggle off" { - "en" "Auto-rebuy has been disabled." + "no" "Autokjøp er deaktivert." } "Weapons zmarket updated loadout" { - "en" "You are not able to purchase a weapon at this time, but your loadout has been updated with this weapon." + "no" "Du kan ikke kjøpe våpen for øyeblikket, men våpenvalget er blitt lagret." } "Weapons zmarket get current loadout" { - "en" "Updated current loadout, use rebuy option to purchase these weapons again." + "no" "Våpenvalg oppdatert. Bruk gjenkjøpvalget for å kjøpe disse våpnene igjen." } // Commands "Weapons command restrict syntax" { - "en" "Restricts a weapon or a weapon type. Usage: zr_restrict [weapon2|weapontype2] ..." + "no" "Sperrer et våpen eller en våpentype. Syntaks: zr_restrict [våpen|våpentype] ..." } "Weapons command unrestrict syntax" { - "en" "Unrestricts a weapon or a weapon type. Usage: zr_unrestrict [weapon2|weapontype2] ..." + "no" "Fjerner sperre av et våpen eller en våpentype. Syntaks: zr_unrestrict [våpen|våpentype] ..." } // Menu (Restrict) "Weapons menu restrict main title" { - "en" "Weapons Management" + "no" "Våpenbehandling" } "Weapons menu restrict main restrict" { - "en" "Weapon Restrictions" + "no" "Våpensperringer" } "Weapons menu restrict main market" { - "en" "ZMarket" + "no" "ZMarket" } "Weapons menu restrict types title" { - "en" "Weapon Restrictions\nSelect Weapon Type:" + "no" "Våpensperringer\nVelg våpentype:" } "Weapons menu restrict types weapon type title" { - "#format" "{1:s}" - "en" "Weapon Restrictions\nWeapon Type: {1}\n[] = Restricted" + "no" "Våpensperringer\nVåpentype: {1}\n[] = Sperret" } "Weapons menu restrict types restrict all" { - "#format" "{1:s}" - "en" "Restrict weapon type {1}" + "no" "Sperr våpentypen \"{1}\"" } "Weapons menu restrict types unrestrict all" { - "#format" "{1:s}" - "en" "Unrestrict weapon type {1}" + "no" "Fjern sperre for våpentypen \"{1}\"" } "Weapons menu restrict zmarket title" { - "en" "ZMarket\nSelect Setting:" + "no" "ZMarket\nVelg instilling:" } "Weapons menu restrict zmarket buyzone" { - "#format" "{1:s}" - "en" "Buyzone Only - {1}" + "no" "Kun i kjøpesoner - {1}" } // Menu (ZMarket) "Weapons menu zmarket main title" { - "en" "ZMarket\nSelect an Option:" + "no" "ZMarket" } "Weapons menu zmarket main get loadout" { - "en" "Get Current Loadout" + "no" "Kjøp gjeldende våpenvalg" } "Weapons menu zmarket main view loadout" { - "en" "View My Loadout" + "no" "Vis våpenvalg" } "Weapons menu zmarket main rebuy" { - "en" "Rebuy My Loadout" + "no" "Kjøp gjeldende våpenvalg" } "Weapons menu zmarket main auto-rebuy" { - "#format" "{1:s}" - "en" "Auto-Rebuy: {1}" + "no" "Autokjøp: {1}" } "Weapons menu zmarket main weapons list" { - "en" "View Weapons List" + "no" "Vis våpenliste" } "Weapons menu zmarket loadout title" { - "en" "ZMarket\nMy Current Loadout:\nSelect weapon slot to clear.\nNote: Rebuy refers to these weapons." + "no" "ZMarket\nGjeldende våpenvalg:\nFjern våpen ved å velge det." } "Weapons menu zmarket loadout primary" { - "#format" "{1:s}" - "en" "Primary: {1}" + "no" "Primærvåpen: {1}" } "Weapons menu zmarket loadout secondary" { - "#format" "{1:s}" - "en" "Secondary: {1}" + "no" "sekundærvåpen: {1}" } "Weapons menu zmarket loadout melee" { - "#format" "{1:s}" - "en" "Melee: {1}" + "no" "Nærkamp: {1}" } "Weapons menu zmarket loadout projectile" { - "#format" "{1:s}" - "en" "Projectile: {1}" + "no" "Prosjektiler: {1}" } "Weapons menu zmarket loadout explosive" { - "#format" "{1:s}" - "en" "Explosive: {1}" + "no" "Granater: {1}" } "Weapons menu zmarket loadout nvgs" { - "#format" "{1:s}" - "en" "NVGs: {1}" + "no" "Nattsyn: {1}" } "Weapons menu zmarket loadout empty" { - "en" "(None)" + "no" "(Ingen)" } "Weapons menu zmarket types title" { - "en" "ZMarket\nSelect Weapon Type:" + "no" "ZMarket\nVelg våpentype:" } "Weapons menu zmarket types weapon type title" { - "#format" "{1:s}" - "en" "ZMarket\nWeapon Type: {1}\n[] = Restricted" + "no" "ZMarket\nVåpentype: {1}\n[] = Sperret" } "Weapons menu zmarket types weapon info" { - "#format" "{1:s},{2:d},{3:d}" - "en" "{1} (${2})\nPurchases Left: {3}" + "no" "{1} (${2})\nAntall kjøp igjen: {3}" } "Weapons menu zmarket types weapon ammo" { - "en" "Ammo" + "no" "Ammunisjon" } // =========================== @@ -772,62 +736,59 @@ "Hitgroups menu hitgroups title" { - "en" "Hitgroup Management\nCommands: zr_hitgroup(_enable_all/_headshots_only)\nSelect a Hitgroup to Toggle:" + "no" "Treffgruppebehandling\nKommandoer: zr_hitgroup(_enable_all/_headshots_only)\nVelg en treffgruppe for å aktivere/deaktivere:" } "Hitgroups menu hitgroups enable all" { - "en" "Enable All Hitgroups" + "no" "Aktiver alle treffgrupper" } "Hitgroups menu hitgroups headshots only" { - "en" "Headshots Only" + "no" "Kun hodeskudd" } // Commands "Hitgroups command syntax" { - "en" "Toggles or sets if a zombie's hitgroup can be damaged. Usage: zr_hitgroup [1/0]" + "no" "Veksle, aktiver eller deaktiver en treffgruppe til zombiene. Usage: zr_hitgroup [aktiv - 1/0]" } "Hitgroups command related commands" { - "en" "Related command(s): zr_hitgroup_enable_all, zr_hitgroup_headshots_only" + "no" "Relaterte kommandoer: zr_hitgroup_enable_all, zr_hitgroup_headshots_only" } "Hitgroups command syntax names" { - "en" "Hitgroup Names:" + "no" "Treffgruppenavn:" } "Hitgroups command successful on" { - "#format" "{1:s}" - "en" "Damage for hitgroup \"{1}\" has been toggled on." + "no" "Skade for treffgruppen \"{1}\" er aktivert." } "Hitgroups command successful off" { - "#format" "{1:s}" - "en" "Damage for hitgroup \"{1}\" has been toggled off." + "no" "Skade for treffgruppen \"{1}\" er deaktivert." } "Hitgroups command invalid hitgroup" { - "#format" "{1:s}" - "en" "\"{1}\" is not a valid hitgroup alias. Type zr_hitgroup to view all aliases." + "no" "\"{1}\" er ikke en gyldig treffgruppe. Bruk zr_hitgroup for å se alle treffgruppenavnene." } "Hitgroups command enable all successful" { - "en" "All zombie hitgroups have been enabled for damage." + "no" "Alle treffgruppene er aktivert." } "Hitgroups command headshots only successful" { - "en" "Zombies may now only be damaged by headshots." + "no" "Zombiene kan nå kun bli skadet av hodeskudd." } // =========================== @@ -836,37 +797,37 @@ "ZAdmin main title" { - "en" "ZAdmin\nSelect Category:" + "no" "ZAdmin\nVelg kategori:" } "ZAdmin main class multipliers" { - "en" "Class Multipliers" + "no" "Klassemultiplikatorer" } "ZAdmin main weapons" { - "en" "Weapon Management" + "no" "Våpenbehandling" } "ZAdmin main hitgroups" { - "en" "Hitgroup Management" + "no" "Treffgruppebehandling" } "ZAdmin main zombie" { - "en" "Zombie Management" + "no" "Spillerbehandling" } "ZAdmin main force zspawn" { - "en" "Force ZSpawn" + "no" "Tving gjenoppliving" } "ZAdmin main force ztele" { - "en" "Force ZTele" + "no" "Tving teleport" } // =========================== @@ -874,39 +835,37 @@ // =========================== // Commands + + // Not translating antistick phrases because hull width settings had no effect. To be removed. "AntiStick command set width syntax" { - "en" "Sets the width of a model's hull. (See zr_antistick_list_models) Usage: zr_antistick_set_width " + "no" "Sets the width of a model's hull. (See zr_antistick_list_models) Usage: zr_antistick_set_width " } "AntiStick command list models list" { - "en" "Player name: Model: Hull width:\n-------------------------------------------------------------------------------------------------------------" + "no" "Player name: Model: Hull width:\n-------------------------------------------------------------------------------------------------------------" } "AntiStick command list models name" { - "#format" "{1:-35s},{2:-51s},{3:-.2f}" - "en" "{1} {2} {3}" + "no" "{1} {2} {3}" } "AntiStick command set width successful" { - "#format" "{1:s},{2:f}" - "en" "Model hull width for model \"{1}\" has been changed to \"{2}.\"" + "no" "Model hull width for model \"{1}\" has been changed to \"{2}.\"" } "AntiStick command set width invalid model" { - "#format" "{1:s}" - "en" "Invalid model/player specified: \"{1}\"" + "no" "Invalid model/player specified: \"{1}\"" } "AntiStick command set width invalid width" { - "#format" "{1:f}" - "en" "Invalid model hull width specified: \"{1}\"" + "no" "Invalid model hull width specified: \"{1}\"" } // =========================== @@ -917,23 +876,19 @@ "Spawn protection begin" { - "#format" "{1:d}" - "en" "Zombies are present, you have {1} seconds to find a safe place before you lose immunity." - "ru" "Зомби на свободе, у вас {1} секунд, чтобы найти безопасное место, пока не потеряли иммунитет." + "no" "Zombier tilstede, du er beskyttet og har {1} sekunder på å finne et trygt sted." } "Spawn protection end" { - "en" "You are now susceptible to zombie infection." - "ru" "Теперь вы восприимчивы к зомби инфекции." + "no" "Du er nå utsatt for å bli smittet av en zombie." } // HUD "Spawn Protect" { - "#format" "{1:d}" - "en" "Zombie protection ends in: {1} seconds." + "no" "Zombiebeskyttelsen stopper om {1} sekunder." } // =========================== @@ -942,30 +897,27 @@ "ZCookies Menu main title" { - "en" "ZCookies\nSelect a Cookie:" + "no" "ZCookies\nVelg informasjonskapsel:" } "ZCookies menu main auto-rebuy" { - "#format" "{1:s}" - "en" "ZMarket Auto-Rebuy: {1}" + "no" "Autokjøp (ZMarket): {1}" } "ZCookies menu main zhp" { - "#format" "{1:s}" - "en" "ZHP Display: {1}" + "no" "ZHP-skjerm: {1}" } "ZCookies menu main overlay" { - "#format" "{1:s}" - "en" "Human/Zombie Class Overlay: {1}" + "no" "Vis klasseoverlegg: {1}" } "ZCookies zmarket loadout" { - "en" "ZMarket Loadout" + "no" "Våpenvalg (ZMarket)" } // =========================== @@ -976,40 +928,36 @@ "ZSpawn double spawn" { - "en" "ZSpawn can only be used if you joined late during a round in progress." + "no" "ZSpawn kan kun bli brukt hvis du koblet til servern midt i en runde." } "ZSpawn timelimit" { - "#format" "{1:d}" - "en" "The timelimit ({1} seconds), to use ZSpawn, has already expired." + "no" "Tidsfristen ({1} sekunder) for å bruke ZSpawn har gått ut." } // Menu "ZSpawn clients title" { - "en" "Force ZSpawn (zr_zspawn_force)\nSelect a Player:" + "no" "Tving gjenoppliving (zr_zspawn_force)\nVelg en spiller:" } // Commands "ZSpawn command force syntax" { - "en" "Force ZSpawn on a client. Usage: zr_zspawn_force ['0' = Spawn as human | '1' = Spawn as zombie]" - + "no" "Tving gjenoppliving på en spiller. Syntaks: zr_zspawn_force ['0' = Menneske | '1' = Zombie]" } "ZSpawn command force successful" { - "#format" "{1:s}" - "en" "Player {1} was successfully spawned." + "no" "{1} ble vellykket gjenopplivet." } "ZSpawn command force unsuccessful" { - "#format" "{1:s}" - "en" "Player {1} couldn't be spawned." + "no" "{1} kunne ikke bli gjenopplivet." } // =========================== @@ -1020,70 +968,63 @@ "ZTele restricted human" { - "en" "ZTele is restricted for humans at this time." + "no" "Mennesker kan ikke teleporteres for øyeblikket." } "ZTele max" { - "#format" "{1:d}" - "en" "You have reached your max of {1} teleport(s) per round." + "no" "Du har brukt opp alle teleportene ({1}) for denne runden." } "ZTele in progress" { - "en" "You are currently pending teleportation." + "no" "Du venter på allerede på en teleport." } "ZTele autocancel text" { - "#format" "{1:d}" - "en" "Teleport has been cancelled. (Restrictive boundary is {1} ft.)" + "no" "Teleport avbrutt. Du har forflyttet deg lengre enn tillatt da du ventet på en teleport. Maks lengde er {1} fot." } // Center Text "ZTele countdown" { - "#format" "{1:d}" - "en" "Teleporting back to spawn in: {1} seconds." + "no" "Teleporterer til startområdet om {1} sekunder." } "ZTele autocancel centertext" { - "en" "Teleport has been cancelled." + "no" "Teleport avbrutt." } "ZTele countdown end" { - "#format" "{1:d},{2:d}" - "en" "Teleported back to spawn. (Count: {1}/{2})" + "no" "Teleportert til startområdet. (Antall: {1}/{2})" } // Menu "ZTele clients title" { - "en" "Force ZTele (zr_ztele_force)\nSelect a Player:" + "no" "Tving teleport (zr_ztele_force)\nVelg en spiller:" } // Commands "ZTele command force syntax" { - "en" "Force ZTele on a client. Usage: zr_ztele_force " - + "no" "Tving teleport på en spiller. Syntaks: zr_ztele_force " } "ZTele command force successful" { - "#format" "{1:s}" - "en" "Player {1} was successfully teleported." + "no" "{1} ble vellykket teleportert." } "ZTele command force unsuccessful" { - "#format" "{1:s}" - "en" "Player {1} couldn't be teleported." + "no" "{1} kunne ikke bli teleportert." } // =========================== @@ -1094,22 +1035,19 @@ "ZHP enable" { - "en" "HP display enabled, your real HP will be displayed after infection." + "no" "HP-skjerm aktivert. Du vil se din ekte helseverdi som zombie." } "ZHP disable" { - "en" "HP display disabled." - "ru" "Отображение здоровья включено." + "no" "HP-skjerm deaktivert." } // HUD "Display HP" { - "#format" "{1:d}" - "en" "HP: {1}" - "ru" "Здоровье: {1}" + "no" "HP: {1}" } // =========================== @@ -1118,18 +1056,16 @@ "Vol Anticamp Message" { - "en" "This area is restricted, please move along." + "no" "Dette området er sperret, vennligst gå videre." } "Vol Slay" { - "#format" "{1:s},{2:d}" - "en" "Slayed player \"{1}\" for camping in a restricted area (ID: {2})." + "no" "Drepte \"{1}\" for opphold i sperret område (ID: {2})." } "Vol Ignite" { - "#format" "{1:s},{2:d}" - "en" "Ignited player \"{1}\" for camping in a restricted area (ID: {2})." + "no" "Satt fyr på \"{1}\" for opphold i sperret område (ID: {2})." } } diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index 6b34eca..f0ed4dc 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -65,7 +65,7 @@ "Must be zombie" { - "en" "This feature requires that you are a zombie. + "en" "This feature requires that you are a zombie." } "Must be human" @@ -356,6 +356,11 @@ "en" "Jump Distance" } + "Classes Selection Not Allowed" + { + "en" "Changing classes is not allowed." + } + // =========================== // Overlays (core) // =========================== diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index 3380d30..09accb7 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -91,7 +91,7 @@ zr_log "1" // Default: "3" zr_log_flags "3" -// Enable module filtering. Only log events from listed modules will be logged. +// Enable module filtering. Only events from listed modules will be logged. // Default: "0" zr_log_module_filter "0" @@ -163,6 +163,18 @@ zr_classes_default_zombie "random" // Default: "motherzombies" zr_classes_default_mother_zombie "motherzombies" +// Allow players to select zombie classes. +// Default: "1" +zr_classes_zombie_select "1" + +// Allow players to select human classes. +// Default: "1" +zr_classes_human_select "1" + +// Allow admins to select admin mode classes. (Not to be confused by admin-only classes!) +// Default: "1" +zr_classes_admin_select "1" + // Menu // Automatically close class selection menu. diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 3cfde01..5b624dd 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -62,6 +62,9 @@ enum CvarsList Handle:CVAR_CLASSES_OVERLAY_TOGGLE, Handle:CVAR_CLASSES_OVERLAY_TOGGLECMDS, Handle:CVAR_CLASSES_OVERLAY_DEFAULT, + Handle:CVAR_CLASSES_ZOMBIE_SELECT, + Handle:CVAR_CLASSES_HUMAN_SELECT, + Handle:CVAR_CLASSES_ADMIN_SELECT, Handle:CVAR_WEAPONS, Handle:CVAR_WEAPONS_RESTRICT, Handle:CVAR_WEAPONS_ZMARKET, @@ -214,7 +217,7 @@ CvarsCreate() // =========================== g_hCvarsList[CVAR_LOG] = CreateConVar("zr_log", "1", "Enable logging of events in the plugin. Fatal errors are logged independent on this setting."); g_hCvarsList[CVAR_LOG_FLAGS] = CreateConVar("zr_log_flags", "3", "A bit field that specify what event types to log. See logging section (3.3) in manual for details."); - g_hCvarsList[CVAR_LOG_MODULE_FILTER] = CreateConVar("zr_log_module_filter", "0", "Enable module filtering. Only log events from listed modules will be logged."); + g_hCvarsList[CVAR_LOG_MODULE_FILTER] = CreateConVar("zr_log_module_filter", "0", "Enable module filtering. Only events from listed modules will be logged."); g_hCvarsList[CVAR_LOG_IGNORE_CONSOLE] = CreateConVar("zr_log_ignore_console", "1", "Don't log events triggered by console commands that are executed by the console itself, like commands in configs. Enable this command to avoid spamming logs with events like weapon restrictions."); g_hCvarsList[CVAR_LOG_ERROR_OVERRIDE] = CreateConVar("zr_log_error_override", "1", "Always log error messages. Overrides module filter and logging flags."); g_hCvarsList[CVAR_LOG_PRINT_ADMINS] = CreateConVar("zr_log_print_admins", "0", "Print log events to admin chat in addition to the log file."); @@ -242,6 +245,9 @@ CvarsCreate() g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "motherzombies","Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. [\"random\" = Random human class | \"\" = Class config default]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "random", "Admin class assigned to admins on connect. [\"random\" = Random admin class | \"\" = Class config default]"); + g_hCvarsList[CVAR_CLASSES_ZOMBIE_SELECT] = CreateConVar("zr_classes_zombie_select", "1", "Allow players to select zombie classes."); + g_hCvarsList[CVAR_CLASSES_HUMAN_SELECT] = CreateConVar("zr_classes_human_select", "1", "Allow players to select human classes."); + g_hCvarsList[CVAR_CLASSES_ADMIN_SELECT] = CreateConVar("zr_classes_admin_select", "1", "Allow admins to select admin mode classes. (Not to be confused by admin-only classes!)"); // Menu g_hCvarsList[CVAR_CLASSES_MENU_AUTOCLOSE] = CreateConVar("zr_classes_menu_autoclose", "0", "Automatically close class selection menu after selecting a class."); diff --git a/src/zr/log.inc b/src/zr/log.inc index 0682a3c..99e9e5c 100644 --- a/src/zr/log.inc +++ b/src/zr/log.inc @@ -624,7 +624,7 @@ public Action:Command_LogRemoveModule(client, argc) if (argc < 1) { // Display syntax info. - StrCat(buffer, sizeof(buffer), "Add one or more modules to the module filter. Usage: zr_log_add_module [module] ...\n"); + StrCat(buffer, sizeof(buffer), "Remove one or more modules to the module filter. Usage: zr_log_remove_module [module] ...\n"); StrCat(buffer, sizeof(buffer), "See zr_log_list to list available module names (short names)."); ReplyToCommand(client, buffer); } diff --git a/src/zr/menu.inc b/src/zr/menu.inc index 4585af7..93ddff6 100644 --- a/src/zr/menu.inc +++ b/src/zr/menu.inc @@ -117,7 +117,10 @@ ZMenuMain(client) new bool:admin = ZRIsClientAdmin(client); AddMenuItem(menu_main, "zadmin", zadmin, MenuGetItemDraw(admin)); - AddMenuItem(menu_main, "zclass", zclass); + // Decide whether the client can use zclass. + new zclassdraw = ClassAllowSelection(client) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; + + AddMenuItem(menu_main, "zclass", zclass, zclassdraw); AddMenuItem(menu_main, "zcookies", zcookies); AddMenuItem(menu_main, "zspawn", zspawn); AddMenuItem(menu_main, "ztele", ztele); diff --git a/src/zr/playerclasses/classcommands.inc b/src/zr/playerclasses/classcommands.inc index ae6b859..22286fe 100644 --- a/src/zr/playerclasses/classcommands.inc +++ b/src/zr/playerclasses/classcommands.inc @@ -59,7 +59,14 @@ public Action:ZClassCommand(client, argc) // If client is console, then stop and tell them this feature is for players only. if (ZRIsConsole(client)) { - TranslationPrintToServer("Must be player"); + TranslationReplyToCommand(client, "Must be player"); + return Plugin_Handled; + } + + // Check if class selection is allowed. + if (!ClassAllowSelection(client)) + { + TranslationReplyToCommand(client, "Classes Selection Not Allowed"); return Plugin_Handled; } diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index 33deaca..e3f6bc2 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -65,18 +65,19 @@ ClassMenuMain(client) // Get number of enabled classes per team. new zombiecount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES); new humancount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES); - new admincount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES); + new admincount = ClassCountTeam(ZR_CLASS_TEAM_ADMINS); // Get previously selected class indexes, if set. new nextzombie = ClassSelectedNext[client][ZR_CLASS_TEAM_ZOMBIES]; new nexthuman = ClassSelectedNext[client][ZR_CLASS_TEAM_HUMANS]; new nextadmin = ClassSelectedNext[client][ZR_CLASS_TEAM_ADMINS]; - // Set draw style on class options depending on number of enabled classes. - // Disable class selection if there's only one class. - new zombie_itemdraw = (zombiecount > 1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; - new human_itemdraw = (humancount > 1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; - new admin_itemdraw = (admincount > 1) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; + // Set draw style on class options depending on number of enabled classes + // and selection permissions. Disable class selection if there's only one + // class. + new zombie_itemdraw = (zombiecount > 1 && ClassAllowSelection(client, ZR_CLASS_TEAM_ZOMBIES)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; + new human_itemdraw = (humancount > 1 && ClassAllowSelection(client, ZR_CLASS_TEAM_HUMANS)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; + new admin_itemdraw = (admincount > 1 && ClassAllowSelection(client, ZR_CLASS_TEAM_ADMINS)) ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED; // Check if the player is in admin mode. if (ClassPlayerInAdminMode[client]) diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index e74c0b6..4c53ae6 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -515,6 +515,64 @@ stock bool:ClassFlagFilterMatch(index, require, deny, cachetype) } } +/** + * Decides whether a class selection menu should be enabled. The decision is + * based on zr_class_allow_* console variables. + * + * @param team Optional. Team ID to match. Default is all. + * @return True if allowed, false otherwise. + */ +bool:ClassAllowSelection(client, team = -1) +{ + // Get selection settings. + new bool:zombie = GetConVarBool(g_hCvarsList[CVAR_CLASSES_ZOMBIE_SELECT]); + new bool:human = GetConVarBool(g_hCvarsList[CVAR_CLASSES_HUMAN_SELECT]); + new bool:admin = GetConVarBool(g_hCvarsList[CVAR_CLASSES_ADMIN_SELECT]); + + // Since admin mode classes are optional they must be counted to verify + // that they exist. + new bool:adminexist; + + // Check if player is admin. + new bool:isadmin = ZRIsClientAdmin(client); + + // Only count admin mode classes if client is admin for better performance. + if (isadmin) + { + adminexist = ClassCountTeam(ZR_CLASS_TEAM_ADMINS) > 0; + } + + // Check if a team id is specified. + if (team >= 0) + { + // Check team and return the corresponding selection setting. + switch (team) + { + case ZR_CLASS_TEAM_ZOMBIES: + { + return zombie; + } + case ZR_CLASS_TEAM_HUMANS: + { + return human; + } + case ZR_CLASS_TEAM_ADMINS: + { + // Player must be admin to select admin mode classes. + return admin && isadmin && adminexist; + } + } + + // Team ID didn't match. + return false; + } + else + { + // Check zombie and human. + return zombie || human; + } +} + /** * Gets all class indexes or from a specified team, and adds them to the * specified array. diff --git a/src/zr/translation.inc b/src/zr/translation.inc index 63658d8..812fdae 100644 --- a/src/zr/translation.inc +++ b/src/zr/translation.inc @@ -333,16 +333,13 @@ stock TranslationReplyToCommand(client, any:...) { // Format string to create plugin style. (color) TranslationPluginFormatString(translation, sizeof(translation)); - - // Print translated phrase to client's chat/console. - PrintToChat(client, translation); } else { // Format string to create plugin style. (no color) TranslationPluginFormatString(translation, sizeof(translation), false); - - // Print to server. - PrintToServer(translation); } + + // Print translated phrase to server or client's chat/console. + ReplyToCommand(client, translation); } From 20f649e32e1007e61ebcf24b8daee4224c3c5228 Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 10 Aug 2009 02:55:42 +0200 Subject: [PATCH 03/16] Changes in translations. Simplified zmenu phrases. --- .../no/zombiereloaded.phrases.txt | 16 +++++++------- .../translations/zombiereloaded.phrases.txt | 21 +++++++------------ src/zr/menu.inc | 14 ++++++------- 3 files changed, 22 insertions(+), 29 deletions(-) diff --git a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt index 208c4a9..92b1446 100644 --- a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt @@ -439,37 +439,37 @@ "Menu main zadmin" { - "no" "ZAdmin - Åpne administrasjonsmeny. (Kommando: {1})" + "no" "ZAdmin - Åpne administrasjonsmeny" } "Menu main zclass" { - "no" "ZClass - Endre klasseinstillinger. (Kommando: {1})" + "no" "ZClass - Endre klasseinstillinger" } "Menu main zcookies" { - "no" "ZCookies - Endre egendefinerte instillinger. (Kommando: {1})" + "no" "ZCookies - Endre lagrede instillinger" } "Menu main zspawn" { - "no" "ZSpawn - Bli med i spillet øyeblikkelig. (Kommando: {1})" + "no" "ZSpawn - Bli med i spillet øyeblikkelig" } "Menu main ztele" { - "no" "ZTele - Teleporter til startområde. (Kommando: {1})" + "no" "ZTele - Teleporter til startområde" } "Menu main zhp" { - "no" "ZHP - Vis nåværende helsenivå. (Kommando: {1})" + "no" "ZHP - Vis nåværende helsenivå" } "Menu main zmarket" { - "no" "ZMarket - Endre egendefinerte våpeninstillinger. (Kommando: {1})" + "no" "ZMarket - Endre våpeninstillinger" } // =========================== @@ -645,7 +645,7 @@ "Weapons menu zmarket main get loadout" { - "no" "Kjøp gjeldende våpenvalg" + "no" "Lagre gjeldende våpenvalg" } "Weapons menu zmarket main view loadout" diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index f0ed4dc..54ca9ce 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -466,44 +466,37 @@ "Menu main zadmin" { - "#format" "{1:s}" - "en" "ZAdmin - Open admin menu. (Command: {1})" + "en" "ZAdmin - Open admin menu" } "Menu main zclass" { - "#format" "{1:s}" - "en" "ZClass - Configure class settings. (Command: {1})" + "en" "ZClass - Configure class settings" } "Menu main zcookies" { - "#format" "{1:s}" - "en" "ZCookies - Toggle personal ZR settings here. (Command: {1})" + "en" "ZCookies - Toggle personal ZR settings here" } "Menu main zspawn" { - "#format" "{1:s}" - "en" "ZSpawn - Join late? Spawn with this. (Command: {1})" + "en" "ZSpawn - Join late? Spawn with this" } "Menu main ztele" { - "#format" "{1:s}" - "en" "ZTele - Stuck? Teleport back to spawn. (Command: {1})" + "en" "ZTele - Stuck? Teleport back to spawn" } "Menu main zhp" { - "#format" "{1:s}" - "en" "ZHP - Shows real HP as zombie. (Command: {1})" + "en" "ZHP - Shows real HP as zombie" } "Menu main zmarket" { - "#format" "{1:s}" - "en" "ZMarket - Customize loadouts here. (Command: {1})" + "en" "ZMarket - Customize loadouts here" } // =========================== diff --git a/src/zr/menu.inc b/src/zr/menu.inc index 93ddff6..47514aa 100644 --- a/src/zr/menu.inc +++ b/src/zr/menu.inc @@ -101,13 +101,13 @@ ZMenuMain(client) // Translate each line into client's language. Format(title, sizeof(title), "%t\n ", "Menu main title", publictrigger, silenttrigger); - Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin", SAYHOOKS_KEYWORD_ZADMIN); - Format(zclass, sizeof(zclass), "%t", "Menu main zclass", SAYHOOKS_KEYWORD_ZCLASS); - Format(zcookies, sizeof(zcookies), "%t", "Menu main zcookies", SAYHOOKS_KEYWORD_ZCOOKIES); - Format(zspawn, sizeof(zspawn), "%t", "Menu main zspawn", SAYHOOKS_KEYWORD_ZSPAWN); - Format(ztele, sizeof(ztele), "%t", "Menu main ztele", SAYHOOKS_KEYWORD_ZTELE); - Format(zhp, sizeof(zhp), "%t", "Menu main zhp", SAYHOOKS_KEYWORD_ZHP); - Format(zmarket, sizeof(zmarket), "%t", "Menu main zmarket", SAYHOOKS_KEYWORD_ZMARKET); + Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin"); + Format(zclass, sizeof(zclass), "%t", "Menu main zclass"); + Format(zcookies, sizeof(zcookies), "%t", "Menu main zcookies"); + Format(zspawn, sizeof(zspawn), "%t", "Menu main zspawn"); + Format(ztele, sizeof(ztele), "%t", "Menu main ztele"); + Format(zhp, sizeof(zhp), "%t", "Menu main zhp"); + Format(zmarket, sizeof(zmarket), "%t", "Menu main zmarket"); // Add items to menu. From 658a800fea6df397549aa76060070568a5c091ce Mon Sep 17 00:00:00 2001 From: ricahrd Date: Mon, 10 Aug 2009 19:01:43 +0200 Subject: [PATCH 04/16] Implemented zr_classes_spawn. Made new instant class change feature on human classes, with time limit. --- .../zombiereloaded/zombiereloaded.cfg | 6 ++- src/zr/cvars.inc | 4 +- src/zr/playerclasses/classevents.inc | 35 +++++++++++++ src/zr/playerclasses/classmenus.inc | 49 ++++++++++++------- src/zr/playerclasses/playerclasses.inc | 8 ++- 5 files changed, 80 insertions(+), 22 deletions(-) diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index c36b0bf..f7e103f 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -143,10 +143,14 @@ zr_config_path_hitgroups "configs/zr/hitgroups.txt" // Default: "0" zr_classes_spawn "0" -// Player is assigned a random class every spawn. [Override: zr_classes_spawn & zr_classes_default_*] +// Player is assigned a random class every spawn. [Override: zr_classes_default_*] // Default: "0" zr_classes_random "0" +// Time limit to change class with instant change after spawning. Time is in seconds. Use 0 or negative to disable. +// Default: "20" +zr_classes_change_timelimit "20" + // Admin class assigned to admins on connect. ["random" = Random admin class | "" = Class config default] // Default: "random" zr_classes_default_admin "random" diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 6925732..c3f012c 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -54,6 +54,7 @@ enum CvarsList Handle:CVAR_CONFIG_PATH_HITGROUPS, Handle:CVAR_CLASSES_SPAWN, Handle:CVAR_CLASSES_RANDOM, + Handle:CVAR_CLASSES_CHANGE_TIMELIMIT, Handle:CVAR_CLASSES_DEFAULT_ZOMBIE, Handle:CVAR_CLASSES_DEFAULT_M_ZOMB, Handle:CVAR_CLASSES_DEFAULT_HUMAN, @@ -240,7 +241,8 @@ CvarsCreate() // General g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Re-display class selection menu every spawn."); - g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_spawn and zr_classes_default_*]"); + g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_default_*]"); + g_hCvarsList[CVAR_CLASSES_CHANGE_TIMELIMIT] = CreateConVar("zr_classes_change_timelimit", "20", "Time limit to change class with instant change after spawning. Time is in seconds. Use 0 or negative to disable."); g_hCvarsList[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "random", "Zombie class assigned to players on connect. [\"random\" = Random zombie class | \"\" = Class config default]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "motherzombies","Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. [\"random\" = Random human class | \"\" = Class config default]"); diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc index b217081..3ae4ebc 100644 --- a/src/zr/playerclasses/classevents.inc +++ b/src/zr/playerclasses/classevents.inc @@ -141,11 +141,34 @@ ClassOnClientSpawn(client) ClassGetName(randomhuman, classname, sizeof(classname), ZR_CLASS_TEAM_HUMANS); TranslationPrintToChat(client, "Classes random assignment", classname); } + + // Display class menu if enabled. + new bool:classmenu = GetConVarBool(g_hCvarsList[CVAR_CLASSES_SPAWN]); + if (classmenu) + { + ClassMenuMain(client); + } } // Apply class attributes for the active class. ClassReloadPlayerCache(client, ClassGetActiveIndex(client)); ClassApplyAttributes(client); + + // Check if instant class change cvar is set. + new Float:instantspawn = GetConVarFloat(g_hCvarsList[CVAR_CLASSES_CHANGE_TIMELIMIT]); + if (instantspawn > 0) + { + // Allow instant class change. + ClassAllowInstantChange[client] = true; + + // Create timer to disable instant change. + CreateTimer(instantspawn, Event_ClassDisableInstantSpawn, client, TIMER_FLAG_NO_MAPCHANGE); + } + else + { + // Make sure instant change is not allowed. + ClassAllowInstantChange[client] = false; + } } /** @@ -182,6 +205,9 @@ ClassOnClientInfected(client, bool:motherzombie = false) // Disable class attributes with timers. ClassHealthRegenStop(client); + // Make sure the player is not allowed to instantly change class. + ClassAllowInstantChange[client] = false; + // Check if it's a mother zombie. if (motherzombie) { @@ -259,3 +285,12 @@ ClassOnClientInfected(client, bool:motherzombie = false) // Apply the new attributes. ClassApplyAttributes(client, motherzombie); } + +/** + * Timer callback for disabling instant class change setting on a client. + */ +public Action:Event_ClassDisableInstantSpawn(Handle:timer, any:client) +{ + // Disable instant class change. + ClassAllowInstantChange[client] = false; +} diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index e3f6bc2..88602bb 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -332,28 +332,41 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot) // Solve teamid from the class index. teamid = ClassGetTeamID(classindex, ZR_CLASS_CACHE_MODIFIED); - // Check if the player is alive. - if (IsPlayerAlive(client)) + // Allow instant class change if enabled and both class and player is human. + if (ClassAllowInstantChange[client] && !iszombie && teamid == ZR_CLASS_TEAM_HUMANS) { - // 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)) - { - // Set class to be used on next spawn. - ClassSelectedNext[client][teamid] = classindex; - } - else - { - // Directly change the selected class index. - ClassSelected[client][teamid] = classindex; - } + // Directly change the selected class index. + ClassSelected[client][teamid] = classindex; + + // Update cache and apply attributes. + ClassReloadPlayerCache(client, classindex); + ClassApplyAttributes(client); } else { - // Player isn't alive. The class can be directly changed. - ClassSelected[client][teamid] = classindex; + // 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)) + { + // 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; + } } } case MenuAction_Cancel: diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 0de2ee4..05ddf75 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -362,9 +362,13 @@ new ClassMultipliers:ClassAdminAttributeSelected[MAXPLAYERS + 1]; new bool:ClassPlayerInAdminMode[MAXPLAYERS + 1]; /** - * Specifies the admin class to use on next admin mode spawn. + * Specifies whether a player is allowed to change class with instant effect. + * This is only used on human classes, and in combination with the + * zr_classes_change_timelimit time limit, but could be used other places too. + * The class menu will automatically check this setting and apply attributes if + * set to true. */ -//new ClassPlayerNextAdminClass[MAXPLAYERS + 1]; +new bool:ClassAllowInstantChange[MAXPLAYERS + 1]; /** * Cache for storing original model path before applying custom models. Used From 3a82d3d9b058351294eb7a7548569f85d4e59741 Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 11 Aug 2009 03:29:22 +0200 Subject: [PATCH 05/16] Added support for group based authentication. --- .../zombiereloaded/zombiereloaded.cfg | 9 + src/zombiereloaded.sp | 1 + src/zr/admintools.inc | 168 ++++++++++++++++++ src/zr/cvars.inc | 7 + src/zr/playerclasses/classmenus.inc | 10 +- src/zr/zadmin.inc | 16 +- src/zr/zombiereloaded.inc | 4 +- 7 files changed, 198 insertions(+), 17 deletions(-) create mode 100644 src/zr/admintools.inc diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index f7e103f..00261b9 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -133,6 +133,15 @@ zr_config_path_weapons "configs/zr/weapons.txt" zr_config_path_hitgroups "configs/zr/hitgroups.txt" +// ---------------------------------------------------------------------------- +// Permission settings +// ---------------------------------------------------------------------------- + +// Use group authentication instead of flags to access admin features. Generic admin flag is still required on some features. +// - +// Default: "0" +zr_permissions_use_groups "0" + // ---------------------------------------------------------------------------- // Classes (core) // ---------------------------------------------------------------------------- diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index b0655a2..59dc729 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -41,6 +41,7 @@ #include "zr/zombiereloaded" #include "zr/translation" #include "zr/cvars" +#include "zr/admintools" #include "zr/log" #include "zr/config" #include "zr/steamidcache" diff --git a/src/zr/admintools.inc b/src/zr/admintools.inc new file mode 100644 index 0000000..e767679 --- /dev/null +++ b/src/zr/admintools.inc @@ -0,0 +1,168 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: admintools.inc + * Type: Core + * Description: Functions for checking extended admin privileges. + * + * Copyright (C) 2009 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 Pre-defined group names for authenticating players. + */ +#define ZR_GROUP_ADMINS "zr_admins" +#define ZR_GROUP_MODERATORS "zr_moderators" +#define ZR_GROUP_CONFIGURATORS "zr_configurators" +/** + * @endsection + */ + +/** + * List of operation types to specify the category of a admin operation. + */ +enum OperationTypes +{ + OperationType_Invalid = -1, /** Invalid operation type. */ + OperationType_Generic, /** Generic events like infecting or teleporting players. */ + OperationType_Configuration, /** Changing settings. */ +} + + +/** + * Returns whether a player is allowed to do a certain operation or not. + * + * @param client The client index. + * @param operationType The operation category. + * @return True if allowed, false otherwise. + */ +stock bool:ZRIsClientPrivileged(client, OperationTypes:operationType = OperationType_Generic) +{ + // Validate client index. + if (!ZRIsClientValid(client)) + { + return false; + } + + // Check if group permissions is enabled. + new bool:groupauth = GetConVarBool(g_hCvarsList[CVAR_PERMISSIONS_USE_GROUPS]); + if (groupauth) + { + /********************************** + * * + * GROUP BASED AUTHENTICATION * + * * + **********************************/ + + // Check if client is full admin. + if (ZRIsClientInGroup(client, ZR_GROUP_ADMINS)) + { + return true; + } + + // Check operation type. + switch (operationType) + { + case OperationType_Generic: + { + return ZRIsClientInGroup(client, ZR_GROUP_MODERATORS); + } + case OperationType_Configuration: + { + return ZRIsClientInGroup(client, ZR_GROUP_CONFIGURATORS); + } + } + + // Invalid operation type. + return false; + } + else + { + /********************************* + * * + * FLAG BASED AUTHENTICATION * + * * + *********************************/ + + new AdminFlag:flag; + + // Check operation type. + switch (operationType) + { + case OperationType_Generic: + { + flag = Admin_Generic; + } + case OperationType_Configuration: + { + flag = Admin_Config; + } + default: + { + // Invalid operation type. + return false; + } + } + + return GetAdminFlag(GetUserAdmin(client), flag); + } +} + +/** + * Returns whether a player is in a spesific group or not. + * + * @param client The client index. + * @param groupName SourceMod group name to check. + * @return True if in the group, false otherwise. + */ +stock bool:ZRIsClientInGroup(client, const String:groupName[]) +{ + new AdminId:id = GetUserAdmin(client); + + // Validate id. + if (id == INVALID_ADMIN_ID) + { + return false; + } + + // Get number of groups. + new groupnum = GetAdminGroupCount(id); + decl String:groupname[64]; + + // Validate number of groups. + if (groupnum > 0) + { + // Loop through each group. + for (new group = 0; group < groupnum; group++) + { + // Get group name. + GetAdminGroup(id, group, groupname, sizeof(groupname)); + + // Compare names. + if (StrEqual(groupName, groupname, false)) + { + return true; + } + } + } + + // No groups or no match. + return false; +} diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index c3f012c..02b9ec6 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -52,6 +52,7 @@ enum CvarsList Handle:CVAR_CONFIG_PATH_CLASSES, Handle:CVAR_CONFIG_PATH_WEAPONS, Handle:CVAR_CONFIG_PATH_HITGROUPS, + Handle:CVAR_PERMISSIONS_USE_GROUPS, Handle:CVAR_CLASSES_SPAWN, Handle:CVAR_CLASSES_RANDOM, Handle:CVAR_CLASSES_CHANGE_TIMELIMIT, @@ -235,6 +236,12 @@ CvarsCreate() g_hCvarsList[CVAR_CONFIG_PATH_HITGROUPS] = CreateConVar("zr_config_path_hitgroups", "configs/zr/hitgroups.txt", "Path, relative to root sourcemod directory, to hitgroups config file."); + // =========================== + // Permission Settings + // =========================== + g_hCvarsList[CVAR_PERMISSIONS_USE_GROUPS] = CreateConVar("zr_permissions_use_groups", "0", "Use group authentication instead of flags to access admin features. Generic admin flag is still required on some features."); + + // =========================== // Classes (core) // =========================== diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index 88602bb..89c5fa4 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -409,15 +409,9 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot) * @return True if displayed, false otherwise. */ bool:ClassTeamSelect(client) -{ - // Validate client. - if (!ZRIsClientValid(client, false)) - { - return false; - } - +{ // Validate permissions. - if (!ZRIsClientAdmin(client, Admin_Config)) + if (!ZRIsClientPrivileged(client, OperationType_Configuration)) { return false; } diff --git a/src/zr/zadmin.inc b/src/zr/zadmin.inc index 0ec51a1..557f7ae 100644 --- a/src/zr/zadmin.inc +++ b/src/zr/zadmin.inc @@ -64,7 +64,7 @@ public Action:ZAdminCommand(client, argc) */ bool:ZAdminMenu(client) { - // If client isn't an admin, then stop. + // If client isn't an generic admin, then stop. if (!ZRIsClientAdmin(client)) { TranslationPrintToChat(client, "Must be admin"); @@ -94,16 +94,18 @@ bool:ZAdminMenu(client) Format(ztele, sizeof(ztele), "%t", "ZAdmin main force ztele"); // Get conditions for options. - new bool:hitgroupsenabled = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]); + new configdraw = MenuGetItemDraw(ZRIsClientPrivileged(client, OperationType_Configuration)); + new moderatordraw = MenuGetItemDraw(ZRIsClientPrivileged(client, OperationType_Generic)); + new bool:hitgroupsenabled = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]) && ZRIsClientPrivileged(client, OperationType_Configuration); // Add items to menu. SetMenuTitle(menu_zadmin, title); - AddMenuItem(menu_zadmin, "classmultipliers", classmultipliers); - AddMenuItem(menu_zadmin, "weapons", weapons); + AddMenuItem(menu_zadmin, "classmultipliers", classmultipliers, configdraw); + AddMenuItem(menu_zadmin, "weapons", weapons, configdraw); AddMenuItem(menu_zadmin, "hitgroups", hitgroups, MenuGetItemDraw(hitgroupsenabled)); - AddMenuItem(menu_zadmin, "infect", infect); - AddMenuItem(menu_zadmin, "zspawn", zspawn); - AddMenuItem(menu_zadmin, "ztele", ztele); + AddMenuItem(menu_zadmin, "infect", infect, moderatordraw); + AddMenuItem(menu_zadmin, "zspawn", zspawn, moderatordraw); + AddMenuItem(menu_zadmin, "ztele", ztele, moderatordraw); // Set "Back" button. SetMenuExitBackButton(menu_zadmin, true); diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 4dbb895..f97041c 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -235,7 +235,7 @@ stock bool:ZRTeamHasClients(team = -1) } /** - * Returns whether a player is a generic admin or not. + * Returns whether a player is a admin or not. * * @param client The client index. * @param flag Optional. Flag to check. Default is generic admin flag. @@ -249,7 +249,7 @@ stock bool:ZRIsClientAdmin(client, AdminFlag:flag = Admin_Generic) return false; } - // If client doesn't have the Admin_Generic flag, then stop. + // If client doesn't have the specified flag, then stop. if (!GetAdminFlag(GetUserAdmin(client), flag)) { return false; From 6a14b952af4b3c74721c5e13346d885903fdb5d3 Mon Sep 17 00:00:00 2001 From: richard Date: Thu, 13 Aug 2009 18:31:21 +0200 Subject: [PATCH 06/16] Added group class attribute, not implemented. Capitalized all class attribute names. --- docs/zr_manual.txt | 60 +++-- src/zr/playerclasses/attributes.inc | 210 +++++++++------ src/zr/playerclasses/classcommands.inc | 83 +++--- src/zr/playerclasses/filtertools.inc | 54 ++-- src/zr/playerclasses/playerclasses.inc | 353 +++++++++++++------------ 5 files changed, 423 insertions(+), 337 deletions(-) diff --git a/docs/zr_manual.txt b/docs/zr_manual.txt index 51c928a..3ac1f1c 100644 --- a/docs/zr_manual.txt +++ b/docs/zr_manual.txt @@ -651,8 +651,13 @@ The list below explains all available class attributes in detail: setting must be set to "motherzombies" for this flag to take effect. - Remember that these flags can be used in a combination (1 + 2), so - it's a mother zombie class for admins only. + These flags can be used in a combination (1 + 2), so it could be a + mother zombie class for admins only. + + group text Name of a valid SourceMod group. + --------------------------------------------------------------------------- + Rescrict class to members of this SourceMod group. Useful for making + VIP-only classes. Leave blank to allow everyone to use this class. name text Unique, not empty, max 64 charact. --------------------------------------------------------------------------- @@ -750,8 +755,8 @@ The list below explains all available class attributes in detail: kill_bonus number 0 - 16 --------------------------------------------------------------------------- - Zombie classes only. How many EXTRA points to give the killer of a - zombie. If this is 0, the default value of 1 point will be given. + Zombie classes only. How many extra points to give the killer of this + zombie. If this is 0, the default value of 1 point will be given. speed decimal 10.0 - 2000.0 --------------------------------------------------------------------------- @@ -798,29 +803,30 @@ Attribute flags: team 2 2 team_default 3 4 flags 4 8 - name 5 16 - description 6 32 - model_path 7 64 - alpha_initial 8 128 - alpha_damaged 9 256 - alpha_damage 10 512 - overlay_path 11 1024 - nvgs 12 2048 - fov 13 4096 - has_napalm 14 8192 - napalm_time 15 16384 - immunity_mode 16 32768 - immunity_amount 17 65536 - no_fall_damage 18 131072 - health 19 262144 - health_regen_interval 20 524288 - health_regen_amount 21 1048576 - infect_gain 22 2097152 - kill_bonus 23 4194304 - speed 24 8388608 - knockback 25 16777216 - jump_height 26 33554432 - jump_distance 27 67108864 + group 5 16 + name 6 32 + description 7 64 + model_path 8 128 + alpha_initial 9 256 + alpha_damaged 10 512 + alpha_damage 11 1024 + overlay_path 12 2048 + nvgs 13 4096 + fov 14 8192 + has_napalm 15 16384 + napalm_time 16 32768 + immunity_mode 17 65536 + immunity_amount 18 131072 + no_fall_damage 19 262144 + health 20 524288 + health_regen_interval 21 1048576 + health_regen_amount 22 2097152 + infect_gain 23 4194304 + kill_bonus 24 8388608 + speed 25 16777216 + knockback 26 33554432 + jump_height 27 67108864 + jump_distance 28 134217728 The error flags are stored in a bit field (explained in the log configuration in section 3.2). diff --git a/src/zr/playerclasses/attributes.inc b/src/zr/playerclasses/attributes.inc index 960c60b..274e263 100644 --- a/src/zr/playerclasses/attributes.inc +++ b/src/zr/playerclasses/attributes.inc @@ -52,15 +52,15 @@ stock bool:ClassIsEnabled(index, cachetype = ZR_CLASS_CACHE_MODIFIED) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_enabled]; + return ClassData[index][Class_Enabled]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_enabled]; + return ClassDataCache[index][Class_Enabled]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_enabled]; + return ClassPlayerCache[index][Class_Enabled]; } } return false; @@ -84,15 +84,15 @@ stock ClassGetTeamID(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_team]; + return ClassData[index][Class_Team]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_team]; + return ClassDataCache[index][Class_Team]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_team]; + return ClassPlayerCache[index][Class_Team]; } } return -1; @@ -118,15 +118,15 @@ stock bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_team_default]; + return ClassData[index][Class_TeamDefault]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_team_default]; + return ClassDataCache[index][Class_TeamDefault]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_team_default]; + return ClassPlayerCache[index][Class_TeamDefault]; } } return false; @@ -151,15 +151,15 @@ stock ClassGetFlags(index, cachetype = ZR_CLASS_CACHE_MODIFIED) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_flags]; + return ClassData[index][Class_Flags]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_flags]; + return ClassDataCache[index][Class_Flags]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_flags]; + return ClassPlayerCache[index][Class_Flags]; } } return -1; @@ -185,20 +185,55 @@ stock bool:ClassHasFlags(index, flags, cachetype = ZR_CLASS_CACHE_MODIFIED) { case ZR_CLASS_CACHE_ORIGINAL: { - return bool:(ClassData[index][class_flags] & flags); + return bool:(ClassData[index][Class_Flags] & flags); } case ZR_CLASS_CACHE_MODIFIED: { - return bool:(ClassDataCache[index][class_flags] & flags); + return bool:(ClassDataCache[index][Class_Flags] & flags); } case ZR_CLASS_CACHE_PLAYER: { - return bool:(ClassPlayerCache[index][class_flags] & flags); + return bool:(ClassPlayerCache[index][Class_Flags] & flags); } } return false; } +/** + * Gets the class group required to be a member of to use the class. + * + * @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 what class cache to read from. Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED - Changed/newest class data. + * ZR_CLASS_CACHE_PLAYER (default) - Player cache. If this one + * is used, index will be used as a client index. + * @return Number of cells written. -1 on error. + */ +stock ClassGetGroup(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) +{ + switch (cachetype) + { + case ZR_CLASS_CACHE_ORIGINAL: + { + return strcopy(buffer, maxlen, ClassData[index][Class_Group]); + } + case ZR_CLASS_CACHE_MODIFIED: + { + return strcopy(buffer, maxlen, ClassDataCache[index][Class_Group]); + } + case ZR_CLASS_CACHE_PLAYER: + { + return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_Group]); + } + } + + return -1; +} + /** * Gets the class name to be displayed in the class menu. * @@ -219,15 +254,15 @@ stock ClassGetName(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PL { case ZR_CLASS_CACHE_ORIGINAL: { - return strcopy(buffer, maxlen, ClassData[index][class_name]); + return strcopy(buffer, maxlen, ClassData[index][Class_Name]); } case ZR_CLASS_CACHE_MODIFIED: { - return strcopy(buffer, maxlen, ClassDataCache[index][class_name]); + return strcopy(buffer, maxlen, ClassDataCache[index][Class_Name]); } case ZR_CLASS_CACHE_PLAYER: { - return strcopy(buffer, maxlen, ClassPlayerCache[index][class_name]); + return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_Name]); } } @@ -254,15 +289,15 @@ stock ClassGetDescription(index, String:buffer[], maxlen, cachetype = ZR_CLASS_C { case ZR_CLASS_CACHE_ORIGINAL: { - return strcopy(buffer, maxlen, ClassData[index][class_description]); + return strcopy(buffer, maxlen, ClassData[index][Class_Description]); } case ZR_CLASS_CACHE_MODIFIED: { - return strcopy(buffer, maxlen, ClassDataCache[index][class_description]); + return strcopy(buffer, maxlen, ClassDataCache[index][Class_Description]); } case ZR_CLASS_CACHE_PLAYER: { - return strcopy(buffer, maxlen, ClassPlayerCache[index][class_description]); + return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_Description]); } } return -1; @@ -298,15 +333,15 @@ stock ClassGetModelPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CAC { case ZR_CLASS_CACHE_ORIGINAL: { - return strcopy(buffer, maxlen, ClassData[index][class_model_path]); + return strcopy(buffer, maxlen, ClassData[index][Class_ModelPath]); } case ZR_CLASS_CACHE_MODIFIED: { - return strcopy(buffer, maxlen, ClassDataCache[index][class_model_path]); + return strcopy(buffer, maxlen, ClassDataCache[index][Class_ModelPath]); } case ZR_CLASS_CACHE_PLAYER: { - return strcopy(buffer, maxlen, ClassPlayerCache[index][class_model_path]); + return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_ModelPath]); } } return -1; @@ -330,15 +365,15 @@ stock ClassGetAlphaInitial(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_alpha_initial]; + return ClassData[index][Class_AlphaInitial]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_alpha_initial]; + return ClassDataCache[index][Class_AlphaInitial]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_alpha_initial]; + return ClassPlayerCache[index][Class_AlphaInitial]; } } return -1; @@ -363,15 +398,15 @@ stock ClassGetAlphaDamaged(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_alpha_damaged]; + return ClassData[index][Class_AlphaDamaged]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_alpha_damaged]; + return ClassDataCache[index][Class_AlphaDamaged]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_alpha_damaged]; + return ClassPlayerCache[index][Class_AlphaDamaged]; } } return -1; @@ -396,15 +431,15 @@ stock ClassGetAlphaDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_alpha_damage]; + return ClassData[index][Class_AlphaDamage]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_alpha_damage]; + return ClassDataCache[index][Class_AlphaDamage]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_alpha_damage]; + return ClassPlayerCache[index][Class_AlphaDamage]; } } return -1; @@ -440,15 +475,15 @@ stock ClassGetOverlayPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_C { case ZR_CLASS_CACHE_ORIGINAL: { - return strcopy(buffer, maxlen, ClassData[index][class_overlay_path]); + return strcopy(buffer, maxlen, ClassData[index][Class_OverlayPath]); } case ZR_CLASS_CACHE_MODIFIED: { - return strcopy(buffer, maxlen, ClassDataCache[index][class_overlay_path]); + return strcopy(buffer, maxlen, ClassDataCache[index][Class_OverlayPath]); } case ZR_CLASS_CACHE_PLAYER: { - return strcopy(buffer, maxlen, ClassPlayerCache[index][class_overlay_path]); + return strcopy(buffer, maxlen, ClassPlayerCache[index][Class_OverlayPath]); } } return -1; @@ -472,15 +507,15 @@ stock bool:ClassGetNvgs(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_nvgs]; + return ClassData[index][Class_Nvgs]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_nvgs]; + return ClassDataCache[index][Class_Nvgs]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_nvgs]; + return ClassPlayerCache[index][Class_Nvgs]; } } return false; @@ -504,15 +539,15 @@ stock ClassGetFOV(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_fov]; + return ClassData[index][Class_Fov]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_fov]; + return ClassDataCache[index][Class_Fov]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_fov]; + return ClassPlayerCache[index][Class_Fov]; } } return -1; @@ -546,15 +581,15 @@ stock bool:ClassGetHasNapalm(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_has_napalm]; + return ClassData[index][Class_HasNapalm]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_has_napalm]; + return ClassDataCache[index][Class_HasNapalm]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_has_napalm]; + return ClassPlayerCache[index][Class_HasNapalm]; } } return false; @@ -580,15 +615,15 @@ stock Float:ClassGetNapalmTime(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_napalm_time]; + return ClassData[index][Class_NapalmTime]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_napalm_time]; + return ClassDataCache[index][Class_NapalmTime]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_napalm_time] * ClassGetAttributeMultiplier(index, ClassM_NapalmTime); + return ClassPlayerCache[index][Class_NapalmTime] * ClassGetAttributeMultiplier(index, ClassM_NapalmTime); } } return -1.0; @@ -622,15 +657,15 @@ stock ClassGetImmunityMode(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_immunity_mode]; + return ClassData[index][Class_ImmunityMode]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_immunity_mode]; + return ClassDataCache[index][Class_ImmunityMode]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_immunity_mode]; + return ClassPlayerCache[index][Class_ImmunityMode]; } } return -1; @@ -654,15 +689,15 @@ stock Float:ClassGetImmunityAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_immunity_amount]; + return ClassData[index][Class_ImmunityAmount]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_immunity_amount]; + return ClassDataCache[index][Class_ImmunityAmount]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_immunity_amount]; + return ClassPlayerCache[index][Class_ImmunityAmount]; } } return -1.0; @@ -687,15 +722,15 @@ stock bool:ClassGetNoFallDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_no_fall_damage]; + return ClassData[index][Class_NoFallDamage]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_no_fall_damage]; + return ClassDataCache[index][Class_NoFallDamage]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_no_fall_damage]; + return ClassPlayerCache[index][Class_NoFallDamage]; } } return false; @@ -721,15 +756,15 @@ stock ClassGetHealth(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_health]; + return ClassData[index][Class_Health]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_health]; + return ClassDataCache[index][Class_Health]; } case ZR_CLASS_CACHE_PLAYER: { - return RoundToCeil(ClassPlayerCache[index][class_health] * ClassGetAttributeMultiplier(index, ClassM_Health)); + return RoundToCeil(ClassPlayerCache[index][Class_Health] * ClassGetAttributeMultiplier(index, ClassM_Health)); } } return -1; @@ -756,15 +791,15 @@ stock Float:ClassGetHealthRegenInterval(index, cachetype = ZR_CLASS_CACHE_PLAYER { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_health_regen_interval]; + return ClassData[index][Class_HealthRegenInterval]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_health_regen_interval]; + return ClassDataCache[index][Class_HealthRegenInterval]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_health_regen_interval] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenInterval); + return ClassPlayerCache[index][Class_HealthRegenInterval] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenInterval); } } return -1.0; @@ -791,15 +826,15 @@ stock ClassGetHealthRegenAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_health_regen_amount]; + return ClassData[index][Class_HealthRegenAmount]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_health_regen_amount]; + return ClassDataCache[index][Class_HealthRegenAmount]; } case ZR_CLASS_CACHE_PLAYER: { - return RoundToCeil(ClassPlayerCache[index][class_health_regen_amount] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenAmount)); + return RoundToCeil(ClassPlayerCache[index][Class_HealthRegenAmount] * ClassGetAttributeMultiplier(index, ClassM_HealthRegenAmount)); } } return -1; @@ -826,15 +861,15 @@ stock ClassGetHealthInfectGain(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_health_infect_gain]; + return ClassData[index][Class_HealthInfectGain]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_health_infect_gain]; + return ClassDataCache[index][Class_HealthInfectGain]; } case ZR_CLASS_CACHE_PLAYER: { - return RoundToCeil(ClassPlayerCache[index][class_health_infect_gain] * ClassGetAttributeMultiplier(index, ClassM_HealthInfectGain)); + return RoundToCeil(ClassPlayerCache[index][Class_HealthInfectGain] * ClassGetAttributeMultiplier(index, ClassM_HealthInfectGain)); } } return -1; @@ -858,15 +893,15 @@ stock ClassGetKillBonus(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_kill_bonus]; + return ClassData[index][Class_KillBonus]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_kill_bonus]; + return ClassDataCache[index][Class_KillBonus]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_kill_bonus]; + return ClassPlayerCache[index][Class_KillBonus]; } } return -1; @@ -892,15 +927,15 @@ stock Float:ClassGetSpeed(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_speed]; + return ClassData[index][Class_Speed]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_speed]; + return ClassDataCache[index][Class_Speed]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_speed] * ClassGetAttributeMultiplier(index, ClassM_Speed); + return ClassPlayerCache[index][Class_Speed] * ClassGetAttributeMultiplier(index, ClassM_Speed); } } return -1.0; @@ -926,15 +961,15 @@ stock Float:ClassGetKnockback(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_knockback]; + return ClassData[index][Class_KnockBack]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_knockback]; + return ClassDataCache[index][Class_KnockBack]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_knockback] * ClassGetAttributeMultiplier(index, ClassM_Knockback); + return ClassPlayerCache[index][Class_KnockBack] * ClassGetAttributeMultiplier(index, ClassM_Knockback); } } return 0.0; @@ -960,15 +995,15 @@ stock Float:ClassGetJumpHeight(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_jump_height]; + return ClassData[index][Class_JumpHeight]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_jump_height]; + return ClassDataCache[index][Class_JumpHeight]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_jump_height] * ClassGetAttributeMultiplier(index, ClassM_JumpHeight); + return ClassPlayerCache[index][Class_JumpHeight] * ClassGetAttributeMultiplier(index, ClassM_JumpHeight); } } return -1.0; @@ -994,15 +1029,15 @@ stock Float:ClassGetJumpDistance(index, cachetype = ZR_CLASS_CACHE_PLAYER) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_jump_distance]; + return ClassData[index][Class_JumpDistance]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_jump_distance]; + return ClassDataCache[index][Class_JumpDistance]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_jump_distance] * ClassGetAttributeMultiplier(index, ClassM_JumpDistance); + return ClassPlayerCache[index][Class_JumpDistance] * ClassGetAttributeMultiplier(index, ClassM_JumpDistance); } } return -1.0; @@ -1034,6 +1069,10 @@ stock ClassAttributeNameToFlag(const String:attributename[]) { return ZR_CLASS_FLAGS; } + else if (StrEqual(attributename, "group", false)) + { + return ZR_CLASS_GROUP; + } else if (StrEqual(attributename, "name", false)) { return ZR_CLASS_NAME; @@ -1230,7 +1269,8 @@ stock ClassDataTypes:ClassGetAttributeType(attributeflag) } // String. - case ZR_CLASS_NAME, + case ZR_CLASS_GROUP, + ZR_CLASS_NAME, ZR_CLASS_DESCRIPTION, ZR_CLASS_MODEL_PATH, ZR_CLASS_OVERLAY_PATH: diff --git a/src/zr/playerclasses/classcommands.inc b/src/zr/playerclasses/classcommands.inc index 22286fe..0405bce 100644 --- a/src/zr/playerclasses/classcommands.inc +++ b/src/zr/playerclasses/classcommands.inc @@ -619,22 +619,22 @@ stock bool:ClassModifyBoolean(classindex, attributeflag, bool:value) { case ZR_CLASS_ENABLED: { - ClassDataCache[classindex][class_enabled] = bool:value; + ClassDataCache[classindex][Class_Enabled] = bool:value; return true; } case ZR_CLASS_NVGS: { - ClassDataCache[classindex][class_nvgs] = bool:value; + ClassDataCache[classindex][Class_Nvgs] = bool:value; return true; } case ZR_CLASS_NO_FALL_DAMAGE: { - ClassDataCache[classindex][class_no_fall_damage] = bool:value; + ClassDataCache[classindex][Class_NoFallDamage] = bool:value; return true; } case ZR_CLASS_HAS_NAPALM: { - ClassDataCache[classindex][class_has_napalm] = bool:value; + ClassDataCache[classindex][Class_HasNapalm] = bool:value; return true; } } @@ -670,80 +670,80 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. { case ZR_CLASS_FLAGS: { - ClassDataCache[classindex][class_flags] = value; + ClassDataCache[classindex][Class_Flags] = value; return true; } case ZR_CLASS_ALPHA_INITIAL: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_alpha_initial]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_AlphaInitial]) * multiplier); } - ClassDataCache[classindex][class_alpha_initial] = value; + ClassDataCache[classindex][Class_AlphaInitial] = value; return true; } case ZR_CLASS_ALPHA_DAMAGED: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_alpha_damaged]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_AlphaDamaged]) * multiplier); } - ClassDataCache[classindex][class_alpha_damaged] = value; + ClassDataCache[classindex][Class_AlphaDamaged] = value; return true; } case ZR_CLASS_ALPHA_DAMAGE: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_alpha_damage]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_AlphaDamage]) * multiplier); } - ClassDataCache[classindex][class_alpha_damage] = value; + ClassDataCache[classindex][Class_AlphaDamage] = value; return true; } case ZR_CLASS_FOV: { - ClassDataCache[classindex][class_fov] = value; + ClassDataCache[classindex][Class_Fov] = value; return true; } case ZR_CLASS_IMMUNITY_MODE: { - ClassDataCache[classindex][class_fov] = value; + ClassDataCache[classindex][Class_ImmunityMode] = value; return true; } case ZR_CLASS_HEALTH: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_health]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_Health]) * multiplier); } - ClassDataCache[classindex][class_health] = value; + ClassDataCache[classindex][Class_Health] = value; return true; } case ZR_CLASS_HEALTH_REGEN_AMOUNT: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_health_regen_amount]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_HealthRegenAmount]) * multiplier); } - ClassDataCache[classindex][class_health_regen_amount] = value; + ClassDataCache[classindex][Class_HealthRegenAmount] = value; return true; } case ZR_CLASS_HEALTH_INFECT_GAIN: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_health_infect_gain]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_HealthInfectGain]) * multiplier); } - ClassDataCache[classindex][class_health_infect_gain] = value; + ClassDataCache[classindex][Class_HealthInfectGain] = value; return true; } case ZR_CLASS_KILL_BONUS: { if (ismultiplier) { - value = RoundToNearest(float(ClassData[classindex][class_kill_bonus]) * multiplier); + value = RoundToNearest(float(ClassData[classindex][Class_KillBonus]) * multiplier); } - ClassDataCache[classindex][class_kill_bonus] = value; + ClassDataCache[classindex][Class_KillBonus] = value; return true; } } @@ -777,63 +777,63 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier { if (ismultiplier) { - value = ClassData[classindex][class_napalm_time] * value; + value = ClassData[classindex][Class_NapalmTime] * value; } - ClassDataCache[classindex][class_napalm_time] = value; + ClassDataCache[classindex][Class_NapalmTime] = value; return true; } case ZR_CLASS_IMMUNITY_AMOUNT: { if (ismultiplier) { - value = ClassData[classindex][class_immunity_amount] * value; + value = ClassData[classindex][Class_ImmunityAmount] * value; } - ClassDataCache[classindex][class_immunity_amount] = value; + ClassDataCache[classindex][Class_ImmunityAmount] = value; return true; } case ZR_CLASS_HEALTH_REGEN_INTERVAL: { if (ismultiplier) { - value = ClassData[classindex][class_health_regen_interval] * value; + value = ClassData[classindex][Class_HealthRegenInterval] * value; } - ClassDataCache[classindex][class_health_regen_interval] = value; + ClassDataCache[classindex][Class_HealthRegenInterval] = value; return true; } case ZR_CLASS_SPEED: { if (ismultiplier) { - value = ClassData[classindex][class_speed] * value; + value = ClassData[classindex][Class_Speed] * value; } - ClassDataCache[classindex][class_speed] = value; + ClassDataCache[classindex][Class_Speed] = value; return true; } case ZR_CLASS_KNOCKBACK: { if (ismultiplier) { - value = ClassData[classindex][class_knockback] * value; + value = ClassData[classindex][Class_KnockBack] * value; } - ClassDataCache[classindex][class_knockback] = value; + ClassDataCache[classindex][Class_KnockBack] = value; return true; } case ZR_CLASS_JUMP_HEIGHT: { if (ismultiplier) { - value = ClassData[classindex][class_jump_height] * value; + value = ClassData[classindex][Class_JumpHeight] * value; } - ClassDataCache[classindex][class_jump_height] = value; + ClassDataCache[classindex][Class_JumpHeight] = value; return true; } case ZR_CLASS_JUMP_DISTANCE: { if (ismultiplier) { - value = ClassData[classindex][class_jump_distance] * value; + value = ClassData[classindex][Class_JumpDistance] * value; } - ClassDataCache[classindex][class_jump_distance] = value; + ClassDataCache[classindex][Class_JumpDistance] = value; return true; } } @@ -860,24 +860,29 @@ stock ClassModifyString(classindex, attributeflag, const String:value[]) switch (attributeflag) { + case ZR_CLASS_GROUP: + { + strcopy(ClassDataCache[classindex][Class_Group], 64, value); + return true; + } case ZR_CLASS_NAME: { - strcopy(ClassDataCache[classindex][class_name], 64, value); + strcopy(ClassDataCache[classindex][Class_Name], 64, value); return true; } case ZR_CLASS_DESCRIPTION: { - strcopy(ClassDataCache[classindex][class_description], 256, value); + strcopy(ClassDataCache[classindex][Class_Description], 256, value); return true; } case ZR_CLASS_MODEL_PATH: { - strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, value); + strcopy(ClassDataCache[classindex][Class_ModelPath], PLATFORM_MAX_PATH, value); return true; } case ZR_CLASS_OVERLAY_PATH: { - strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, value); + strcopy(ClassDataCache[classindex][Class_OverlayPath], PLATFORM_MAX_PATH, value); return true; } } diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index 4c53ae6..ecfbfe9 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -107,26 +107,29 @@ stock ClassValidateAttributes(classindex) new flags; // Team. - if (ClassData[classindex][class_team] < ZR_CLASS_TEAM_MIN || ClassData[classindex][class_team] > ZR_CLASS_TEAM_MAX) + if (ClassData[classindex][Class_Team] < ZR_CLASS_TEAM_MIN || ClassData[classindex][Class_Team] > ZR_CLASS_TEAM_MAX) { flags += ZR_CLASS_TEAM; } // Class flags. - if (ClassData[classindex][class_flags] < ZR_CLASS_FLAGS_MIN || ClassData[classindex][class_flags] > ZR_CLASS_FLAGS_MAX) + if (ClassData[classindex][Class_Flags] < ZR_CLASS_FLAGS_MIN || ClassData[classindex][Class_Flags] > ZR_CLASS_FLAGS_MAX) { flags += ZR_CLASS_FLAGS; } + // Group. + + // Name. - if (strlen(ClassData[classindex][class_name]) < ZR_CLASS_NAME_MIN) + if (strlen(ClassData[classindex][Class_Name]) < ZR_CLASS_NAME_MIN) { flags += ZR_CLASS_NAME; } else { decl String:name[64]; - strcopy(name, sizeof(name), ClassData[classindex][class_name]); + strcopy(name, sizeof(name), ClassData[classindex][Class_Name]); // Check for reserved name keyworks. These aren't allowed as names. if (StrEqual(name, "all", false) || @@ -139,14 +142,14 @@ stock ClassValidateAttributes(classindex) } // Description. - if (strlen(ClassData[classindex][class_description]) < ZR_CLASS_DESCRIPTION_MIN) + if (strlen(ClassData[classindex][Class_Description]) < ZR_CLASS_DESCRIPTION_MIN) { flags += ZR_CLASS_DESCRIPTION; } // Model path. decl String:model_path[PLATFORM_MAX_PATH]; - if (strcopy(model_path, sizeof(model_path), ClassData[classindex][class_model_path]) == 0) + if (strcopy(model_path, sizeof(model_path), ClassData[classindex][Class_ModelPath]) == 0) { flags += ZR_CLASS_MODEL_PATH; } @@ -164,21 +167,21 @@ stock ClassValidateAttributes(classindex) } // Alpha, initial. - new alpha_initial = ClassData[classindex][class_alpha_initial]; + new alpha_initial = ClassData[classindex][Class_AlphaInitial]; if (!(alpha_initial >= ZR_CLASS_ALPHA_INITIAL_MIN && alpha_initial <= ZR_CLASS_ALPHA_INITIAL_MAX)) { flags += ZR_CLASS_ALPHA_INITIAL; } // Alpha, damaged. - new alpha_damaged = ClassData[classindex][class_alpha_damaged]; + new alpha_damaged = ClassData[classindex][Class_AlphaDamaged]; if (!(alpha_damaged >= ZR_CLASS_ALPHA_DAMAGED_MIN && alpha_damaged <= ZR_CLASS_ALPHA_DAMAGED_MAX)) { flags += ZR_CLASS_ALPHA_DAMAGED; } // Alpha, damage. - new alpha_damage = ClassData[classindex][class_alpha_damage]; + new alpha_damage = ClassData[classindex][Class_AlphaDamage]; if (!(alpha_damage >= ZR_CLASS_ALPHA_DAMAGE_MIN && alpha_damage <= ZR_CLASS_ALPHA_DAMAGE_MAX)) { flags += ZR_CLASS_ALPHA_DAMAGE; @@ -187,7 +190,7 @@ stock ClassValidateAttributes(classindex) // Overlay path. decl String:overlay_path[PLATFORM_MAX_PATH]; decl String:overlay[PLATFORM_MAX_PATH]; - if (strcopy(overlay_path, sizeof(overlay_path), ClassData[classindex][class_overlay_path]) > 0) + if (strcopy(overlay_path, sizeof(overlay_path), ClassData[classindex][Class_OverlayPath]) > 0) { // Check if the file exists. Format(overlay, sizeof(overlay), "materials/%s.vmt", overlay_path); @@ -198,77 +201,80 @@ stock ClassValidateAttributes(classindex) } // Field of view. - new fov = ClassData[classindex][class_fov]; + new fov = ClassData[classindex][Class_Fov]; if (!(fov >= ZR_CLASS_FOV_MIN && fov <= ZR_CLASS_FOV_MAX)) { flags += ZR_CLASS_FOV; } // Napalm time. - new Float:napalm_time = ClassData[classindex][class_napalm_time]; + new Float:napalm_time = ClassData[classindex][Class_NapalmTime]; if (!(napalm_time >= ZR_CLASS_NAPALM_TIME_MIN && napalm_time <= ZR_CLASS_NAPALM_TIME_MAX)) { flags += ZR_CLASS_NAPALM_TIME; } + // Immunity mode (not implemented). + + // Health. - new health = ClassData[classindex][class_health]; + new health = ClassData[classindex][Class_Health]; if (!(health >= ZR_CLASS_HEALTH_MIN && health <= ZR_CLASS_HEALTH_MAX)) { flags += ZR_CLASS_HEALTH; } // Health regen interval. - new Float:regen_interval = ClassData[classindex][class_health_regen_interval]; + new Float:regen_interval = ClassData[classindex][Class_HealthRegenInterval]; if (!(regen_interval >= ZR_CLASS_REGEN_INTERVAL_MIN && regen_interval <= ZR_CLASS_REGEN_INTERVAL_MAX)) { flags += ZR_CLASS_HEALTH_REGEN_INTERVAL; } // Health regen amount. - new regen_amount = ClassData[classindex][class_health_regen_amount]; + new regen_amount = ClassData[classindex][Class_HealthRegenAmount]; if (!(regen_amount >= ZR_CLASS_REGEN_AMOUNT_MIN && regen_amount <= ZR_CLASS_REGEN_AMOUNT_MAX)) { flags += ZR_CLASS_HEALTH_REGEN_AMOUNT; } // Health infect gain. - new infect_gain = ClassData[classindex][class_health_infect_gain]; + new infect_gain = ClassData[classindex][Class_HealthInfectGain]; if (!(infect_gain >= ZR_CLASS_HEALTH_INFECT_GAIN_MIN && infect_gain <= ZR_CLASS_HEALTH_INFECT_GAIN_MAX)) { flags += ZR_CLASS_HEALTH_INFECT_GAIN; } // Kill bonus. - new kill_bonus = ClassData[classindex][class_kill_bonus]; + new kill_bonus = ClassData[classindex][Class_KillBonus]; if (!(kill_bonus >= ZR_CLASS_KILL_BONUS_MIN && kill_bonus <= ZR_CLASS_KILL_BONUS_MAX)) { flags += ZR_CLASS_KILL_BONUS; } // Speed. - new Float:speed = ClassData[classindex][class_speed]; + new Float:speed = ClassData[classindex][Class_Speed]; if (!(speed >= ZR_CLASS_SPEED_MIN && speed <= ZR_CLASS_SPEED_MAX)) { flags += ZR_CLASS_SPEED; } // Knockback. - new Float:knockback = ClassData[classindex][class_knockback]; + new Float:knockback = ClassData[classindex][Class_KnockBack]; if (!(knockback >= ZR_CLASS_KNOCKBACK_MIN && knockback <= ZR_CLASS_KNOCKBACK_MAX)) { flags += ZR_CLASS_KNOCKBACK; } // Jump height. - new Float:jump_height = ClassData[classindex][class_jump_height]; + new Float:jump_height = ClassData[classindex][Class_JumpHeight]; if (!(jump_height >= ZR_CLASS_JUMP_HEIGHT_MIN && jump_height <= ZR_CLASS_JUMP_HEIGHT_MAX)) { flags += ZR_CLASS_JUMP_HEIGHT; } // Jump distance. - new Float:jump_distance = ClassData[classindex][class_jump_distance]; + new Float:jump_distance = ClassData[classindex][Class_JumpDistance]; if (!(jump_distance >= ZR_CLASS_JUMP_DISTANCE_MIN && jump_distance <= ZR_CLASS_JUMP_DISTANCE_MAX)) { flags += ZR_CLASS_JUMP_DISTANCE; @@ -315,21 +321,21 @@ stock bool:ClassTeamCompare(index, teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) { case ZR_CLASS_CACHE_ORIGINAL: { - if (ClassData[index][class_team] == teamid) + if (ClassData[index][Class_Team] == teamid) { return true; } } case ZR_CLASS_CACHE_MODIFIED: { - if (ClassDataCache[index][class_team] == teamid) + if (ClassDataCache[index][Class_Team] == teamid) { return true; } } case ZR_CLASS_CACHE_PLAYER: { - if (ClassPlayerCache[index][class_team] == teamid) + if (ClassPlayerCache[index][Class_Team] == teamid) { return true; } diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 05ddf75..4137d3e 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -31,7 +31,7 @@ - Zombies have to hurt humans so they loose hp. When the hp reach zero (or below) they turn into zombies. - Fully imune to all damage. Can't take or give damage. Sould only be used - on admin classes. + on admin mode classes. TODO: Make class attributes for for changing model render mode and colors. @@ -104,6 +104,7 @@ #define ZR_CLASS_DEFAULT_TEAM ZR_CLASS_TEAM_ZOMBIES #define ZR_CLASS_DEFAULT_TEAM_DEFAULT true #define ZR_CLASS_DEFAULT_FLAGS 0 +#define ZR_CLASS_DEFAULT_GROUP "" #define ZR_CLASS_DEFAULT_NAME "classic" #define ZR_CLASS_DEFAULT_DESCRIPTION "Need brains!!! Arrrrggghh!" #define ZR_CLASS_DEFAULT_MODEL_PATH "models/player/zh/zh_zombie003.mdl" @@ -181,77 +182,94 @@ #define ZR_CLASS_TEAM (1<<1) #define ZR_CLASS_TEAM_DEFAULT (1<<2) #define ZR_CLASS_FLAGS (1<<3) -#define ZR_CLASS_NAME (1<<4) -#define ZR_CLASS_DESCRIPTION (1<<5) -#define ZR_CLASS_MODEL_PATH (1<<6) -#define ZR_CLASS_ALPHA_INITIAL (1<<7) -#define ZR_CLASS_ALPHA_DAMAGED (1<<8) -#define ZR_CLASS_ALPHA_DAMAGE (1<<9) -#define ZR_CLASS_OVERLAY_PATH (1<<10) -#define ZR_CLASS_NVGS (1<<11) -#define ZR_CLASS_FOV (1<<12) -#define ZR_CLASS_HAS_NAPALM (1<<13) -#define ZR_CLASS_NAPALM_TIME (1<<14) -#define ZR_CLASS_IMMUNITY_MODE (1<<15) -#define ZR_CLASS_IMMUNITY_AMOUNT (1<<16) -#define ZR_CLASS_NO_FALL_DAMAGE (1<<17) -#define ZR_CLASS_HEALTH (1<<18) -#define ZR_CLASS_HEALTH_REGEN_INTERVAL (1<<19) -#define ZR_CLASS_HEALTH_REGEN_AMOUNT (1<<20) -#define ZR_CLASS_HEALTH_INFECT_GAIN (1<<21) -#define ZR_CLASS_KILL_BONUS (1<<22) -#define ZR_CLASS_SPEED (1<<23) -#define ZR_CLASS_KNOCKBACK (1<<24) -#define ZR_CLASS_JUMP_HEIGHT (1<<25) -#define ZR_CLASS_JUMP_DISTANCE (1<<26) +#define ZR_CLASS_GROUP (1<<4) +#define ZR_CLASS_NAME (1<<5) +#define ZR_CLASS_DESCRIPTION (1<<6) +#define ZR_CLASS_MODEL_PATH (1<<7) +#define ZR_CLASS_ALPHA_INITIAL (1<<8) +#define ZR_CLASS_ALPHA_DAMAGED (1<<9) +#define ZR_CLASS_ALPHA_DAMAGE (1<<10) +#define ZR_CLASS_OVERLAY_PATH (1<<11) +#define ZR_CLASS_NVGS (1<<12) +#define ZR_CLASS_FOV (1<<13) +#define ZR_CLASS_HAS_NAPALM (1<<14) +#define ZR_CLASS_NAPALM_TIME (1<<15) +#define ZR_CLASS_IMMUNITY_MODE (1<<16) +#define ZR_CLASS_IMMUNITY_AMOUNT (1<<17) +#define ZR_CLASS_NO_FALL_DAMAGE (1<<18) +#define ZR_CLASS_HEALTH (1<<19) +#define ZR_CLASS_HEALTH_REGEN_INTERVAL (1<<20) +#define ZR_CLASS_HEALTH_REGEN_AMOUNT (1<<21) +#define ZR_CLASS_HEALTH_INFECT_GAIN (1<<22) +#define ZR_CLASS_KILL_BONUS (1<<23) +#define ZR_CLASS_SPEED (1<<24) +#define ZR_CLASS_KNOCKBACK (1<<25) +#define ZR_CLASS_JUMP_HEIGHT (1<<26) +#define ZR_CLASS_JUMP_DISTANCE (1<<27) /** * @endsection */ /** * Generic player attributes. + * + * Stuff that must be updated when new attributes are added: + * ZR_CLASS_DEFAULT_... define + * ZR_CLASS_..._MAX/MIN defines + * ZR_CLASS_... define (place in same order as listed in ClassAttributes, bump bit numbers + update numbers in docs) + * ClassLoad + * ClassReloadDataCache + * ClassReloadPlayerCache + * ClassDumpData + * attributes.inc - Add new Get-function + * ClassAttributeNameToFlag + * ClassGetAttributeType + * ClassValidateAttributes + * ClassModify* in classcommands.inc + * Update docs with detailed attribute description */ enum ClassAttributes { /* General */ - bool:class_enabled, - class_team, - bool:class_team_default, - class_flags, + bool:Class_Enabled, + Class_Team, + bool:Class_TeamDefault, + Class_Flags, + String:Class_Group[64], - String:class_name[64], - String:class_description[256], + String:Class_Name[64], + String:Class_Description[256], /* Model */ - String:class_model_path[PLATFORM_MAX_PATH], - class_alpha_initial, - class_alpha_damaged, - class_alpha_damage, + String:Class_ModelPath[PLATFORM_MAX_PATH], + Class_AlphaInitial, + Class_AlphaDamaged, + Class_AlphaDamage, /* Hud */ - String:class_overlay_path[PLATFORM_MAX_PATH], - bool:class_nvgs, - class_fov, + String:Class_OverlayPath[PLATFORM_MAX_PATH], + bool:Class_Nvgs, + Class_Fov, /* Effects */ - bool:class_has_napalm, - Float:class_napalm_time, + bool:Class_HasNapalm, + Float:Class_NapalmTime, /* Player behaviour */ - class_immunity_mode, - Float:class_immunity_amount, - bool:class_no_fall_damage, + Class_ImmunityMode, + Float:Class_ImmunityAmount, + bool:Class_NoFallDamage, - class_health, - Float:class_health_regen_interval, - class_health_regen_amount, - class_health_infect_gain, - class_kill_bonus, + Class_Health, + Float:Class_HealthRegenInterval, + Class_HealthRegenAmount, + Class_HealthInfectGain, + Class_KillBonus, - Float:class_speed, - Float:class_knockback, - Float:class_jump_height, - Float:class_jump_distance + Float:Class_Speed, + Float:Class_KnockBack, + Float:Class_JumpHeight, + Float:Class_JumpDistance } /** @@ -435,6 +453,7 @@ ClassLoad(bool:keepMultipliers = false) } decl String:name[64]; + decl String:group[64]; decl String:description[256]; decl String:model_path[PLATFORM_MAX_PATH]; decl String:overlay_path[PLATFORM_MAX_PATH]; @@ -455,55 +474,58 @@ ClassLoad(bool:keepMultipliers = false) } /* General */ - ClassData[ClassCount][class_enabled] = bool:KvGetNum(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED); - ClassData[ClassCount][class_team] = KvGetNum(kvClassData, "team", ZR_CLASS_DEFAULT_TEAM); - ClassData[ClassCount][class_team_default] = bool:KvGetNum(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT); - ClassData[ClassCount][class_flags] = KvGetNum(kvClassData, "flags", ZR_CLASS_DEFAULT_FLAGS); + ClassData[ClassCount][Class_Enabled] = bool:KvGetNum(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED); + ClassData[ClassCount][Class_Team] = KvGetNum(kvClassData, "team", ZR_CLASS_DEFAULT_TEAM); + ClassData[ClassCount][Class_TeamDefault] = bool:KvGetNum(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT); + ClassData[ClassCount][Class_Flags] = KvGetNum(kvClassData, "flags", ZR_CLASS_DEFAULT_FLAGS); + + KvGetString(kvClassData, "group", group, sizeof(group), ZR_CLASS_DEFAULT_GROUP); + strcopy(ClassData[ClassCount][Class_Group], 64, group); KvGetString(kvClassData, "name", name, sizeof(name), ZR_CLASS_DEFAULT_NAME); - strcopy(ClassData[ClassCount][class_name], 64, name); + strcopy(ClassData[ClassCount][Class_Name], 64, name); KvGetString(kvClassData, "description", description, sizeof(description), ZR_CLASS_DEFAULT_DESCRIPTION); - strcopy(ClassData[ClassCount][class_description], 256, description); + strcopy(ClassData[ClassCount][Class_Description], 256, description); /* Model */ KvGetString(kvClassData, "model_path", model_path, sizeof(model_path), ZR_CLASS_DEFAULT_MODEL_PATH); - strcopy(ClassData[ClassCount][class_model_path], PLATFORM_MAX_PATH, model_path); + strcopy(ClassData[ClassCount][Class_ModelPath], PLATFORM_MAX_PATH, model_path); - ClassData[ClassCount][class_alpha_initial] = KvGetNum(kvClassData, "alpha_initial", ZR_CLASS_DEFAULT_ALPHA_INITIAL); - ClassData[ClassCount][class_alpha_damaged] = KvGetNum(kvClassData, "alpha_damaged", ZR_CLASS_DEFAULT_ALPHA_DAMAGED); - ClassData[ClassCount][class_alpha_damage] = KvGetNum(kvClassData, "alpha_damage", ZR_CLASS_DEFAULT_ALPHA_DAMAGE); + ClassData[ClassCount][Class_AlphaInitial] = KvGetNum(kvClassData, "alpha_initial", ZR_CLASS_DEFAULT_ALPHA_INITIAL); + ClassData[ClassCount][Class_AlphaDamaged] = KvGetNum(kvClassData, "alpha_damaged", ZR_CLASS_DEFAULT_ALPHA_DAMAGED); + ClassData[ClassCount][Class_AlphaDamage] = KvGetNum(kvClassData, "alpha_damage", ZR_CLASS_DEFAULT_ALPHA_DAMAGE); /* Hud */ KvGetString(kvClassData, "overlay_path", overlay_path, sizeof(overlay_path), ZR_CLASS_DEFAULT_OVERLAY_PATH); - strcopy(ClassData[ClassCount][class_overlay_path], PLATFORM_MAX_PATH, overlay_path); + strcopy(ClassData[ClassCount][Class_OverlayPath], PLATFORM_MAX_PATH, overlay_path); - ClassData[ClassCount][class_nvgs] = bool:KvGetNum(kvClassData, "nvgs", ZR_CLASS_DEFAULT_NVGS); - ClassData[ClassCount][class_fov] = KvGetNum(kvClassData, "fov", ZR_CLASS_DEFAULT_FOV); + ClassData[ClassCount][Class_Nvgs] = bool:KvGetNum(kvClassData, "nvgs", ZR_CLASS_DEFAULT_NVGS); + ClassData[ClassCount][Class_Fov] = KvGetNum(kvClassData, "fov", ZR_CLASS_DEFAULT_FOV); /* Effects */ - ClassData[ClassCount][class_has_napalm] = bool:KvGetNum(kvClassData, "have_napalm", ZR_CLASS_DEFAULT_HAS_NAPALM); - ClassData[ClassCount][class_napalm_time] = KvGetFloat(kvClassData, "napalm_time", ZR_CLASS_DEFAULT_NAPALM_TIME); + ClassData[ClassCount][Class_HasNapalm] = bool:KvGetNum(kvClassData, "have_napalm", ZR_CLASS_DEFAULT_HAS_NAPALM); + ClassData[ClassCount][Class_NapalmTime] = KvGetFloat(kvClassData, "napalm_time", ZR_CLASS_DEFAULT_NAPALM_TIME); /* Player behaviour */ - ClassData[ClassCount][class_immunity_mode] = KvGetNum(kvClassData, "immunity_mode", ZR_CLASS_DEFAULT_IMMUNITY_MODE); - ClassData[ClassCount][class_immunity_amount] = KvGetFloat(kvClassData, "immunity_amount", ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT); - ClassData[ClassCount][class_no_fall_damage] = bool:KvGetNum(kvClassData, "no_fall_damage", ZR_CLASS_DEFAULT_NO_FALL_DAMAGE); + ClassData[ClassCount][Class_ImmunityMode] = KvGetNum(kvClassData, "immunity_mode", ZR_CLASS_DEFAULT_IMMUNITY_MODE); + ClassData[ClassCount][Class_ImmunityAmount] = KvGetFloat(kvClassData, "immunity_amount", ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT); + ClassData[ClassCount][Class_NoFallDamage] = bool:KvGetNum(kvClassData, "no_fall_damage", ZR_CLASS_DEFAULT_NO_FALL_DAMAGE); - ClassData[ClassCount][class_health] = KvGetNum(kvClassData, "health", ZR_CLASS_DEFAULT_HEALTH); - ClassData[ClassCount][class_health_regen_interval] = KvGetFloat(kvClassData, "health_regen_interval", ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL); - ClassData[ClassCount][class_health_regen_amount] = KvGetNum(kvClassData, "health_regen_amount", ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT); - ClassData[ClassCount][class_health_infect_gain] = KvGetNum(kvClassData, "health_infect_gain", ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN); - ClassData[ClassCount][class_kill_bonus] = KvGetNum(kvClassData, "kill_bonus", ZR_CLASS_DEFAULT_KILL_BONUS); + ClassData[ClassCount][Class_Health] = KvGetNum(kvClassData, "health", ZR_CLASS_DEFAULT_HEALTH); + ClassData[ClassCount][Class_HealthRegenInterval] = KvGetFloat(kvClassData, "health_regen_interval", ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL); + ClassData[ClassCount][Class_HealthRegenAmount] = KvGetNum(kvClassData, "health_regen_amount", ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT); + ClassData[ClassCount][Class_HealthInfectGain] = KvGetNum(kvClassData, "health_infect_gain", ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN); + ClassData[ClassCount][Class_KillBonus] = KvGetNum(kvClassData, "kill_bonus", ZR_CLASS_DEFAULT_KILL_BONUS); - ClassData[ClassCount][class_speed] = KvGetFloat(kvClassData, "speed", ZR_CLASS_DEFAULT_SPEED); - ClassData[ClassCount][class_knockback] = KvGetFloat(kvClassData, "knockback", ZR_CLASS_DEFAULT_KNOCKBACK); - ClassData[ClassCount][class_jump_height] = KvGetFloat(kvClassData, "jump_height", ZR_CLASS_DEFAULT_JUMP_HEIGHT); - ClassData[ClassCount][class_jump_distance] = KvGetFloat(kvClassData, "jump_distance", ZR_CLASS_DEFAULT_JUMP_DISTANCE); + ClassData[ClassCount][Class_Speed] = KvGetFloat(kvClassData, "speed", ZR_CLASS_DEFAULT_SPEED); + ClassData[ClassCount][Class_KnockBack] = KvGetFloat(kvClassData, "knockback", ZR_CLASS_DEFAULT_KNOCKBACK); + ClassData[ClassCount][Class_JumpHeight] = KvGetFloat(kvClassData, "jump_height", ZR_CLASS_DEFAULT_JUMP_HEIGHT); + ClassData[ClassCount][Class_JumpDistance] = KvGetFloat(kvClassData, "jump_distance", ZR_CLASS_DEFAULT_JUMP_DISTANCE); // Validate the class attributes. ClassErrorFlags = ClassValidateAttributes(ClassCount); @@ -511,7 +533,7 @@ ClassLoad(bool:keepMultipliers = false) { // There's one or more invalid class attributes. Disable the class // and log an error message. - ClassData[ClassCount][class_enabled] = false; + ClassData[ClassCount][Class_Enabled] = false; LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Config Validation", "Warning: Invalid class at index %d, disabled class. Class error flags: %d.", ClassCount, ClassErrorFlags); failedcount++; @@ -589,41 +611,42 @@ bool:ClassReloadDataCache() for (new classindex = 0; classindex < ClassCount; classindex++) { /* General */ - ClassDataCache[classindex][class_enabled] = ClassData[classindex][class_enabled]; - ClassDataCache[classindex][class_team] = ClassData[classindex][class_team]; - ClassDataCache[classindex][class_team_default] = ClassData[classindex][class_team_default]; - ClassDataCache[classindex][class_flags] = ClassData[classindex][class_flags]; - strcopy(ClassDataCache[classindex][class_name], 64, ClassData[classindex][class_name]); - strcopy(ClassDataCache[classindex][class_description], 256, ClassData[classindex][class_description]); + ClassDataCache[classindex][Class_Enabled] = ClassData[classindex][Class_Enabled]; + ClassDataCache[classindex][Class_Team] = ClassData[classindex][Class_Team]; + ClassDataCache[classindex][Class_TeamDefault] = ClassData[classindex][Class_TeamDefault]; + ClassDataCache[classindex][Class_Flags] = ClassData[classindex][Class_Flags]; + strcopy(ClassDataCache[classindex][Class_Group], 64, ClassData[classindex][Class_Group]); + strcopy(ClassDataCache[classindex][Class_Name], 64, ClassData[classindex][Class_Name]); + strcopy(ClassDataCache[classindex][Class_Description], 256, ClassData[classindex][Class_Description]); /* Model */ - strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, ClassData[classindex][class_model_path]); - ClassDataCache[classindex][class_alpha_initial] = ClassData[classindex][class_alpha_initial]; - ClassDataCache[classindex][class_alpha_damaged] = ClassData[classindex][class_alpha_damaged]; - ClassDataCache[classindex][class_alpha_damage] = ClassData[classindex][class_alpha_damage]; + strcopy(ClassDataCache[classindex][Class_ModelPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_ModelPath]); + ClassDataCache[classindex][Class_AlphaInitial] = ClassData[classindex][Class_AlphaInitial]; + ClassDataCache[classindex][Class_AlphaDamaged] = ClassData[classindex][Class_AlphaDamaged]; + ClassDataCache[classindex][Class_AlphaDamage] = ClassData[classindex][Class_AlphaDamage]; /* Hud */ - strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, ClassData[classindex][class_overlay_path]); - ClassDataCache[classindex][class_nvgs] = ClassData[classindex][class_nvgs]; - ClassDataCache[classindex][class_fov] = ClassData[classindex][class_fov]; + strcopy(ClassDataCache[classindex][Class_OverlayPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_OverlayPath]); + ClassDataCache[classindex][Class_Nvgs] = ClassData[classindex][Class_Nvgs]; + ClassDataCache[classindex][Class_Fov] = ClassData[classindex][Class_Fov]; /* Effects */ - ClassDataCache[classindex][class_has_napalm] = ClassData[classindex][class_has_napalm]; - ClassDataCache[classindex][class_napalm_time] = ClassData[classindex][class_napalm_time]; + ClassDataCache[classindex][Class_HasNapalm] = ClassData[classindex][Class_HasNapalm]; + ClassDataCache[classindex][Class_NapalmTime] = ClassData[classindex][Class_NapalmTime]; /* Player behaviour */ - ClassDataCache[classindex][class_immunity_mode] = ClassData[classindex][class_immunity_mode]; - ClassDataCache[classindex][class_immunity_amount] = ClassData[classindex][class_immunity_amount]; - ClassDataCache[classindex][class_no_fall_damage] = ClassData[classindex][class_no_fall_damage]; - ClassDataCache[classindex][class_health] = ClassData[classindex][class_health]; - ClassDataCache[classindex][class_health_regen_interval] = ClassData[classindex][class_health_regen_interval]; - ClassDataCache[classindex][class_health_regen_amount] = ClassData[classindex][class_health_regen_amount]; - ClassDataCache[classindex][class_health_infect_gain] = ClassData[classindex][class_health_infect_gain]; - ClassDataCache[classindex][class_kill_bonus] = ClassData[classindex][class_kill_bonus]; - ClassDataCache[classindex][class_speed] = ClassData[classindex][class_speed]; - ClassDataCache[classindex][class_knockback] = ClassData[classindex][class_knockback]; - ClassDataCache[classindex][class_jump_height] = ClassData[classindex][class_jump_height]; - ClassDataCache[classindex][class_jump_distance] = ClassData[classindex][class_jump_distance]; + ClassDataCache[classindex][Class_ImmunityMode] = ClassData[classindex][Class_ImmunityMode]; + ClassDataCache[classindex][Class_ImmunityAmount] = ClassData[classindex][Class_ImmunityAmount]; + ClassDataCache[classindex][Class_NoFallDamage] = ClassData[classindex][Class_NoFallDamage]; + ClassDataCache[classindex][Class_Health] = ClassData[classindex][Class_Health]; + ClassDataCache[classindex][Class_HealthRegenInterval] = ClassData[classindex][Class_HealthRegenInterval]; + ClassDataCache[classindex][Class_HealthRegenAmount] = ClassData[classindex][Class_HealthRegenAmount]; + ClassDataCache[classindex][Class_HealthInfectGain] = ClassData[classindex][Class_HealthInfectGain]; + ClassDataCache[classindex][Class_KillBonus] = ClassData[classindex][Class_KillBonus]; + ClassDataCache[classindex][Class_Speed] = ClassData[classindex][Class_Speed]; + ClassDataCache[classindex][Class_KnockBack] = ClassData[classindex][Class_KnockBack]; + ClassDataCache[classindex][Class_JumpHeight] = ClassData[classindex][Class_JumpHeight]; + ClassDataCache[classindex][Class_JumpDistance] = ClassData[classindex][Class_JumpDistance]; } return true; @@ -653,80 +676,82 @@ bool:ClassReloadPlayerCache(client, classindex, cachetype = ZR_CLASS_CACHE_MODIF case ZR_CLASS_CACHE_ORIGINAL: { /* General */ - ClassPlayerCache[client][class_enabled] = ClassData[classindex][class_enabled]; - ClassPlayerCache[client][class_team] = ClassData[classindex][class_team]; - ClassPlayerCache[client][class_team_default] = ClassData[classindex][class_team_default]; - ClassPlayerCache[client][class_flags] = ClassData[classindex][class_flags]; - strcopy(ClassPlayerCache[client][class_name], 64, ClassData[classindex][class_name]); - strcopy(ClassPlayerCache[client][class_description], 256, ClassData[classindex][class_description]); + ClassPlayerCache[client][Class_Enabled] = ClassData[classindex][Class_Enabled]; + ClassPlayerCache[client][Class_Team] = ClassData[classindex][Class_Team]; + ClassPlayerCache[client][Class_TeamDefault] = ClassData[classindex][Class_TeamDefault]; + ClassPlayerCache[client][Class_Flags] = ClassData[classindex][Class_Flags]; + strcopy(ClassPlayerCache[client][Class_Group], 64, ClassData[classindex][Class_Group]); + strcopy(ClassPlayerCache[client][Class_Name], 64, ClassData[classindex][Class_Name]); + strcopy(ClassPlayerCache[client][Class_Description], 256, ClassData[classindex][Class_Description]); /* Model */ - strcopy(ClassPlayerCache[client][class_model_path], PLATFORM_MAX_PATH, ClassData[classindex][class_model_path]); - ClassPlayerCache[client][class_alpha_initial] = ClassData[classindex][class_alpha_initial]; - ClassPlayerCache[client][class_alpha_damaged] = ClassData[classindex][class_alpha_damaged]; - ClassPlayerCache[client][class_alpha_damage] = ClassData[classindex][class_alpha_damage]; + strcopy(ClassPlayerCache[client][Class_ModelPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_ModelPath]); + ClassPlayerCache[client][Class_AlphaInitial] = ClassData[classindex][Class_AlphaInitial]; + ClassPlayerCache[client][Class_AlphaDamaged] = ClassData[classindex][Class_AlphaDamaged]; + ClassPlayerCache[client][Class_AlphaDamage] = ClassData[classindex][Class_AlphaDamage]; /* Hud */ - strcopy(ClassPlayerCache[client][class_overlay_path], PLATFORM_MAX_PATH, ClassData[classindex][class_overlay_path]); - ClassPlayerCache[client][class_nvgs] = ClassData[classindex][class_nvgs]; - ClassPlayerCache[client][class_fov] = ClassData[classindex][class_fov]; + strcopy(ClassPlayerCache[client][Class_OverlayPath], PLATFORM_MAX_PATH, ClassData[classindex][Class_OverlayPath]); + ClassPlayerCache[client][Class_Nvgs] = ClassData[classindex][Class_Nvgs]; + ClassPlayerCache[client][Class_Fov] = ClassData[classindex][Class_Fov]; /* Effects */ - ClassPlayerCache[client][class_has_napalm] = ClassData[classindex][class_has_napalm]; - ClassPlayerCache[client][class_napalm_time] = ClassData[classindex][class_napalm_time]; + ClassPlayerCache[client][Class_HasNapalm] = ClassData[classindex][Class_HasNapalm]; + ClassPlayerCache[client][Class_NapalmTime] = ClassData[classindex][Class_NapalmTime]; /* Player behaviour */ - ClassPlayerCache[client][class_immunity_mode] = ClassData[classindex][class_immunity_mode]; - ClassPlayerCache[client][class_immunity_amount] = ClassData[classindex][class_immunity_amount]; - ClassPlayerCache[client][class_no_fall_damage] = ClassData[classindex][class_no_fall_damage]; - ClassPlayerCache[client][class_health] = ClassData[classindex][class_health]; - ClassPlayerCache[client][class_health_regen_interval] = ClassData[classindex][class_health_regen_interval]; - ClassPlayerCache[client][class_health_regen_amount] = ClassData[classindex][class_health_regen_amount]; - ClassPlayerCache[client][class_health_infect_gain] = ClassData[classindex][class_health_infect_gain]; - ClassPlayerCache[client][class_kill_bonus] = ClassData[classindex][class_kill_bonus]; - ClassPlayerCache[client][class_speed] = ClassData[classindex][class_speed]; - ClassPlayerCache[client][class_knockback] = ClassData[classindex][class_knockback]; - ClassPlayerCache[client][class_jump_height] = ClassData[classindex][class_jump_height]; - ClassPlayerCache[client][class_jump_distance] = ClassData[classindex][class_jump_distance]; + ClassPlayerCache[client][Class_ImmunityMode] = ClassData[classindex][Class_ImmunityMode]; + ClassPlayerCache[client][Class_ImmunityAmount] = ClassData[classindex][Class_ImmunityAmount]; + ClassPlayerCache[client][Class_NoFallDamage] = ClassData[classindex][Class_NoFallDamage]; + ClassPlayerCache[client][Class_Health] = ClassData[classindex][Class_Health]; + ClassPlayerCache[client][Class_HealthRegenInterval] = ClassData[classindex][Class_HealthRegenInterval]; + ClassPlayerCache[client][Class_HealthRegenAmount] = ClassData[classindex][Class_HealthRegenAmount]; + ClassPlayerCache[client][Class_HealthInfectGain] = ClassData[classindex][Class_HealthInfectGain]; + ClassPlayerCache[client][Class_KillBonus] = ClassData[classindex][Class_KillBonus]; + ClassPlayerCache[client][Class_Speed] = ClassData[classindex][Class_Speed]; + ClassPlayerCache[client][Class_KnockBack] = ClassData[classindex][Class_KnockBack]; + ClassPlayerCache[client][Class_JumpHeight] = ClassData[classindex][Class_JumpHeight]; + ClassPlayerCache[client][Class_JumpDistance] = ClassData[classindex][Class_JumpDistance]; } case ZR_CLASS_CACHE_MODIFIED: { /* General */ - ClassPlayerCache[client][class_enabled] = ClassDataCache[classindex][class_enabled]; - ClassPlayerCache[client][class_team] = ClassDataCache[classindex][class_team]; - ClassPlayerCache[client][class_team_default] = ClassDataCache[classindex][class_team_default]; - ClassPlayerCache[client][class_flags] = ClassDataCache[classindex][class_flags]; - strcopy(ClassPlayerCache[client][class_name], 64, ClassDataCache[classindex][class_name]); - strcopy(ClassPlayerCache[client][class_description], 256, ClassDataCache[classindex][class_description]); + ClassPlayerCache[client][Class_Enabled] = ClassDataCache[classindex][Class_Enabled]; + ClassPlayerCache[client][Class_Team] = ClassDataCache[classindex][Class_Team]; + ClassPlayerCache[client][Class_TeamDefault] = ClassDataCache[classindex][Class_TeamDefault]; + ClassPlayerCache[client][Class_Flags] = ClassDataCache[classindex][Class_Flags]; + strcopy(ClassPlayerCache[client][Class_Group], 64, ClassDataCache[classindex][Class_Group]); + strcopy(ClassPlayerCache[client][Class_Name], 64, ClassDataCache[classindex][Class_Name]); + strcopy(ClassPlayerCache[client][Class_Description], 256, ClassDataCache[classindex][Class_Description]); /* Model */ - strcopy(ClassPlayerCache[client][class_model_path], PLATFORM_MAX_PATH, ClassDataCache[classindex][class_model_path]); - ClassPlayerCache[client][class_alpha_initial] = ClassDataCache[classindex][class_alpha_initial]; - ClassPlayerCache[client][class_alpha_damaged] = ClassDataCache[classindex][class_alpha_damaged]; - ClassPlayerCache[client][class_alpha_damage] = ClassDataCache[classindex][class_alpha_damage]; + strcopy(ClassPlayerCache[client][Class_ModelPath], PLATFORM_MAX_PATH, ClassDataCache[classindex][Class_ModelPath]); + ClassPlayerCache[client][Class_AlphaInitial] = ClassDataCache[classindex][Class_AlphaInitial]; + ClassPlayerCache[client][Class_AlphaDamaged] = ClassDataCache[classindex][Class_AlphaDamaged]; + ClassPlayerCache[client][Class_AlphaDamage] = ClassDataCache[classindex][Class_AlphaDamage]; /* Hud */ - strcopy(ClassPlayerCache[client][class_overlay_path], PLATFORM_MAX_PATH, ClassDataCache[classindex][class_overlay_path]); - ClassPlayerCache[client][class_nvgs] = ClassDataCache[classindex][class_nvgs]; - ClassPlayerCache[client][class_fov] = ClassDataCache[classindex][class_fov]; + strcopy(ClassPlayerCache[client][Class_OverlayPath], PLATFORM_MAX_PATH, ClassDataCache[classindex][Class_OverlayPath]); + ClassPlayerCache[client][Class_Nvgs] = ClassDataCache[classindex][Class_Nvgs]; + ClassPlayerCache[client][Class_Fov] = ClassDataCache[classindex][Class_Fov]; /* Effects */ - ClassPlayerCache[client][class_has_napalm] = ClassDataCache[classindex][class_has_napalm]; - ClassPlayerCache[client][class_napalm_time] = ClassDataCache[classindex][class_napalm_time]; + ClassPlayerCache[client][Class_HasNapalm] = ClassDataCache[classindex][Class_HasNapalm]; + ClassPlayerCache[client][Class_NapalmTime] = ClassDataCache[classindex][Class_NapalmTime]; /* Player behaviour */ - ClassPlayerCache[client][class_immunity_mode] = ClassDataCache[classindex][class_immunity_mode]; - ClassPlayerCache[client][class_immunity_amount] = ClassDataCache[classindex][class_immunity_amount]; - ClassPlayerCache[client][class_no_fall_damage] = ClassDataCache[classindex][class_no_fall_damage]; - ClassPlayerCache[client][class_health] = ClassDataCache[classindex][class_health]; - ClassPlayerCache[client][class_health_regen_interval] = ClassDataCache[classindex][class_health_regen_interval]; - ClassPlayerCache[client][class_health_regen_amount] = ClassDataCache[classindex][class_health_regen_amount]; - ClassPlayerCache[client][class_health_infect_gain] = ClassDataCache[classindex][class_health_infect_gain]; - ClassPlayerCache[client][class_kill_bonus] = ClassDataCache[classindex][class_kill_bonus]; - ClassPlayerCache[client][class_speed] = ClassDataCache[classindex][class_speed]; - ClassPlayerCache[client][class_knockback] = ClassDataCache[classindex][class_knockback]; - ClassPlayerCache[client][class_jump_height] = ClassDataCache[classindex][class_jump_height]; - ClassPlayerCache[client][class_jump_distance] = ClassDataCache[classindex][class_jump_distance]; + ClassPlayerCache[client][Class_ImmunityMode] = ClassDataCache[classindex][Class_ImmunityMode]; + ClassPlayerCache[client][Class_ImmunityAmount] = ClassDataCache[classindex][Class_ImmunityAmount]; + ClassPlayerCache[client][Class_NoFallDamage] = ClassDataCache[classindex][Class_NoFallDamage]; + ClassPlayerCache[client][Class_Health] = ClassDataCache[classindex][Class_Health]; + ClassPlayerCache[client][Class_HealthRegenInterval] = ClassDataCache[classindex][Class_HealthRegenInterval]; + ClassPlayerCache[client][Class_HealthRegenAmount] = ClassDataCache[classindex][Class_HealthRegenAmount]; + ClassPlayerCache[client][Class_HealthInfectGain] = ClassDataCache[classindex][Class_HealthInfectGain]; + ClassPlayerCache[client][Class_KillBonus] = ClassDataCache[classindex][Class_KillBonus]; + ClassPlayerCache[client][Class_Speed] = ClassDataCache[classindex][Class_Speed]; + ClassPlayerCache[client][Class_KnockBack] = ClassDataCache[classindex][Class_KnockBack]; + ClassPlayerCache[client][Class_JumpHeight] = ClassDataCache[classindex][Class_JumpHeight]; + ClassPlayerCache[client][Class_JumpDistance] = ClassDataCache[classindex][Class_JumpDistance]; } default: { @@ -786,7 +811,7 @@ ClassResetMultiplierCache() } /** - * Resets the selected class indexes for next span on one or all clients. + * Resets the selected class indexes for next spawn on one or all clients. * * @param client Optional. Specify client to reset. Default is all. */ @@ -818,7 +843,7 @@ ClassResetNextIndexes(client = -1) * Note: Does not apply attributes. The classes are only marked as selected. * * @param client The client index. - * @param excludeTeam Do not restore the specified team. + * @param excludeTeam Optional. Do not restore the specified team. */ ClassRestoreNextIndexes(client, excludeTeam = -1) { @@ -980,6 +1005,10 @@ ClassDumpData(index, cachetype, String:buffer[], maxlen) Format(attribute, sizeof(attribute), "flags: \"%d\"\n", ClassGetFlags(index, cachetype)); cellcount += StrCat(buffer, maxlen, attribute); + ClassGetGroup(index, format_buffer, sizeof(format_buffer), cachetype); + Format(attribute, sizeof(attribute), "group: \"%d\"\n", format_buffer); + cellcount += StrCat(buffer, maxlen, attribute); + ClassGetName(index, format_buffer, sizeof(format_buffer), cachetype); Format(attribute, sizeof(attribute), "name: \"%s\"\n", format_buffer); cellcount += StrCat(buffer, maxlen, attribute); From d1cbda40c446b4d4034637c90aec47af4a916ad3 Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 14 Aug 2009 22:10:52 +0200 Subject: [PATCH 07/16] Implemented group class attribute. Improved filtering method for class functions. --- .../sourcemod/configs/zr/playerclasses.txt | 12 ++ src/zr/playerclasses/classevents.inc | 58 +++++- src/zr/playerclasses/classmenus.inc | 21 +- src/zr/playerclasses/filtertools.inc | 190 ++++++++++-------- src/zr/playerclasses/playerclasses.inc | 23 ++- 5 files changed, 204 insertions(+), 100 deletions(-) diff --git a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt index 045badd..ea6be44 100644 --- a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt +++ b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt @@ -20,6 +20,7 @@ // use a sum of the flag values. Available flags: // 1 - Admins only // 2 - Mother zombies only +// group text Restrict class to member of this SourceMod group. Leave blank for no restriction. // name text The class name used in class menu. // description text The class description used in class menu. // model_path text Path to model to use. Relative to cstrike folder. @@ -58,6 +59,7 @@ "team" "0" "team_default" "1" "flags" "0" + "group" "" "name" "Classic" "description" "Need brains!!! Arrrrggghh!" @@ -101,6 +103,7 @@ "team" "0" "team_default" "0" "flags" "0" + "group" "" "name" "Fast" "description" "-HP | +Speed | +Jump | +Knockback" @@ -144,6 +147,7 @@ "team" "0" "team_default" "0" "flags" "0" + "group" "" "name" "Mutated" "description" "+HP | -Speed | +Jump | +Knockback" @@ -187,6 +191,7 @@ "team" "0" "team_default" "0" "flags" "0" + "group" "" "name" "Heavy" "description" "+HP | -Speed | -Jump | -Knockback" @@ -230,6 +235,7 @@ "team" "0" "team_default" "0" "flags" "2" + "group" "" "name" "Mother zombie" "description" "+HP regen | +Speed | +Jump | -Knockback" @@ -273,6 +279,7 @@ "team" "0" "team_default" "0" "flags" "3" + "group" "" "name" "Admin mother zombie" "description" "+HP regen | +Speed | +Jump | -Knockback" @@ -322,6 +329,7 @@ "team" "1" "team_default" "1" "flags" "0" + "group" "" "name" "Normal Human" "description" "Default Counter-Strike settings" @@ -365,6 +373,7 @@ "team" "1" "team_default" "0" "flags" "0" + "group" "" "name" "VIP Human" "description" "Human class for important players" @@ -408,6 +417,7 @@ "team" "1" "team_default" "0" "flags" "1" + "group" "" "name" "Admin Human" "description" "Human class for admins" @@ -451,6 +461,7 @@ "team" "1" "team_default" "0" "flags" "0" + "group" "" "name" "Speedy" "description" "Fast human" @@ -494,6 +505,7 @@ "team" "1" "team_default" "0" "flags" "0" + "group" "" "name" "Light" "description" "Regular human with improved jump skills" diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc index 3ae4ebc..60ecf83 100644 --- a/src/zr/playerclasses/classevents.inc +++ b/src/zr/playerclasses/classevents.inc @@ -75,6 +75,7 @@ ClassOnClientSpawn(client) decl String:originalmodel[PLATFORM_MAX_PATH]; decl String:steamid[16]; decl String:classname[64]; + new filter[ClassFilter]; // Check if the player is dead. Spawning into the game is also a event in // the connection process. @@ -121,15 +122,24 @@ ClassOnClientSpawn(client) // Assign random classes if enabled. Always do it for bots. if (randomclass || StrEqual(steamid, "BOT")) { - // Exclude special class flags like mother zombies and admin classes. - new denyflags = ZR_CLASS_SPECIALFLAGS; + // Setup filtering + // --------------- + // Exclude special class flags like mother zombies and admin classes. + filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS; + // Allow admin classes if admin. - denyflags -= ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0; + filter[ClassFilter_DenyFlags] -= ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0; + + // Specify client for checking group permissions. + filter[ClassFilter_Client] = client; + + // Get classes + // ----------- // Get random classes for each type. - new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, denyflags); - new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, _, _, denyflags); + new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter); + new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, filter); // Set selected zombie class index. ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = randomzombie; @@ -199,6 +209,7 @@ ClassOnClientInfected(client, bool:motherzombie = false) new classindex = ClassGetActiveIndex(client); new isadmin; new motherindex; + new filter[ClassFilter]; decl String:motherzombiesetting[64]; @@ -224,8 +235,23 @@ ClassOnClientInfected(client, bool:motherzombie = false) } else if (StrEqual(motherzombiesetting, "random", false)) { + // Setup filtering + // --------------- + + // Exclude special class flags. + filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS; + + // Allow admin classes if admin. + filter[ClassFilter_DenyFlags] -= isadmin; + + // Specify client for checking group permissions. + filter[ClassFilter_Client] = client; + + // Get class + // --------- + // Get random regular zombie class. Remove admin flag if admin. - motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS - isadmin); + motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter); // Validate index. Do not change class if it's invalid. if (ClassValidateIndex(motherindex)) @@ -239,8 +265,26 @@ ClassOnClientInfected(client, bool:motherzombie = false) } else if (StrEqual(motherzombiesetting, "motherzombies", false)) { + // Setup filtering + // --------------- + + // Exclude special class flags except mother zombies. + filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS - ZR_CLASS_FLAG_MOTHER_ZOMBIE; + + // Require mother zombie class flag. + filter[ClassFilter_RequireFlags] = ZR_CLASS_FLAG_MOTHER_ZOMBIE; + + // Allow admin classes if admin. + filter[ClassFilter_DenyFlags] -= isadmin; + + // Specify client for checking group permissions. + filter[ClassFilter_Client] = client; + + // Get class + // --------- + // Get random mother zombie class. Include admin classes if admin. - motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, ZR_CLASS_FLAG_MOTHER_ZOMBIE + isadmin, ZR_CLASS_FLAG_ADMIN_ONLY - isadmin); + motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter); // Validate index. Do not change class if it's invalid. if (ClassValidateIndex(motherindex)) diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index 89c5fa4..e8826c7 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -247,7 +247,6 @@ ClassMenuSelect(client, teamid) new Handle:menu = CreateMenu(ClassMenuSelectHandle); new arraycount; new classindex; - new denyflags; decl String:title[MENU_LINE_TITLE_LENGTH]; decl String:classname[MENU_LINE_REG_LENGTH]; @@ -277,12 +276,24 @@ ClassMenuSelect(client, teamid) // Create buffer array. new Handle:classarray = CreateArray(); - // Set up filtering. - denyflags = ZR_CLASS_FLAG_MOTHER_ZOMBIE; // Hide mother zombie classes. - denyflags += !ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0; // Hide admin-only classes if not admin. + // Set up filtering + // ---------------- + new filter[ClassFilter]; + + // Hide mother zombie classes. + filter[ClassFilter_DenyFlags] = ZR_CLASS_FLAG_MOTHER_ZOMBIE; + + // Hide admin-only classes if not admin. + filter[ClassFilter_DenyFlags] += !ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0; + + // Specify client for checking class group permissions. + filter[ClassFilter_Client] = client; + + // Get classes + // ----------- // Copy all class indexes into the array, with the specified filter settings. - if (ClassAddToArray(classarray, teamid, _, _, denyflags)) + if (ClassAddToArray(classarray, teamid, filter)) { // Get number of classes. arraycount = GetArraySize(classarray); diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index ecfbfe9..f4d0d6a 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -47,8 +47,8 @@ stock bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL) } // Test if a zombie and human class was found. - zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); - humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); + zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, cachetype); + humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, cachetype); // Validate indexes. if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex)) @@ -79,8 +79,8 @@ stock bool:ClassValidateTeamDefaults(cachetype = ZR_CLASS_CACHE_ORIGINAL) } // Test if a default zombie and human class was found. - zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, _, _, cachetype); - humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, _, _, cachetype); + zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, cachetype); + humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, cachetype); // Validate indexes. if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex)) @@ -119,7 +119,14 @@ stock ClassValidateAttributes(classindex) } // Group. - + if (strlen(ClassData[classindex][Class_Group])) + { + // Check if the group exist. + if (FindAdmGroup(ClassData[classindex][Class_Group]) == INVALID_GROUP_ID) + { + flags += ZR_CLASS_GROUP; + } + } // Name. if (strlen(ClassData[classindex][Class_Name]) < ZR_CLASS_NAME_MIN) @@ -454,6 +461,59 @@ stock Float:ClassGetAttributeMultiplier(client, ClassMultipliers:attribute) } } +/** + * Check if a class pass the specified filter. + * + * @param index Index of the class in a class cache or a client index, + * depending on the cache type specified. + * @param filter Structure with filter settings. + * @param cachetype Optional. Specifies what class cache to read from. + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED (default) - Changed/newest + * class data. + * ZR_CLASS_CACHE_PLAYER - Player cache. If this one is + * used index will be used as a client index. + * @return True if passed, false otherwise. + */ +stock bool:ClassFilterMatch(index, filter[ClassFilter], cachetype = ZR_CLASS_CACHE_MODIFIED) +{ + // Check if the class is disabled and the enabled attribute is NOT ignored. + if (!filter[ClassFilter_IgnoreEnabled] && !ClassIsEnabled(index, cachetype)) + { + return false; + } + + // Check class flags pass the flag filter. + if (!ClassFlagFilterMatch(index, filter[ClassFilter_RequireFlags], filter[ClassFilter_DenyFlags], cachetype)) + { + return false; + } + + // Check if a client is specified in the filter. + new client = filter[ClassFilter_Client]; + if (ZRIsClientValid(client)) + { + // Get class group name. + decl String:groupname[64]; + groupname[0] = 0; + ClassGetGroup(index, groupname, sizeof(groupname), cachetype); + + // Check if a group is set on the class. Note: This group name is + // validated when classes are loaded. + if (strlen(groupname)) + { + // Check if the client is a member of that group. + if (!ZRIsClientInGroup(client, groupname)) + { + return false; + } + } + } + + // The class passed the filter. + return true; +} + /** * Check if a class pass the specified flag filters. * @@ -586,12 +646,7 @@ bool:ClassAllowSelection(client, team = -1) * @param array The destination array to add class indexes. * @param teamfilter Optional. The team ID to filter. A negative value * for no filter (default). - * @param ignoreEnabled Optional. Ignore whether the class is enabled or - * not. Default is false. - * @param requireflags Optional. Require certain class flags to be set. - * Default is no filtering. - * @param denyflags Optional. Require certain class flags to be off. - * Default is no filtering. + * @param filter Optional. Structure with filter settings. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -600,7 +655,7 @@ bool:ClassAllowSelection(client, team = -1) * @return True on success. False on error or if no classes were added or * found. */ -stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock bool:ClassAddToArray(Handle:array, teamfilter = -1, filter[ClassFilter] = ClassNoFilter, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Validate the array. if (array == INVALID_HANDLE) @@ -615,46 +670,39 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f } // Store a local boolean that says if the user specified a team filter or not. - new bool:has_filter = bool:(teamfilter >= 0); - new classes_added; + new bool:hasteamfilter = bool:(teamfilter >= 0); + new classesadded; // Loop through all classes. for (new classindex = 0; classindex < ClassCount; classindex++) { - if (!ignoreEnabled && !ClassIsEnabled(classindex, cachetype)) + // Validate filter settings. + if (!ClassFilterMatch(classindex, filter, cachetype)) { - // The class is disabled and the enabled attribute is NOT ignored. - // Skip to the next class. - continue; - } - - // Check flag filter match. - if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype)) - { - // The class didn't pass filter. + // The class is didn't pass the filter, skip class. continue; } // Check team filtering. - if (has_filter) + if (hasteamfilter) { // Only add classes with matching team ID. if (ClassGetTeamID(classindex, cachetype) == teamfilter) { // Team ID match. Add class index to array. PushArrayCell(array, classindex); - classes_added++; + classesadded++; } } else { // No filter. Add any class to the array. PushArrayCell(array, classindex); - classes_added++; + classesadded++; } } - if (classes_added) + if (classesadded) { return true; } @@ -670,12 +718,7 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f * * @param teamfilter Optional. The team ID to filter. Negative value for * no filter (default). - * @param ignoreEnabled Optional. Ignore whether the class is enabled or - * not. Default is false. - * @param requireflags Optional. Require certain class flags to be set. - * Default is no filtering. - * @param denyflags Optional. Require certain class flags to be off. - * Default is no filtering. + * @param filter Optional. Structure with filter settings. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -683,7 +726,7 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f * class data. * @return Number of total classes or classes in the specified team. */ -stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassCountTeam(teamfilter = -1, filter[ClassFilter] = ClassNoFilter, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Check if there are no classes. if (ClassCount == 0) @@ -692,28 +735,21 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags = } // Store a local boolean that says if the user specified a team filter or not. - new bool:has_filter = bool:(teamfilter >= 0); + new bool:hasteamfilter = bool:(teamfilter >= 0); new count; // Loop through all classes. for (new classindex = 0; classindex < ClassCount; classindex++) { - if (!ignoreEnabled && !ClassIsEnabled(classindex, cachetype)) + // Validate filter settings. + if (!ClassFilterMatch(classindex, filter, cachetype)) { - // The class is disabled and the enabled attribute is NOT ignored. - // Skip to the next class. - continue; - } - - // Check flag filter match. - if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype)) - { - // The class didn't pass filter. + // The class is didn't pass the filter, skip class. continue; } // Check team filtering. - if (has_filter) + if (hasteamfilter) { // Only add classes with matching team ID. if (ClassGetTeamID(classindex, cachetype) == teamfilter) @@ -738,12 +774,7 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags = * * @param teamfilter Optional. The team ID to filter. A negative value * for no filter (default). - * @param ignoreEnabled Optional. Ignore whether the class is enabled or - * not. Default is false. - * @param requireflags Optional. Require certain class flags to be set. - * Default is no filtering. - * @param denyflags Optional. Require certain class flags to be off. - * Default is no filtering. + * @param filter Optional. Structure with filter settings. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -751,7 +782,7 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags = * class data. * @return The class index if successful, or -1 on error. */ -stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetRandomClass(teamfilter = -1, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED) { new Handle:classarray; new arraycount; @@ -761,7 +792,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl classarray = CreateArray(); // Try to get a class list. - if (ClassAddToArray(classarray, teamfilter, ignoreEnabled, requireflags, denyflags, cachetype)) + if (ClassAddToArray(classarray, teamfilter, filter, cachetype)) { // Get a random index from the new class array. arraycount = GetArraySize(classarray); @@ -786,12 +817,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl * * @param teamfilter Optional. The team ID to filter. A negative value * for no filter (default). - * @param ignoreEnabled Optional. Ignore whether the class is enabled or - * not. Default is false. - * @param requireflags Optional. Require certain class flags to be set. - * Default is no filtering. - * @param denyflags Optional. Require certain class flags to be off. - * Default is no filtering. + * @param filter Optional. Structure with filter settings. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -800,7 +826,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl * @return The first class index, or the first class index with the specified * team ID. -1 on error. */ -stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetFirstClass(teamfilter = -1, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Check if there are no classes. if (ClassCount == 0) @@ -808,26 +834,19 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla return false; } - new bool:has_filter = bool:(teamfilter >= 0); + new bool:hasteamfilter = bool:(teamfilter >= 0); // Loop through all classes. for (new classindex = 0; classindex < ClassCount; classindex++) { - if (!ignoreEnabled && !ClassIsEnabled(classindex, cachetype)) + // Validate filter settings. + if (!ClassFilterMatch(classindex, filter, cachetype)) { - // The class is disabled and the enabled attribute is NOT ignored. - // Skip to the next class. + // The class is didn't pass the filter, skip class. continue; } - // Check flag filter match. - if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype)) - { - // The class didn't pass filter. - continue; - } - - if (has_filter) + if (hasteamfilter) { if (teamfilter == ClassGetTeamID(classindex, cachetype)) { @@ -849,12 +868,8 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla * Gets the first class marked as default for the specified team. * * @param teamid The team ID. - * @param ignoreEnabled Optional. Ignore whether the class is enabled or - * not. Default is false. - * @param requireflags Optional. Require certain class flags to be set. - * Default is no filtering. - * @param denyflags Optional. Require certain class flags to be off. - * Default is to deny classes with special flags + * @param filter Optional. Structure with filter settings. Default + * is to deny classes with special flags * (ZR_CLASS_SPECIALFLAGS). * @param cachetype Optional. Specifies what class cache to read from. * Options: @@ -863,7 +878,7 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla * class data. * @return The first default class index. -1 on error. */ -stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0, denyflags = ZR_CLASS_SPECIALFLAGS, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetDefaultClass(teamid, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED) { new Handle:classarray; new arraycount; @@ -872,7 +887,7 @@ stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0, classarray = CreateArray(); // Get all classes from the specified team. - if (!ClassAddToArray(classarray, teamid, ignoreEnabled, requireflags, denyflags, cachetype)) + if (!ClassAddToArray(classarray, teamid, filter, cachetype)) { // Failed to get classes. CloseHandle(classarray); @@ -943,11 +958,11 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) if (strlen(classname) > 0) { // Check if the user set "random" as default class. - if (strcmp(classname, "random", false) == 0) + if (StrEqual(classname, "random", false)) { // Get a list of all classes with the specified team ID. Deny // classes with special flags. - classindex = ClassGetRandomClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); + classindex = ClassGetRandomClass(teamid, _, cachetype); // Validate the result, in case there were errors. if (ClassValidateIndex(classindex)) @@ -979,7 +994,7 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) // The class index is invalid or the team IDs didn't match. // Because it's user input, we'll fall back to the first class // in the specified team, and log a warning. - classindex = ClassGetFirstClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); + classindex = ClassGetFirstClass(teamid, _, cachetype); LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Default Spawn Class", "Warning: Failed to set \"%s\" as default spawn class for team %d. The class doesn't exist or the team IDs doesn't match. Falling back to the first class in the team.", classname, teamid); @@ -992,7 +1007,8 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) } else { - // Something went wrong. This is a critical error. + // Something went wrong. This is a critical error. There's + // probably missing classes with no special flags set. return -1; } } @@ -1001,6 +1017,6 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) else { // Blank class name, get the default class and return the index. - return ClassGetDefaultClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); + return ClassGetDefaultClass(teamid, _, cachetype); } } diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 4137d3e..65915aa 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -312,6 +312,27 @@ enum ClassDataTypes ClassDataType_String /** String value */ } +/** + * Structure for class filter settings passed to various functions. + */ +enum ClassFilter +{ + bool:ClassFilter_IgnoreEnabled, /** Ignore whether the class is disabled or not. */ + ClassFilter_RequireFlags, /** Flags the classes must have set. */ + ClassFilter_DenyFlags, /** Flags the classes cannot have set. */ + ClassFilter_Client /** The client to check for class group permissions. Use 0 or less to ignore group filter. */ +} + +/** + * Empty filter structure. + */ +new ClassNoFilter[ClassFilter]; + +/** + * Filter structure for excluding special classes. + */ +new ClassNoSpecialClasses[ClassFilter] = {false, 0, ZR_CLASS_SPECIALFLAGS, -1}; + /** * Keyvalue handle to store class data. */ @@ -1006,7 +1027,7 @@ ClassDumpData(index, cachetype, String:buffer[], maxlen) cellcount += StrCat(buffer, maxlen, attribute); ClassGetGroup(index, format_buffer, sizeof(format_buffer), cachetype); - Format(attribute, sizeof(attribute), "group: \"%d\"\n", format_buffer); + Format(attribute, sizeof(attribute), "group: \"%s\"\n", format_buffer); cellcount += StrCat(buffer, maxlen, attribute); ClassGetName(index, format_buffer, sizeof(format_buffer), cachetype); From 35c3f80ed12aa10edfd18b856f2a64fcd67b7754 Mon Sep 17 00:00:00 2001 From: ricard Date: Sat, 15 Aug 2009 01:28:28 +0200 Subject: [PATCH 08/16] Simplified class menu translations. Small improvement in logic when selected classes. --- .../no/zombiereloaded.phrases.txt | 40 +++++------------ .../translations/zombiereloaded.phrases.txt | 44 +++++-------------- src/zr/playerclasses/classmenus.inc | 40 ++++++++++------- 3 files changed, 45 insertions(+), 79 deletions(-) diff --git a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt index 92b1446..9954212 100644 --- a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt @@ -216,49 +216,29 @@ "no" "Klassevalg:" } - "Classes menu zombie" + "Classes menu active" { - "no" "Velg zombieklasse:" + "no" "Aktiv: {1}" } - "Classes menu zombie current" + "Classes menu next" { - "no" "Velg zombieklasse\n {1}" + "no" "Påfølgende: {1}" } - "Classes menu zombie next" + "Classes menu select zombie" { - "no" "Velg zombieklasse\n Aktiv: {1}\n Påfølgende: {2}" + "no" "Velg zombieklasse" } - "Classes menu human" + "Classes menu select human" { - "no" "Velg menneskeklasse:" + "no" "Velg menneskeklasse" } - "Classes menu human current" + "Classes menu select admin" { - "no" "Velg menneskeklasse\n {1}" - } - - "Classes menu human next" - { - "no" "Velg menneskeklasse\n Aktiv: {1}\n Påfølgende: {2}" - } - - "Classes menu admin" - { - "no" "Velg administratormodusklasse:" - } - - "Classes menu admin current" - { - "no" "Velg administratormodusklasse\n {1}" - } - - "Classes menu admin next" - { - "no" "Velg administratormodusklasse\n Active: {1}\n Next spawn: {2}" + "no" "Velg administratormodusklasse" } "Classes menu admin mode toggle" diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index 54ca9ce..c09ed0b 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -228,55 +228,31 @@ "en" "Class Selection:" } - "Classes menu zombie" - { - "en" "Select Zombie Class:" - } - - "Classes menu zombie current" + "Classes menu active" { "#format" "{1:s}" - "en" "Select Zombie Class\n {1}" + "en" "Active: {1}" } - "Classes menu zombie next" - { - "#format" "{1:s},{2:s}" - "en" "Select Zombie Class\n Active: {1}\n Next spawn: {2}" - } - - "Classes menu human" - { - "en" "Select Human Class:" - } - - "Classes menu human current" + "Classes menu next" { "#format" "{1:s}" - "en" "Select Human Class\n {1}" + "en" "Next spawn: {1}" } - "Classes menu human next" + "Classes menu select zombie" { - "#format" "{1:s},{2:s}" - "en" "Select Human Class\n Active: {1}\n Next spawn: {2}" + "en" "Select Zombie Class" } - "Classes menu admin" + "Classes menu select human" { - "en" "Select Admin Mode Class:" - } - - "Classes menu admin current" - { - "#format" "{1:s}" - "en" "Select Admin Mode Class\n {1}" + "en" "Select Human Class" } - "Classes menu admin next" + "Classes menu select admin" { - "#format" "{1:s},{2:s}" - "en" "Select Admin Mode Class\n Active: {1}\n Next spawn: {2}" + "en" "Select Admin Mode Class" } "Classes menu admin mode toggle" diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index e8826c7..de2cda8 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -67,7 +67,7 @@ ClassMenuMain(client) new humancount = ClassCountTeam(ZR_CLASS_TEAM_ZOMBIES); new admincount = ClassCountTeam(ZR_CLASS_TEAM_ADMINS); - // Get previously selected class indexes, if set. + // Get next class indexes, if set. new nextzombie = ClassSelectedNext[client][ZR_CLASS_TEAM_ZOMBIES]; new nexthuman = ClassSelectedNext[client][ZR_CLASS_TEAM_HUMANS]; new nextadmin = ClassSelectedNext[client][ZR_CLASS_TEAM_ADMINS]; @@ -93,18 +93,18 @@ ClassMenuMain(client) // Get current class name. ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES], zombieclass, sizeof(zombieclass), ZR_CLASS_CACHE_MODIFIED); - // Check if previous index is set. + // Check if next index is set. if (ClassValidateIndex(nextzombie)) { // Get name of previous class index and format item text. ClassGetName(nextzombie, nextzombiename, sizeof(nextzombiename), ZR_CLASS_CACHE_MODIFIED); - Format(zombieselect, sizeof(zombieselect), "%t", "Classes menu zombie next", zombieclass, nextzombiename); + Format(zombieselect, sizeof(zombieselect), "%t\n %t\n %t", "Classes menu select zombie", "Classes menu active", zombieclass, "Classes menu next", nextzombiename); } else { // Use current class name and format item text. - Format(zombieselect, sizeof(zombieselect), "%t", "Classes menu zombie current", zombieclass); + Format(zombieselect, sizeof(zombieselect), "%t\n %s", "Classes menu select zombie", zombieclass); } // Add item to list. @@ -117,18 +117,18 @@ ClassMenuMain(client) // Get current class name. ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_HUMANS], humanclass, sizeof(humanclass), ZR_CLASS_CACHE_MODIFIED); - // Check if previous index is set. + // Check if next index is set. if (ClassValidateIndex(nexthuman)) { // Get name of previous class index and format item text. ClassGetName(nexthuman, nexthumanname, sizeof(nexthumanname), ZR_CLASS_CACHE_MODIFIED); - Format(humanselect, sizeof(humanselect), "%t", "Classes menu human next", humanclass, nexthumanname); + Format(humanselect, sizeof(humanselect), "%t\n %t\n %t", "Classes menu select human", "Classes menu active", humanclass, "Classes menu next", nexthumanname); } else { // Use current class name and format item text. - Format(humanselect, sizeof(humanselect), "%t", "Classes menu human current", humanclass); + Format(humanselect, sizeof(humanselect), "%t\n %s", "Classes menu select human", humanclass); } // Add item to list. @@ -144,17 +144,17 @@ ClassMenuMain(client) // Get current class name. ClassGetName(ClassSelected[client][ZR_CLASS_TEAM_ADMINS], adminclass, sizeof(adminclass), ZR_CLASS_CACHE_MODIFIED); - // Check if previous index is set. + // Check if next index is set. if (ClassValidateIndex(nextadmin)) { // Get name of previous class index and format item text. ClassGetName(nextadmin, nextadminname, sizeof(nextadminname), ZR_CLASS_CACHE_MODIFIED); - Format(adminselect, sizeof(adminselect), "%t", "Classes menu admin next", adminclass, nextadminname); + Format(adminselect, sizeof(adminselect), "%t\n %t\n %t", "Classes menu select admin", "Classes menu active", adminclass, "Classes menu next", nextadminname); } else { // Use current class name and format item text. - Format(adminselect, sizeof(adminselect), "%t", "Classes menu admin current", adminclass); + Format(adminselect, sizeof(adminselect), "%t\n %s", "Classes menu select admin", adminclass); } // Add item to list. @@ -260,15 +260,15 @@ ClassMenuSelect(client, teamid) { case ZR_CLASS_TEAM_ZOMBIES: { - Format(title, sizeof(title), "%t\n", "Classes menu zombie"); + Format(title, sizeof(title), "%t:\n", "Classes menu select zombie"); } case ZR_CLASS_TEAM_HUMANS: { - Format(title, sizeof(title), "%t\n", "Classes menu human"); + Format(title, sizeof(title), "%t:\n", "Classes menu select human"); } case ZR_CLASS_TEAM_ADMINS: { - Format(title, sizeof(title), "%t\n", "Classes menu admin"); + Format(title, sizeof(title), "%t:\n", "Classes menu select admin"); } } SetMenuTitle(menu, title); @@ -364,8 +364,18 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot) (!iszombie && teamid == ZR_CLASS_TEAM_HUMANS) || (ClassPlayerInAdminMode[client] && teamid == ZR_CLASS_TEAM_ADMINS)) { - // Set class to be used on next spawn. - ClassSelectedNext[client][teamid] = classindex; + // 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 { From 89685d17dfa28e6e7831f49c93c1a78c70342aa2 Mon Sep 17 00:00:00 2001 From: richard Date: Sat, 15 Aug 2009 01:33:54 +0200 Subject: [PATCH 09/16] Fixed typo in norwegian translations. --- .../addons/sourcemod/translations/no/zombiereloaded.phrases.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt index 9954212..1e5eb3b 100644 --- a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt @@ -248,7 +248,7 @@ "Classes Menu Team Select Title" { - "no" "velg lag:" + "no" "Velg lag:" } "Classes Menu Zombies" From 32828a917934e8839ebf722a4411f66c7b9636c3 Mon Sep 17 00:00:00 2001 From: richard Date: Sat, 15 Aug 2009 02:58:49 +0200 Subject: [PATCH 10/16] Changed class configs to use yes/no. --- .../sourcemod/configs/zr/playerclasses.txt | 110 +++++++++--------- docs/zr_manual.txt | 10 +- src/zr/playerclasses/playerclasses.inc | 20 ++-- 3 files changed, 70 insertions(+), 70 deletions(-) diff --git a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt index ea6be44..1640aad 100644 --- a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt +++ b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt @@ -10,12 +10,12 @@ // // Attribute: Values: Description: // ---------------------------------------------------------------------------- -// enabled 0/1 Enables or disables a class. +// enabled yes/no Enables or disables a class. // team number Specifies what team the class belongs to: // 0 - Zombies // 1 - Humans // 2 - Admin mode classes (incomplete feautre!) -// team_default 0/1 Marks the class as the default class in the team. +// team_default yes/no Marks the class as the default class in the team. // flags number Special class flags (bit field). To combine multiple flags // use a sum of the flag values. Available flags: // 1 - Admins only @@ -28,13 +28,13 @@ // alpha_damaged number Transparency when damaged. // alpha_damage number How much damage to do before switching alpha. // overlay_path text Overlay displayed at the player. -// nvgs 0/1 Give night vision. +// nvgs yes/no Give night vision. // fov number Field of view value. 90 is default. -// has_napalm 0/1 Allows player to throw napalm grenades. Humans only. +// has_napalm yes/no Allows player to throw napalm grenades. Humans only. // napalm_time decimal Napalm burn duration. Zombies only. // immunity_mode number Sets the immunity mode. // immunity_amount decimal Sets the immunity value. -// no_fall_damage 0/1 Disables fall damage. +// no_fall_damage on/off Disables fall damage. // health number How many health points to give. // health_regen_interval decimal Sets the regeneration interval. 0 to disable. // health_regen_amount number How much HP to give per interval. @@ -55,9 +55,9 @@ "zombie_classic" { // General - "enabled" "1" + "enabled" "yes" "team" "0" - "team_default" "1" + "team_default" "yes" "flags" "0" "group" "" @@ -72,17 +72,17 @@ // Hud "overlay_path" "overlays/zr/zvision" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "0" + "has_napalm" "no" "napalm_time" "10.0" // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "2500" "health_regen_interval" "0.0" @@ -99,9 +99,9 @@ "zombie_fast" { // General - "enabled" "1" + "enabled" "yes" "team" "0" - "team_default" "0" + "team_default" "no" "flags" "0" "group" "" @@ -116,17 +116,17 @@ // Hud "overlay_path" "overlays/zr/zvision" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "0" + "has_napalm" "no" "napalm_time" "5.0" // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "2000" "health_regen_interval" "0.0" @@ -143,9 +143,9 @@ "zombie_mutated" { // General - "enabled" "1" + "enabled" "yes" "team" "0" - "team_default" "0" + "team_default" "no" "flags" "0" "group" "" @@ -160,17 +160,17 @@ // Hud "overlay_path" "overlays/zr/zvision" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "0" + "has_napalm" "no" "napalm_time" "15.0" // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "3500" "health_regen_interval" "0.0" @@ -187,9 +187,9 @@ "zombie_heavy" { // General - "enabled" "1" + "enabled" "yes" "team" "0" - "team_default" "0" + "team_default" "no" "flags" "0" "group" "" @@ -204,17 +204,17 @@ // Hud "overlay_path" "overlays/zr/zvision" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "0" + "has_napalm" "no" "napalm_time" "20.0" // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "4000" "health_regen_interval" "0.0" @@ -231,9 +231,9 @@ "mother_zombie" { // General - "enabled" "1" + "enabled" "yes" "team" "0" - "team_default" "0" + "team_default" "no" "flags" "2" "group" "" @@ -248,7 +248,7 @@ // Hud "overlay_path" "overlays/zr/zvision" - "nvgs" "0" + "nvgs" "no" "fov" "110" // Effects @@ -258,7 +258,7 @@ // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "2500" "health_regen_interval" "0.25" @@ -275,9 +275,9 @@ "mother_zombie_admin" { // General - "enabled" "1" + "enabled" "yes" "team" "0" - "team_default" "0" + "team_default" "no" "flags" "3" "group" "" @@ -292,7 +292,7 @@ // Hud "overlay_path" "overlays/zr/zvision" - "nvgs" "0" + "nvgs" "no" "fov" "110" // Effects @@ -302,7 +302,7 @@ // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "3500" "health_regen_interval" "0.25" @@ -325,9 +325,9 @@ "human_normal" { // General - "enabled" "1" + "enabled" "yes" "team" "1" - "team_default" "1" + "team_default" "yes" "flags" "0" "group" "" @@ -342,17 +342,17 @@ // Hud "overlay_path" "" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "1" + "has_napalm" "yes" "napalm_time" "0.0" // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "0" + "no_fall_damage" "no" "health" "100" "health_regen_interval" "0.0" @@ -369,9 +369,9 @@ "human_vip" { // General - "enabled" "1" + "enabled" "yes" "team" "1" - "team_default" "0" + "team_default" "yes" "flags" "0" "group" "" @@ -386,7 +386,7 @@ // Hud "overlay_path" "" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects @@ -396,7 +396,7 @@ // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "0" + "no_fall_damage" "no" "health" "200" "health_regen_interval" "1.0" @@ -413,9 +413,9 @@ "human_admin" { // General - "enabled" "1" + "enabled" "yes" "team" "1" - "team_default" "0" + "team_default" "no" "flags" "1" "group" "" @@ -430,7 +430,7 @@ // Hud "overlay_path" "" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects @@ -440,7 +440,7 @@ // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "1" + "no_fall_damage" "yes" "health" "200" "health_regen_interval" "1.0" @@ -457,9 +457,9 @@ "human_speedy" { // General - "enabled" "1" + "enabled" "yes" "team" "1" - "team_default" "0" + "team_default" "no" "flags" "0" "group" "" @@ -474,11 +474,11 @@ // Hud "overlay_path" "" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "0" + "has_napalm" "no" "napalm_time" "0.0" // Player behaviour @@ -501,9 +501,9 @@ "human_light" { // General - "enabled" "1" + "enabled" "yes" "team" "1" - "team_default" "0" + "team_default" "no" "flags" "0" "group" "" @@ -518,17 +518,17 @@ // Hud "overlay_path" "" - "nvgs" "0" + "nvgs" "no" "fov" "90" // Effects - "has_napalm" "1" + "has_napalm" "yes" "napalm_time" "0.0" // Player behaviour "immunity_mode" "0" "immunity_amount" "0.0" - "no_fall_damage" "0" + "no_fall_damage" "no" "health" "100" "health_regen_interval" "0.0" diff --git a/docs/zr_manual.txt b/docs/zr_manual.txt index 3ac1f1c..a9d2670 100644 --- a/docs/zr_manual.txt +++ b/docs/zr_manual.txt @@ -604,7 +604,7 @@ The list below explains all available class attributes in detail: Attribute: Value type: Limits/Requirements: =========================================================================== - enabled boolean 0 or 1 + enabled text "yes" or "no" --------------------------------------------------------------------------- Enables or disables the class. Disabled classes won't show up in the class selection menus. Also, if some attributes failed to validate the @@ -627,7 +627,7 @@ The list below explains all available class attributes in detail: See the "flags" attribute for admin-only classes. - team_default boolean 0 or 1 + team_default text "yes" or "no" --------------------------------------------------------------------------- Marks the class as the default class for its specified team. This class will be automatically selected on new players when they join the @@ -699,7 +699,7 @@ The list below explains all available class attributes in detail: controlled by the night vision key ("n" by default). The path is relative to "cstrike/materials". Leave blank to disable. - nvgs boolean 0 or 1 + nvgs text "yes" or "no" --------------------------------------------------------------------------- Gives night vision to the player. @@ -708,7 +708,7 @@ The list below explains all available class attributes in detail: The field of view on the player. Note that the weapon hud disappear if FOV is anything else than 90. - has_napalm boolean 0 or 1 + has_napalm text "yes" or "no" --------------------------------------------------------------------------- Human classes only. Specifies whether the human can trow napalm grenades or not. @@ -730,7 +730,7 @@ The list below explains all available class attributes in detail: The value for the specified immunity mode. This feature is currently incomplete and values are ignored. - no_fall_damage boolean 0 or 1 + no_fall_damage text "yes" or "no" --------------------------------------------------------------------------- Blocks fall damage on the player. diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 65915aa..85c9be9 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -100,9 +100,9 @@ * @section Overall default class settings. Since this is a zombie plugin the * default values represent a zombie. */ -#define ZR_CLASS_DEFAULT_ENABLED true +#define ZR_CLASS_DEFAULT_ENABLED "yes" #define ZR_CLASS_DEFAULT_TEAM ZR_CLASS_TEAM_ZOMBIES -#define ZR_CLASS_DEFAULT_TEAM_DEFAULT true +#define ZR_CLASS_DEFAULT_TEAM_DEFAULT "yes" #define ZR_CLASS_DEFAULT_FLAGS 0 #define ZR_CLASS_DEFAULT_GROUP "" #define ZR_CLASS_DEFAULT_NAME "classic" @@ -112,13 +112,13 @@ #define ZR_CLASS_DEFAULT_ALPHA_DAMAGED 255 #define ZR_CLASS_DEFAULT_ALPHA_DAMAGE 0 #define ZR_CLASS_DEFAULT_OVERLAY_PATH "overlays/zr/zvision" -#define ZR_CLASS_DEFAULT_NVGS true +#define ZR_CLASS_DEFAULT_NVGS "no" #define ZR_CLASS_DEFAULT_FOV 90 -#define ZR_CLASS_DEFAULT_HAS_NAPALM 1 +#define ZR_CLASS_DEFAULT_HAS_NAPALM "yes" #define ZR_CLASS_DEFAULT_NAPALM_TIME 10.0 #define ZR_CLASS_DEFAULT_IMMUNITY_MODE ZR_CLASS_IMMUNITY_DISABLED #define ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT 0.0 -#define ZR_CLASS_DEFAULT_NO_FALL_DAMAGE true +#define ZR_CLASS_DEFAULT_NO_FALL_DAMAGE "on" #define ZR_CLASS_DEFAULT_HEALTH 6000 #define ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL 0.0 #define ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT 2 @@ -495,9 +495,9 @@ ClassLoad(bool:keepMultipliers = false) } /* General */ - ClassData[ClassCount][Class_Enabled] = bool:KvGetNum(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED); + ClassData[ClassCount][Class_Enabled] = ConfigKvGetStringBool(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED); ClassData[ClassCount][Class_Team] = KvGetNum(kvClassData, "team", ZR_CLASS_DEFAULT_TEAM); - ClassData[ClassCount][Class_TeamDefault] = bool:KvGetNum(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT); + ClassData[ClassCount][Class_TeamDefault] = ConfigKvGetStringBool(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT); ClassData[ClassCount][Class_Flags] = KvGetNum(kvClassData, "flags", ZR_CLASS_DEFAULT_FLAGS); KvGetString(kvClassData, "group", group, sizeof(group), ZR_CLASS_DEFAULT_GROUP); @@ -523,19 +523,19 @@ ClassLoad(bool:keepMultipliers = false) KvGetString(kvClassData, "overlay_path", overlay_path, sizeof(overlay_path), ZR_CLASS_DEFAULT_OVERLAY_PATH); strcopy(ClassData[ClassCount][Class_OverlayPath], PLATFORM_MAX_PATH, overlay_path); - ClassData[ClassCount][Class_Nvgs] = bool:KvGetNum(kvClassData, "nvgs", ZR_CLASS_DEFAULT_NVGS); + ClassData[ClassCount][Class_Nvgs] = ConfigKvGetStringBool(kvClassData, "nvgs", ZR_CLASS_DEFAULT_NVGS); ClassData[ClassCount][Class_Fov] = KvGetNum(kvClassData, "fov", ZR_CLASS_DEFAULT_FOV); /* Effects */ - ClassData[ClassCount][Class_HasNapalm] = bool:KvGetNum(kvClassData, "have_napalm", ZR_CLASS_DEFAULT_HAS_NAPALM); + ClassData[ClassCount][Class_HasNapalm] = ConfigKvGetStringBool(kvClassData, "have_napalm", ZR_CLASS_DEFAULT_HAS_NAPALM); ClassData[ClassCount][Class_NapalmTime] = KvGetFloat(kvClassData, "napalm_time", ZR_CLASS_DEFAULT_NAPALM_TIME); /* Player behaviour */ ClassData[ClassCount][Class_ImmunityMode] = KvGetNum(kvClassData, "immunity_mode", ZR_CLASS_DEFAULT_IMMUNITY_MODE); ClassData[ClassCount][Class_ImmunityAmount] = KvGetFloat(kvClassData, "immunity_amount", ZR_CLASS_DEFAULT_IMMUNITY_AMOUNT); - ClassData[ClassCount][Class_NoFallDamage] = bool:KvGetNum(kvClassData, "no_fall_damage", ZR_CLASS_DEFAULT_NO_FALL_DAMAGE); + ClassData[ClassCount][Class_NoFallDamage] = ConfigKvGetStringBool(kvClassData, "no_fall_damage", ZR_CLASS_DEFAULT_NO_FALL_DAMAGE); ClassData[ClassCount][Class_Health] = KvGetNum(kvClassData, "health", ZR_CLASS_DEFAULT_HEALTH); ClassData[ClassCount][Class_HealthRegenInterval] = KvGetFloat(kvClassData, "health_regen_interval", ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL); From daadefbaeafbe7f825fff8e3035613bbdf3a88b0 Mon Sep 17 00:00:00 2001 From: richard Date: Sat, 15 Aug 2009 03:33:09 +0200 Subject: [PATCH 11/16] Added nochange option in class model attribute. --- docs/zr_manual.txt | 9 ++++++--- src/zr/playerclasses/apply.inc | 13 ++++++++----- src/zr/playerclasses/filtertools.inc | 6 ++++-- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/docs/zr_manual.txt b/docs/zr_manual.txt index a9d2670..f4757e4 100644 --- a/docs/zr_manual.txt +++ b/docs/zr_manual.txt @@ -673,10 +673,13 @@ The list below explains all available class attributes in detail: model_path text Max 256 characters, not empty --------------------------------------------------------------------------- The model file to use on the player, path is relative to the "cstrike" - folder. There are two special values supported by this attribute: + folder. There are a few special values supported by this attribute: - "default" - Don't change model, use default CS models. - "random" - Selects a random model for the current team. + "default" - Use default CS models. The one players select when + selecting team. + "random" - Selects a random model for the current team. + "nochange" - Don't change model. To be used in combination with + other plugins that change model on players. alpha_spawn number 0 - 255 --------------------------------------------------------------------------- diff --git a/src/zr/playerclasses/apply.inc b/src/zr/playerclasses/apply.inc index 45fd0bd..5c622f8 100644 --- a/src/zr/playerclasses/apply.inc +++ b/src/zr/playerclasses/apply.inc @@ -89,16 +89,14 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) ClassGetModelPath(classindex, modelpath, sizeof(modelpath), cachetype); } - // Check if the user specified a random model. - if (strcmp(modelpath, "random", false) == 0) + // Check if the user specified a pre-defined model setting. + if (StrEqual(modelpath, "random", false)) { // TODO: Make a function that gets a random model from the specified team. ModelsGetRandomModelIndex(modelpath, sizeof(modelpath), false, true); Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath); } - - // Check if the user specified no change. - else if (strcmp(modelpath, "default", false) == 0) + else if (StrEqual(modelpath, "default", false)) { // Get current model. GetClientModel(client, modelpath, sizeof(modelpath)); @@ -114,6 +112,11 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) return true; } } + else if (StrEqual(modelpath, "nochange", false)) + { + // Do nothing. + return true; + } SetEntityModel(client, modelpath); return true; diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index f4d0d6a..c8ece10 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -162,8 +162,10 @@ stock ClassValidateAttributes(classindex) } else { - // Check if a model different from default or random is specified. - if (!StrEqual(model_path, "random", false) && !StrEqual(model_path, "default", false)) + // Check if a model different from a pre-defined setting. + if (!StrEqual(model_path, "random", false) && + !StrEqual(model_path, "default", false) && + !StrEqual(model_path, "nochange", false)) { // Check if the file exists. if (!FileExists(model_path)) From 2fc590ab59e0468eeb2e32b61f3869bf639f0bd1 Mon Sep 17 00:00:00 2001 From: richard Date: Sat, 15 Aug 2009 06:32:44 +0200 Subject: [PATCH 12/16] Added support for saving class selections in cookies. --- src/zr/cookies.inc | 34 ++++++- src/zr/playerclasses/classevents.inc | 5 + src/zr/playerclasses/classmenus.inc | 3 + src/zr/playerclasses/playerclasses.inc | 121 ++++++++++++++++++++----- 4 files changed, 140 insertions(+), 23 deletions(-) diff --git a/src/zr/cookies.inc b/src/zr/cookies.inc index 8c3c316..37069da 100644 --- a/src/zr/cookies.inc +++ b/src/zr/cookies.inc @@ -67,4 +67,36 @@ bool:CookiesGetClientCookieBool(client, Handle:cookie) // Return string casted into an int, then to bool. return bool:StringToInt(cookievalue); -} \ No newline at end of file +} + +/** + * Sets a integer value on a cookie. + * + * @param client The client index. + * @param cookie The handle to the cookie. + * @param value The value to set. + */ +CookiesSetInt(client, Handle:cookie, value) +{ + // Convert value to string. + decl String:strValue[16]; + IntToString(value, strValue, sizeof(strValue)); + + // Set string value. + SetClientCookie(client, cookie, strValue); +} + +/** + * Gets a integer value from a cookie. + * + * @param client The client index. + * @param cookie The handle to the cookie. + */ +CookiesGetInt(client, Handle:cookie) +{ + decl String:strValue[16]; + strValue[0] = 0; + GetClientCookie(client, cookie, strValue, sizeof(strValue)); + + return StringToInt(strValue); +} diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc index 60ecf83..9788419 100644 --- a/src/zr/playerclasses/classevents.inc +++ b/src/zr/playerclasses/classevents.inc @@ -24,6 +24,11 @@ ClassOnCookiesCreate() { // Forward event to sub-modules. ClassOverlayOnCookiesCreate(); + + // Create class index cookies. + g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS] = RegClientCookie("zr_humanclass", "The last human class selected.", CookieAccess_Protected); + g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES] = RegClientCookie("zr_zombieclass", "The last zombie class selected.", CookieAccess_Protected); + g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS] = RegClientCookie("zr_adminclass", "The last admin mode class selected.", CookieAccess_Protected); } /** diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index de2cda8..a32c894 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -388,6 +388,9 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot) // Player isn't alive. The class can be directly changed. ClassSelected[client][teamid] = classindex; } + + // Save selected class index in cookie. + CookiesSetInt(client, g_hClassCookieClassSelected[teamid], classindex + 1); } } case MenuAction_Cancel: diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 85c9be9..2d84994 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -390,6 +390,11 @@ new ClassSelectedNext[MAXPLAYERS + 1][ZR_CLASS_TEAMCOUNT]; */ new ClassAdminTeamSelected[MAXPLAYERS + 1]; +/** + * Cookies for storing class indexes. + */ +new Handle:g_hClassCookieClassSelected[ZR_CLASS_TEAMCOUNT]; + /** * Cache for the currently selected attribute multiplier (admin menus). */ @@ -920,38 +925,94 @@ ClassRestoreNextIndexes(client, excludeTeam = -1) * Sets default class indexes for each team on all players, or a single player * if specified. * - * @param client Optional. The client index. + * @param client Optional. The client index. If specified, cookies are used. */ ClassClientSetDefaultIndexes(client = -1) { - // Get indexes. - new zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES); - new humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS); - new adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS); + new bool:clientvalid = ZRIsClientValid(client); + new zombieindex; + new humanindex; + new adminindex; - // Validate zombie class index. + new bool:haszombie; + new bool:hashuman; + new bool:hasadmin; + + // Check if a client is specified. + if (clientvalid) + { + // Get cookie indexes. + zombieindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES]); + humanindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS]); + adminindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS]); + + // Note: When class indexes are set on cookies, they're incremented by + // one so zero means no class set and will result in a invalid + // class index when restored. + + // Check if class indexes are set. If not, fall back to default class + // indexes. Otherwise substract index by one. + if (zombieindex <= 0) + { + zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES); + } + else + { + zombieindex--; + haszombie = true; + } + + if (humanindex <= 0) + { + humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS); + } + else + { + humanindex--; + hashuman = true; + } + + if (adminindex <= 0) + { + adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS); + } + else + { + adminindex--; + hasadmin = true; + } + } + else + { + // Get default class indexes. + zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES); + humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS); + adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS); + } + + // Validate indexes. if (!ClassValidateIndex(zombieindex)) { // Invalid class index. Fall back to default class in class config and // log a warning. - LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get default zombie class, falling back to default class in class config. Check spelling in \"zr_classes_default_zombie\"."); + LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get specified zombie class, falling back to default class in class config. Check spelling in \"zr_classes_default_zombie\"."); // Use default class. zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES); } - // Validate human class index. + // Get human class index. if (!ClassValidateIndex(humanindex)) { // Invalid class index. Fall back to default class in class config and // log a warning. - LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get default human class, falling back to default class in class config. Check spelling in \"zr_classes_default_human\"."); + LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get specified human class, falling back to default class in class config. Check spelling in \"zr_classes_default_human\"."); // Use default class. humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS); } - // Validate admin class index. + // Get admin class index. if (!ClassValidateIndex(adminindex)) { // Invalid class index. Fall back to default class in class config if @@ -960,12 +1021,37 @@ ClassClientSetDefaultIndexes(client = -1) adminindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ADMINS); } - // Check if a client isn't specified. - if (client < 1) + // Check if a client is specified. + if (clientvalid) + { + // Set selected class idexes. + ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = zombieindex; + ClassSelected[client][ZR_CLASS_TEAM_HUMANS] = humanindex; + ClassSelected[client][ZR_CLASS_TEAM_ADMINS] = adminindex; + + // Copy human class data to player cache. + ClassReloadPlayerCache(client, humanindex); + + // Save indexes in cookies if not already saved. + if (!haszombie) + { + CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES], zombieindex + 1); + } + if (!hashuman) + { + CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS], humanindex + 1); + } + if (!hasadmin) + { + CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS], adminindex + 1); + } + } + else { // No client specified. Loop through all players. - for (new clientindex = 1; clientindex <= MAXPLAYERS; clientindex++) + for (new clientindex = 1; clientindex <= MaxClients; clientindex++) { + // Set selected class idexes. ClassSelected[clientindex][ZR_CLASS_TEAM_ZOMBIES] = zombieindex; ClassSelected[clientindex][ZR_CLASS_TEAM_HUMANS] = humanindex; ClassSelected[clientindex][ZR_CLASS_TEAM_ADMINS] = adminindex; @@ -974,15 +1060,6 @@ ClassClientSetDefaultIndexes(client = -1) ClassReloadPlayerCache(client, humanindex); } } - else - { - ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = zombieindex; - ClassSelected[client][ZR_CLASS_TEAM_HUMANS] = humanindex; - ClassSelected[client][ZR_CLASS_TEAM_ADMINS] = adminindex; - - // Copy human class data to player cache. - ClassReloadPlayerCache(client, humanindex); - } } /** From 855ffc3c0da632ef6ea8f5d6e3db28e53eb3fdf4 Mon Sep 17 00:00:00 2001 From: richard Date: Sat, 15 Aug 2009 17:37:30 +0200 Subject: [PATCH 13/16] Updated class filter to support filtering by classes with no groups set. Fixed default class assignment assigning classes players doesn't have access to. --- src/zr/playerclasses/filtertools.inc | 37 +++++++++++++++--------- src/zr/playerclasses/playerclasses.inc | 39 ++++++++++++++++---------- 2 files changed, 48 insertions(+), 28 deletions(-) diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index c8ece10..79f8656 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -485,26 +485,25 @@ stock bool:ClassFilterMatch(index, filter[ClassFilter], cachetype = ZR_CLASS_CAC return false; } - // Check class flags pass the flag filter. + // Check if class flags pass the flag filter. if (!ClassFlagFilterMatch(index, filter[ClassFilter_RequireFlags], filter[ClassFilter_DenyFlags], cachetype)) { return false; } + // Get class group name. + decl String:groupname[64]; + groupname[0] = 0; + ClassGetGroup(index, groupname, sizeof(groupname), cachetype); + // Check if a client is specified in the filter. new client = filter[ClassFilter_Client]; if (ZRIsClientValid(client)) { - // Get class group name. - decl String:groupname[64]; - groupname[0] = 0; - ClassGetGroup(index, groupname, sizeof(groupname), cachetype); - - // Check if a group is set on the class. Note: This group name is - // validated when classes are loaded. + // Check if a group is set on the class. if (strlen(groupname)) { - // Check if the client is a member of that group. + // Check if the client is not a member of that group. if (!ZRIsClientInGroup(client, groupname)) { return false; @@ -512,6 +511,16 @@ stock bool:ClassFilterMatch(index, filter[ClassFilter], cachetype = ZR_CLASS_CAC } } + // Check if classes with groups are set to be excluded. + if (client < 0) + { + // Exclude class if it has a group name. + if (strlen(groupname)) + { + return false; + } + } + // The class passed the filter. return true; } @@ -921,6 +930,8 @@ stock ClassGetDefaultClass(teamid, filter[ClassFilter] = ClassNoSpecialClasses, * when players join the server. * * @param teamid The team ID. + * @param filter Optional. Structure with filter settings. Default is to + * deny classes with special flags (ZR_CLASS_SPECIALFLAGS). * @param cachetype Optional. Specifies what class cache to read from. Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. * ZR_CLASS_CACHE_MODIFIED (default) - Changed/newest class @@ -929,7 +940,7 @@ stock ClassGetDefaultClass(teamid, filter[ClassFilter] = ClassNoSpecialClasses, * successful. -1 on critical errors. Otherwise it will try to fall * back on the first class in the specified team. */ -stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetDefaultSpawnClass(teamid, filter[ClassFilter] = ClassNoSpecialClasses, cachetype = ZR_CLASS_CACHE_MODIFIED) { decl String:classname[64]; new classindex; @@ -964,7 +975,7 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Get a list of all classes with the specified team ID. Deny // classes with special flags. - classindex = ClassGetRandomClass(teamid, _, cachetype); + classindex = ClassGetRandomClass(teamid, filter, cachetype); // Validate the result, in case there were errors. if (ClassValidateIndex(classindex)) @@ -996,7 +1007,7 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) // The class index is invalid or the team IDs didn't match. // Because it's user input, we'll fall back to the first class // in the specified team, and log a warning. - classindex = ClassGetFirstClass(teamid, _, cachetype); + classindex = ClassGetFirstClass(teamid, filter, cachetype); LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Default Spawn Class", "Warning: Failed to set \"%s\" as default spawn class for team %d. The class doesn't exist or the team IDs doesn't match. Falling back to the first class in the team.", classname, teamid); @@ -1019,6 +1030,6 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) else { // Blank class name, get the default class and return the index. - return ClassGetDefaultClass(teamid, _, cachetype); + return ClassGetDefaultClass(teamid, filter, cachetype); } } diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 2d84994..abdb3c2 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -320,7 +320,7 @@ enum ClassFilter bool:ClassFilter_IgnoreEnabled, /** Ignore whether the class is disabled or not. */ ClassFilter_RequireFlags, /** Flags the classes must have set. */ ClassFilter_DenyFlags, /** Flags the classes cannot have set. */ - ClassFilter_Client /** The client to check for class group permissions. Use 0 or less to ignore group filter. */ + ClassFilter_Client /** The client to check for class group permissions. Use 0 to ignore group filter and negative to exclude classes with groups set. */ } /** @@ -930,6 +930,8 @@ ClassRestoreNextIndexes(client, excludeTeam = -1) ClassClientSetDefaultIndexes(client = -1) { new bool:clientvalid = ZRIsClientValid(client); + new filter[ClassFilter]; + new zombieindex; new humanindex; new adminindex; @@ -950,11 +952,15 @@ ClassClientSetDefaultIndexes(client = -1) // one so zero means no class set and will result in a invalid // class index when restored. - // Check if class indexes are set. If not, fall back to default class - // indexes. Otherwise substract index by one. - if (zombieindex <= 0) + // Setup filtering so group permission is checked on player first. + filter[ClassFilter_Client] = client; + + // Check if class indexes are set and that the client pass group + // permissions. If not, fall back to default class indexes. Otherwise + // substract index by one. + if (zombieindex <= 0 || !ClassFilterMatch(zombieindex, filter)) { - zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES); + zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES, filter); } else { @@ -962,9 +968,9 @@ ClassClientSetDefaultIndexes(client = -1) haszombie = true; } - if (humanindex <= 0) + if (humanindex <= 0 || !ClassFilterMatch(humanindex, filter)) { - humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS); + humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS, filter); } else { @@ -972,9 +978,9 @@ ClassClientSetDefaultIndexes(client = -1) hashuman = true; } - if (adminindex <= 0) + if (adminindex <= 0 || !ClassFilterMatch(adminindex, filter)) { - adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS); + adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS, filter); } else { @@ -984,10 +990,13 @@ ClassClientSetDefaultIndexes(client = -1) } else { + // Setup filtering so classes with groups set are excluded. + filter[ClassFilter_Client] = -1; + // Get default class indexes. - zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES); - humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS); - adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS); + zombieindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ZOMBIES, filter); + humanindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_HUMANS, filter); + adminindex = ClassGetDefaultSpawnClass(ZR_CLASS_TEAM_ADMINS, filter); } // Validate indexes. @@ -998,7 +1007,7 @@ ClassClientSetDefaultIndexes(client = -1) LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get specified zombie class, falling back to default class in class config. Check spelling in \"zr_classes_default_zombie\"."); // Use default class. - zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES); + zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, filter); } // Get human class index. @@ -1009,7 +1018,7 @@ ClassClientSetDefaultIndexes(client = -1) LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Set Default Indexes", "Warning: Failed to get specified human class, falling back to default class in class config. Check spelling in \"zr_classes_default_human\"."); // Use default class. - humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS); + humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, filter); } // Get admin class index. @@ -1018,7 +1027,7 @@ ClassClientSetDefaultIndexes(client = -1) // Invalid class index. Fall back to default class in class config if // possible. A invalid class index (-1) can also be stored if there are // no admin classes at all. - adminindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ADMINS); + adminindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ADMINS, filter); } // Check if a client is specified. From 5591adfd257d700d42625906979ad93fa1dc0c86 Mon Sep 17 00:00:00 2001 From: richard Date: Sat, 15 Aug 2009 19:48:51 +0200 Subject: [PATCH 14/16] Added cvar for enabling/disabling class cookies. Fixed teleport not resetting velocity. --- .../zombiereloaded/zombiereloaded.cfg | 6 ++- docs/zr_manual.txt | 19 ++++++++ src/zr/cvars.inc | 4 +- src/zr/playerclasses/classmenus.inc | 7 ++- src/zr/playerclasses/playerclasses.inc | 45 ++++++++++++------- src/zr/ztele.inc | 2 +- 6 files changed, 63 insertions(+), 20 deletions(-) diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index 00261b9..7151e00 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -156,10 +156,14 @@ zr_classes_spawn "0" // Default: "0" zr_classes_random "0" -// Time limit to change class with instant change after spawning. Time is in seconds. Use 0 or negative to disable. +// Time limit to change human class with instant change after spawning. Time is in seconds. Use 0 or negative to disable. // Default: "20" zr_classes_change_timelimit "20" +// Save players' class selections in server cookies and restore when connecting. [Override: zr_classes_default_*] +// Default: "1" +zr_classes_save "1" + // Admin class assigned to admins on connect. ["random" = Random admin class | "" = Class config default] // Default: "random" zr_classes_default_admin "random" diff --git a/docs/zr_manual.txt b/docs/zr_manual.txt index f4757e4..34355e5 100644 --- a/docs/zr_manual.txt +++ b/docs/zr_manual.txt @@ -882,6 +882,25 @@ Class console variables: --------------------------------------------------------------------------- Assign random classes to all players each round. + This setting overrides zr_classes_save. + + Options: + 0 or 1 + + zr_classes_change_timelimit 20 + --------------------------------------------------------------------------- + The time limit to change human classes with instant change after + spawning. So humans don't have to set class before spawning. Time is in + seconds. + + zr_classes_save 1 + --------------------------------------------------------------------------- + Save players' class selections in server cookies. Class selections are + restored next time players connect. + + This setting overrides zr_classes_default_*, but on first-time + connecting players the default classes are assigned. + Options: 0 or 1 diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 02b9ec6..8108115 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -56,6 +56,7 @@ enum CvarsList Handle:CVAR_CLASSES_SPAWN, Handle:CVAR_CLASSES_RANDOM, Handle:CVAR_CLASSES_CHANGE_TIMELIMIT, + Handle:CVAR_CLASSES_SAVE, Handle:CVAR_CLASSES_DEFAULT_ZOMBIE, Handle:CVAR_CLASSES_DEFAULT_M_ZOMB, Handle:CVAR_CLASSES_DEFAULT_HUMAN, @@ -249,7 +250,8 @@ CvarsCreate() // General g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Re-display class selection menu every spawn."); g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_default_*]"); - g_hCvarsList[CVAR_CLASSES_CHANGE_TIMELIMIT] = CreateConVar("zr_classes_change_timelimit", "20", "Time limit to change class with instant change after spawning. Time is in seconds. Use 0 or negative to disable."); + g_hCvarsList[CVAR_CLASSES_CHANGE_TIMELIMIT] = CreateConVar("zr_classes_change_timelimit", "20", "Time limit to change human class with instant change after spawning. Time is in seconds. Use 0 or negative to disable."); + g_hCvarsList[CVAR_CLASSES_SAVE] = CreateConVar("zr_classes_save", "1", "Save players' class selections in server cookies and restore when connecting. [Override: zr_classes_default_*]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "random", "Zombie class assigned to players on connect. [\"random\" = Random zombie class | \"\" = Class config default]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "motherzombies","Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]"); g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. [\"random\" = Random human class | \"\" = Class config default]"); diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index a32c894..981032e 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -389,8 +389,11 @@ public ClassMenuSelectHandle(Handle:menu, MenuAction:action, client, slot) ClassSelected[client][teamid] = classindex; } - // Save selected class index in cookie. - CookiesSetInt(client, g_hClassCookieClassSelected[teamid], classindex + 1); + // Save selected class index in cookie if enabled. + if (GetConVarBool(g_hCvarsList[CVAR_CLASSES_SAVE])) + { + CookiesSetInt(client, g_hClassCookieClassSelected[teamid], classindex + 1); + } } } case MenuAction_Cancel: diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index abdb3c2..ba13f15 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -931,6 +931,7 @@ ClassClientSetDefaultIndexes(client = -1) { new bool:clientvalid = ZRIsClientValid(client); new filter[ClassFilter]; + new bool:saveclasses = GetConVarBool(g_hCvarsList[CVAR_CLASSES_SAVE]); new zombieindex; new humanindex; @@ -943,10 +944,21 @@ ClassClientSetDefaultIndexes(client = -1) // Check if a client is specified. if (clientvalid) { - // Get cookie indexes. - zombieindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES]); - humanindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS]); - adminindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS]); + // Get cookie indexes if enabled. + if (saveclasses) + { + zombieindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES]); + humanindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS]); + adminindex = CookiesGetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS]); + } + else + { + // Do not use indexes in cookies. Set invalid values so it will + // fall back to default class. + zombieindex = 0; + humanindex = 0; + adminindex = 0; + } // Note: When class indexes are set on cookies, they're incremented by // one so zero means no class set and will result in a invalid @@ -1041,18 +1053,21 @@ ClassClientSetDefaultIndexes(client = -1) // Copy human class data to player cache. ClassReloadPlayerCache(client, humanindex); - // Save indexes in cookies if not already saved. - if (!haszombie) + // Save indexes in cookies if enabled, and not already saved. + if (saveclasses) { - CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES], zombieindex + 1); - } - if (!hashuman) - { - CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS], humanindex + 1); - } - if (!hasadmin) - { - CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS], adminindex + 1); + if (!haszombie) + { + CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ZOMBIES], zombieindex + 1); + } + if (!hashuman) + { + CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_HUMANS], humanindex + 1); + } + if (!hasadmin) + { + CookiesSetInt(client, g_hClassCookieClassSelected[ZR_CLASS_TEAM_ADMINS], adminindex + 1); + } } } else diff --git a/src/zr/ztele.inc b/src/zr/ztele.inc index 33aec78..ca5d90e 100644 --- a/src/zr/ztele.inc +++ b/src/zr/ztele.inc @@ -233,7 +233,7 @@ bool:ZTeleClient(client, bool:force = false) ZTeleTeleportClient(client) { // Teleport client. - TeleportEntity(client, g_vecZTeleSpawn[client], NULL_VECTOR, NULL_VECTOR); + TeleportEntity(client, g_vecZTeleSpawn[client], NULL_VECTOR, Float:{0.0, 0.0, 0.0}); } /** From 6a9c49eced81a77ed21d9c4930d60e3755acc37e Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 18 Aug 2009 16:43:15 +0200 Subject: [PATCH 15/16] Fixed no fall damage class attribute not working on human classes. --- src/zr/damage.inc | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/zr/damage.inc b/src/zr/damage.inc index 008a218..1919db5 100644 --- a/src/zr/damage.inc +++ b/src/zr/damage.inc @@ -307,12 +307,6 @@ public ZRTools_Action:DamageOnTakeDamage(client, inflictor, attacker, Float:dama // Client was damaged by falling. else if (damagetype & DMG_CSS_FALL) { - // If client isn't a zombie, then allow damage. - if (!InfectIsClientInfected(client)) - { - return ZRTools_Continue; - } - // If class has "nofalldamage" disabled, then allow damage. new bool:blockfalldamage = ClassGetNoFallDamage(client); if (!blockfalldamage) From 6bffb0c947892198527cbe3ef2102a762a85f9e0 Mon Sep 17 00:00:00 2001 From: richard Date: Fri, 21 Aug 2009 04:35:29 +0200 Subject: [PATCH 16/16] Fixed typo in docs. --- docs/zr_manual.txt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/zr_manual.txt b/docs/zr_manual.txt index 34355e5..8de2262 100644 --- a/docs/zr_manual.txt +++ b/docs/zr_manual.txt @@ -770,13 +770,15 @@ The list below explains all available class attributes in detail: Zombie classes only. Force to apply on the zombie when shot at. The zombie is pushed in the same direction as the bullet. - jump_height decimal -500.0 - 500.0 + jump_height decimal 0.0 - 5.0 --------------------------------------------------------------------------- - Extra upward boost when jumping. + Jump height multiplier. Extra upward boost when jumping. If 1.0 or 0.0 + no boost will be applied. - jump_distance decimal -500.0 - 500.0 + jump_distance decimal 0.0 - 5.0 --------------------------------------------------------------------------- - Extra forward boost when jumping. + Jump distance multiplier. Extra forward boost when jumping. If 1.0 or + 0.0 no boost will be applied. 3.7.3 CLASS REQUIREMENTS