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);