Implemented group class attribute. Improved filtering method for class functions.

This commit is contained in:
richard 2009-08-14 22:10:52 +02:00
parent 6a14b952af
commit d1cbda40c4
5 changed files with 204 additions and 100 deletions

View File

@ -20,6 +20,7 @@
// use a sum of the flag values. Available flags: // use a sum of the flag values. Available flags:
// 1 - Admins only // 1 - Admins only
// 2 - Mother zombies 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. // name text The class name used in class menu.
// description text The class description 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. // model_path text Path to model to use. Relative to cstrike folder.
@ -58,6 +59,7 @@
"team" "0" "team" "0"
"team_default" "1" "team_default" "1"
"flags" "0" "flags" "0"
"group" ""
"name" "Classic" "name" "Classic"
"description" "Need brains!!! Arrrrggghh!" "description" "Need brains!!! Arrrrggghh!"
@ -101,6 +103,7 @@
"team" "0" "team" "0"
"team_default" "0" "team_default" "0"
"flags" "0" "flags" "0"
"group" ""
"name" "Fast" "name" "Fast"
"description" "-HP | +Speed | +Jump | +Knockback" "description" "-HP | +Speed | +Jump | +Knockback"
@ -144,6 +147,7 @@
"team" "0" "team" "0"
"team_default" "0" "team_default" "0"
"flags" "0" "flags" "0"
"group" ""
"name" "Mutated" "name" "Mutated"
"description" "+HP | -Speed | +Jump | +Knockback" "description" "+HP | -Speed | +Jump | +Knockback"
@ -187,6 +191,7 @@
"team" "0" "team" "0"
"team_default" "0" "team_default" "0"
"flags" "0" "flags" "0"
"group" ""
"name" "Heavy" "name" "Heavy"
"description" "+HP | -Speed | -Jump | -Knockback" "description" "+HP | -Speed | -Jump | -Knockback"
@ -230,6 +235,7 @@
"team" "0" "team" "0"
"team_default" "0" "team_default" "0"
"flags" "2" "flags" "2"
"group" ""
"name" "Mother zombie" "name" "Mother zombie"
"description" "+HP regen | +Speed | +Jump | -Knockback" "description" "+HP regen | +Speed | +Jump | -Knockback"
@ -273,6 +279,7 @@
"team" "0" "team" "0"
"team_default" "0" "team_default" "0"
"flags" "3" "flags" "3"
"group" ""
"name" "Admin mother zombie" "name" "Admin mother zombie"
"description" "+HP regen | +Speed | +Jump | -Knockback" "description" "+HP regen | +Speed | +Jump | -Knockback"
@ -322,6 +329,7 @@
"team" "1" "team" "1"
"team_default" "1" "team_default" "1"
"flags" "0" "flags" "0"
"group" ""
"name" "Normal Human" "name" "Normal Human"
"description" "Default Counter-Strike settings" "description" "Default Counter-Strike settings"
@ -365,6 +373,7 @@
"team" "1" "team" "1"
"team_default" "0" "team_default" "0"
"flags" "0" "flags" "0"
"group" ""
"name" "VIP Human" "name" "VIP Human"
"description" "Human class for important players" "description" "Human class for important players"
@ -408,6 +417,7 @@
"team" "1" "team" "1"
"team_default" "0" "team_default" "0"
"flags" "1" "flags" "1"
"group" ""
"name" "Admin Human" "name" "Admin Human"
"description" "Human class for admins" "description" "Human class for admins"
@ -451,6 +461,7 @@
"team" "1" "team" "1"
"team_default" "0" "team_default" "0"
"flags" "0" "flags" "0"
"group" ""
"name" "Speedy" "name" "Speedy"
"description" "Fast human" "description" "Fast human"
@ -494,6 +505,7 @@
"team" "1" "team" "1"
"team_default" "0" "team_default" "0"
"flags" "0" "flags" "0"
"group" ""
"name" "Light" "name" "Light"
"description" "Regular human with improved jump skills" "description" "Regular human with improved jump skills"

View File

@ -75,6 +75,7 @@ ClassOnClientSpawn(client)
decl String:originalmodel[PLATFORM_MAX_PATH]; decl String:originalmodel[PLATFORM_MAX_PATH];
decl String:steamid[16]; decl String:steamid[16];
decl String:classname[64]; decl String:classname[64];
new filter[ClassFilter];
// Check if the player is dead. Spawning into the game is also a event in // Check if the player is dead. Spawning into the game is also a event in
// the connection process. // the connection process.
@ -121,15 +122,24 @@ ClassOnClientSpawn(client)
// Assign random classes if enabled. Always do it for bots. // Assign random classes if enabled. Always do it for bots.
if (randomclass || StrEqual(steamid, "BOT")) if (randomclass || StrEqual(steamid, "BOT"))
{ {
// Setup filtering
// ---------------
// Exclude special class flags like mother zombies and admin classes. // Exclude special class flags like mother zombies and admin classes.
new denyflags = ZR_CLASS_SPECIALFLAGS; filter[ClassFilter_DenyFlags] = ZR_CLASS_SPECIALFLAGS;
// Allow admin classes if admin. // 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. // Get random classes for each type.
new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, denyflags); new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, filter);
new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, _, _, denyflags); new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, filter);
// Set selected zombie class index. // Set selected zombie class index.
ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = randomzombie; ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = randomzombie;
@ -199,6 +209,7 @@ ClassOnClientInfected(client, bool:motherzombie = false)
new classindex = ClassGetActiveIndex(client); new classindex = ClassGetActiveIndex(client);
new isadmin; new isadmin;
new motherindex; new motherindex;
new filter[ClassFilter];
decl String:motherzombiesetting[64]; decl String:motherzombiesetting[64];
@ -224,8 +235,23 @@ ClassOnClientInfected(client, bool:motherzombie = false)
} }
else if (StrEqual(motherzombiesetting, "random", 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. // 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. // Validate index. Do not change class if it's invalid.
if (ClassValidateIndex(motherindex)) if (ClassValidateIndex(motherindex))
@ -239,8 +265,26 @@ ClassOnClientInfected(client, bool:motherzombie = false)
} }
else if (StrEqual(motherzombiesetting, "motherzombies", 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. // 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. // Validate index. Do not change class if it's invalid.
if (ClassValidateIndex(motherindex)) if (ClassValidateIndex(motherindex))

View File

@ -247,7 +247,6 @@ ClassMenuSelect(client, teamid)
new Handle:menu = CreateMenu(ClassMenuSelectHandle); new Handle:menu = CreateMenu(ClassMenuSelectHandle);
new arraycount; new arraycount;
new classindex; new classindex;
new denyflags;
decl String:title[MENU_LINE_TITLE_LENGTH]; decl String:title[MENU_LINE_TITLE_LENGTH];
decl String:classname[MENU_LINE_REG_LENGTH]; decl String:classname[MENU_LINE_REG_LENGTH];
@ -277,12 +276,24 @@ ClassMenuSelect(client, teamid)
// Create buffer array. // Create buffer array.
new Handle:classarray = CreateArray(); new Handle:classarray = CreateArray();
// Set up filtering. // 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. 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. // 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. // Get number of classes.
arraycount = GetArraySize(classarray); arraycount = GetArraySize(classarray);

View File

@ -47,8 +47,8 @@ stock bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL)
} }
// Test if a zombie and human class was found. // Test if a zombie and human class was found.
zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, cachetype);
humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, cachetype);
// Validate indexes. // Validate indexes.
if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex)) 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. // Test if a default zombie and human class was found.
zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, _, _, cachetype); zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, cachetype);
humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, _, _, cachetype); humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, cachetype);
// Validate indexes. // Validate indexes.
if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex)) if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex))
@ -119,7 +119,14 @@ stock ClassValidateAttributes(classindex)
} }
// Group. // 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. // Name.
if (strlen(ClassData[classindex][Class_Name]) < ZR_CLASS_NAME_MIN) 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. * 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 array The destination array to add class indexes.
* @param teamfilter Optional. The team ID to filter. A negative value * @param teamfilter Optional. The team ID to filter. A negative value
* for no filter (default). * for no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or * @param filter Optional. Structure with filter settings.
* 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 cachetype Optional. Specifies what class cache to read from. * @param cachetype Optional. Specifies what class cache to read from.
* Options: * Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. * 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 * @return True on success. False on error or if no classes were added or
* found. * 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. // Validate the array.
if (array == INVALID_HANDLE) 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. // 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 classes_added; new classesadded;
// Loop through all classes. // Loop through all classes.
for (new classindex = 0; classindex < ClassCount; classindex++) 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. // The class is didn't pass the filter, skip class.
// Skip to the next class.
continue;
}
// Check flag filter match.
if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype))
{
// The class didn't pass filter.
continue; continue;
} }
// Check team filtering. // Check team filtering.
if (has_filter) if (hasteamfilter)
{ {
// Only add classes with matching team ID. // Only add classes with matching team ID.
if (ClassGetTeamID(classindex, cachetype) == teamfilter) if (ClassGetTeamID(classindex, cachetype) == teamfilter)
{ {
// Team ID match. Add class index to array. // Team ID match. Add class index to array.
PushArrayCell(array, classindex); PushArrayCell(array, classindex);
classes_added++; classesadded++;
} }
} }
else else
{ {
// No filter. Add any class to the array. // No filter. Add any class to the array.
PushArrayCell(array, classindex); PushArrayCell(array, classindex);
classes_added++; classesadded++;
} }
} }
if (classes_added) if (classesadded)
{ {
return true; 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 * @param teamfilter Optional. The team ID to filter. Negative value for
* no filter (default). * no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or * @param filter Optional. Structure with filter settings.
* 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 cachetype Optional. Specifies what class cache to read from. * @param cachetype Optional. Specifies what class cache to read from.
* Options: * Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
@ -683,7 +726,7 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f
* class data. * class data.
* @return Number of total classes or classes in the specified team. * @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. // Check if there are no classes.
if (ClassCount == 0) 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. // 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; new count;
// Loop through all classes. // Loop through all classes.
for (new classindex = 0; classindex < ClassCount; classindex++) 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. // The class is didn't pass the filter, skip class.
// Skip to the next class.
continue;
}
// Check flag filter match.
if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype))
{
// The class didn't pass filter.
continue; continue;
} }
// Check team filtering. // Check team filtering.
if (has_filter) if (hasteamfilter)
{ {
// Only add classes with matching team ID. // Only add classes with matching team ID.
if (ClassGetTeamID(classindex, cachetype) == teamfilter) 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 * @param teamfilter Optional. The team ID to filter. A negative value
* for no filter (default). * for no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or * @param filter Optional. Structure with filter settings.
* 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 cachetype Optional. Specifies what class cache to read from. * @param cachetype Optional. Specifies what class cache to read from.
* Options: * Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data.
@ -751,7 +782,7 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags =
* class data. * class data.
* @return The class index if successful, or -1 on error. * @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 Handle:classarray;
new arraycount; new arraycount;
@ -761,7 +792,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requirefl
classarray = CreateArray(); classarray = CreateArray();
// Try to get a class list. // 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. // Get a random index from the new class array.
arraycount = GetArraySize(classarray); 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 * @param teamfilter Optional. The team ID to filter. A negative value
* for no filter (default). * for no filter (default).
* @param ignoreEnabled Optional. Ignore whether the class is enabled or * @param filter Optional. Structure with filter settings.
* 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 cachetype Optional. Specifies what class cache to read from. * @param cachetype Optional. Specifies what class cache to read from.
* Options: * Options:
* ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. * 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 * @return The first class index, or the first class index with the specified
* team ID. -1 on error. * 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. // Check if there are no classes.
if (ClassCount == 0) if (ClassCount == 0)
@ -808,26 +834,19 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla
return false; return false;
} }
new bool:has_filter = bool:(teamfilter >= 0); new bool:hasteamfilter = bool:(teamfilter >= 0);
// Loop through all classes. // Loop through all classes.
for (new classindex = 0; classindex < ClassCount; classindex++) 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. // The class is didn't pass the filter, skip class.
// Skip to the next class.
continue; continue;
} }
// Check flag filter match. if (hasteamfilter)
if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype))
{
// The class didn't pass filter.
continue;
}
if (has_filter)
{ {
if (teamfilter == ClassGetTeamID(classindex, cachetype)) 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. * Gets the first class marked as default for the specified team.
* *
* @param teamid The team ID. * @param teamid The team ID.
* @param ignoreEnabled Optional. Ignore whether the class is enabled or * @param filter Optional. Structure with filter settings. Default
* not. Default is false. * is to deny classes with special flags
* @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
* (ZR_CLASS_SPECIALFLAGS). * (ZR_CLASS_SPECIALFLAGS).
* @param cachetype Optional. Specifies what class cache to read from. * @param cachetype Optional. Specifies what class cache to read from.
* Options: * Options:
@ -863,7 +878,7 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requirefla
* class data. * class data.
* @return The first default class index. -1 on error. * @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 Handle:classarray;
new arraycount; new arraycount;
@ -872,7 +887,7 @@ stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0,
classarray = CreateArray(); classarray = CreateArray();
// Get all classes from the specified team. // 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. // Failed to get classes.
CloseHandle(classarray); CloseHandle(classarray);
@ -943,11 +958,11 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
if (strlen(classname) > 0) if (strlen(classname) > 0)
{ {
// Check if the user set "random" as default class. // 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 // Get a list of all classes with the specified team ID. Deny
// classes with special flags. // classes with special flags.
classindex = ClassGetRandomClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); classindex = ClassGetRandomClass(teamid, _, cachetype);
// Validate the result, in case there were errors. // Validate the result, in case there were errors.
if (ClassValidateIndex(classindex)) 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. // 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 // Because it's user input, we'll fall back to the first class
// in the specified team, and log a warning. // 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); 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 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; return -1;
} }
} }
@ -1001,6 +1017,6 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
else else
{ {
// Blank class name, get the default class and return the index. // Blank class name, get the default class and return the index.
return ClassGetDefaultClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); return ClassGetDefaultClass(teamid, _, cachetype);
} }
} }

View File

@ -312,6 +312,27 @@ enum ClassDataTypes
ClassDataType_String /** String value */ 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. * Keyvalue handle to store class data.
*/ */
@ -1006,7 +1027,7 @@ ClassDumpData(index, cachetype, String:buffer[], maxlen)
cellcount += StrCat(buffer, maxlen, attribute); cellcount += StrCat(buffer, maxlen, attribute);
ClassGetGroup(index, format_buffer, sizeof(format_buffer), cachetype); 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); cellcount += StrCat(buffer, maxlen, attribute);
ClassGetName(index, format_buffer, sizeof(format_buffer), cachetype); ClassGetName(index, format_buffer, sizeof(format_buffer), cachetype);