2009-04-06 03:20:13 +02:00
/*
* ============================================================================
*
2009-07-05 08:49:23 +02:00
* Zombie : Reloaded
2009-04-06 03:20:13 +02:00
*
2009-06-12 05:51:26 +02:00
* File : filtertools . inc
* Type : Core
* Description : Class system tools ; validating , getting indexes or lists
*
* 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 < http :// www . gnu . org / licenses />.
2009-04-06 03:20:13 +02:00
*
* ============================================================================
*/
/**
* Validates the team requirements in a class cache and check that theres at
* least one class for each team . Minium team requirements are zombies and
2009-04-11 01:56:22 +02:00
* humans . The admin team is optinal and not validated .
2009-04-06 03:20:13 +02:00
*
* @ param cachetype Optional . Specifies what class cache to validate . Options :
* ZR_CLASS_CACHE_ORIGINAL ( default , unchanged class data ),
* ZR_CLASS_CACHE_MODIFIED ( modified class data ) .
* @ return True if validation was successful , false otherwise .
*/
2009-05-30 04:17:01 +02:00
stock bool : ClassValidateTeamRequirements ( cachetype = ZR_CLASS_CACHE_ORIGINAL )
2009-04-06 03:20:13 +02:00
{
new zombieindex ;
new humanindex ;
// Check if there are no classes.
if ( ClassCount == 0 )
{
return false ;
}
// Test if a zombie and human class was found.
2009-08-14 22:10:52 +02:00
zombieindex = ClassGetFirstClass ( ZR_CLASS_TEAM_ZOMBIES , _ , cachetype );
humanindex = ClassGetFirstClass ( ZR_CLASS_TEAM_HUMANS , _ , cachetype );
2009-04-06 03:20:13 +02:00
2009-04-11 01:56:22 +02:00
// Validate indexes.
if ( ClassValidateIndex ( zombieindex ) && ClassValidateIndex ( humanindex ))
2009-04-06 03:20:13 +02:00
{
return true ;
}
return false ;
}
2009-04-11 01:56:22 +02:00
/**
* Validates that there ' s a class marked as team default for each team .
*
* @ param cachetype Optional . Specifies what class cache to validate . Options :
* ZR_CLASS_CACHE_ORIGINAL ( default , unchanged class data ),
* ZR_CLASS_CACHE_MODIFIED ( modified class data ) .
* @ return True if validation was successful , false otherwise .
*/
2009-05-30 04:17:01 +02:00
stock bool : ClassValidateTeamDefaults ( cachetype = ZR_CLASS_CACHE_ORIGINAL )
2009-04-11 01:56:22 +02:00
{
new zombieindex ;
new humanindex ;
// Check if there are no classes.
if ( ClassCount == 0 )
{
return false ;
}
// Test if a default zombie and human class was found.
2009-08-14 22:10:52 +02:00
zombieindex = ClassGetDefaultClass ( ZR_CLASS_TEAM_ZOMBIES , _ , cachetype );
humanindex = ClassGetDefaultClass ( ZR_CLASS_TEAM_HUMANS , _ , cachetype );
2009-04-11 01:56:22 +02:00
// Validate indexes.
if ( ClassValidateIndex ( zombieindex ) && ClassValidateIndex ( humanindex ))
{
return true ;
}
else
{
return false ;
}
}
2009-04-06 03:20:13 +02:00
/**
* Validates all the class attributes in the original class data array , to
2009-04-07 04:44:37 +02:00
* check if they have invalid values . Boolean settings are not validated .
2009-04-06 03:20:13 +02:00
*
* @ param classindex The index of the class to validate .
2010-08-06 14:24:10 +02:00
* @ param logErrors Log invalid attributes .
2009-04-07 04:44:37 +02:00
* @ return A value with attribute error flags .
2009-04-06 03:20:13 +02:00
*/
2010-08-06 14:24:10 +02:00
stock ClassValidateAttributes ( classindex , bool : logErrors = false )
2009-04-06 03:20:13 +02:00
{
2009-04-07 04:44:37 +02:00
// TODO: Validate immunity mode and amount.
new flags ;
2009-06-14 19:10:30 +02:00
// Team.
2010-08-06 14:24:10 +02:00
new team = ClassData [ classindex ][ Class_Team ];
if ( team < ZR_CLASS_TEAM_MIN || team > ZR_CLASS_TEAM_MAX )
2009-06-14 19:10:30 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_TEAM ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid team at index %d: %d " , classindex , team );
}
2009-06-22 01:09:51 +02:00
}
// Class flags.
2010-08-06 14:24:10 +02:00
new class_flags = ClassData [ classindex ][ Class_Flags ];
if ( class_flags < ZR_CLASS_FLAGS_MIN || class_flags > ZR_CLASS_FLAGS_MAX )
2009-06-22 01:09:51 +02:00
{
flags += ZR_CLASS_FLAGS ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid flags at index %d: %d " , classindex , class_flags );
}
2009-06-14 19:10:30 +02:00
}
2009-08-13 18:31:21 +02:00
// Group.
2010-08-06 14:24:10 +02:00
decl String : group [ 64 ];
group [ 0 ] = 0 ;
if ( strcopy ( group , sizeof ( group ), ClassData [ classindex ][ Class_Group ]) > 0 )
2009-08-14 22:10:52 +02:00
{
// Check if the group exist.
2010-08-06 14:24:10 +02:00
if ( FindAdmGroup ( group ) == INVALID_GROUP_ID )
2009-08-14 22:10:52 +02:00
{
flags += ZR_CLASS_GROUP ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid group at index %d: \" %s \" " , classindex , group );
}
2009-08-14 22:10:52 +02:00
}
}
2009-08-13 18:31:21 +02:00
2009-04-07 04:44:37 +02:00
// Name.
2010-08-06 14:24:10 +02:00
decl String : name [ 64 ];
name [ 0 ] = 0 ;
if ( strcopy ( name , sizeof ( name ), ClassData [ classindex ][ Class_Name ]) < ZR_CLASS_NAME_MIN )
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_NAME ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Missing name at index %d. " , classindex );
}
2009-04-07 04:44:37 +02:00
}
2009-05-10 18:49:47 +02:00
else
{
2009-06-14 19:10:30 +02:00
// Check for reserved name keyworks. These aren't allowed as names.
2009-05-10 18:49:47 +02:00
if ( StrEqual ( name , " all " , false ) ||
StrEqual ( name , " humans " , false ) ||
StrEqual ( name , " zombies " , false ) ||
StrEqual ( name , " admins " , false ))
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_NAME ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid name at index %d. Cannot be a team name: \" %s \" " , classindex , name );
}
2009-05-10 18:49:47 +02:00
}
}
2009-04-07 04:44:37 +02:00
// Description.
2009-08-13 18:31:21 +02:00
if ( strlen ( ClassData [ classindex ][ Class_Description ]) < ZR_CLASS_DESCRIPTION_MIN )
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_DESCRIPTION ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Missing description at index %d. " , classindex );
}
2009-04-07 04:44:37 +02:00
}
// Model path.
2009-04-25 14:19:14 +02:00
decl String : model_path [ PLATFORM_MAX_PATH ];
2009-08-13 18:31:21 +02:00
if ( strcopy ( model_path , sizeof ( model_path ), ClassData [ classindex ][ Class_ModelPath ]) == 0 )
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_MODEL_PATH ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Missing model_path at index %d. " , classindex , model_path );
}
2009-04-07 04:44:37 +02:00
}
else
{
2009-11-17 08:47:39 +01:00
// Validate only if not a pre-defined setting.
2009-08-15 03:33:09 +02:00
if ( ! StrEqual ( model_path , " random " , false ) &&
2009-11-17 08:47:39 +01:00
! StrEqual ( model_path , " random_public " , false ) &&
! StrEqual ( model_path , " random_hidden " , false ) &&
2010-01-07 08:56:12 +01:00
! StrEqual ( model_path , " random_admin " , false ) &&
! StrEqual ( model_path , " random_mother_zombie " , false ) &&
2009-08-15 03:33:09 +02:00
! StrEqual ( model_path , " default " , false ) &&
2009-11-28 22:32:44 +01:00
! StrEqual ( model_path , " no_change " , false ))
2009-04-07 04:44:37 +02:00
{
// Check if the file exists.
if ( ! FileExists ( model_path ))
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_MODEL_PATH ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid model_path at index %d. File not found: \" %s \" " , classindex , model_path );
}
2009-04-07 04:44:37 +02:00
}
2009-11-17 08:47:39 +01:00
}
2009-04-07 04:44:37 +02:00
}
// Alpha, initial.
2009-08-13 18:31:21 +02:00
new alpha_initial = ClassData [ classindex ][ Class_AlphaInitial ];
2009-04-25 14:19:14 +02:00
if ( ! ( alpha_initial >= ZR_CLASS_ALPHA_INITIAL_MIN && alpha_initial <= ZR_CLASS_ALPHA_INITIAL_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_ALPHA_INITIAL ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid alpha_inital at index %d: %d " , classindex , alpha_initial );
}
2009-04-07 04:44:37 +02:00
}
// Alpha, damaged.
2009-08-13 18:31:21 +02:00
new alpha_damaged = ClassData [ classindex ][ Class_AlphaDamaged ];
2009-04-25 14:19:14 +02:00
if ( ! ( alpha_damaged >= ZR_CLASS_ALPHA_DAMAGED_MIN && alpha_damaged <= ZR_CLASS_ALPHA_DAMAGED_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_ALPHA_DAMAGED ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid alpha_damaged at index %d: %d " , classindex , alpha_damaged );
}
2009-04-07 04:44:37 +02:00
}
// Alpha, damage.
2009-08-13 18:31:21 +02:00
new alpha_damage = ClassData [ classindex ][ Class_AlphaDamage ];
2009-04-25 14:19:14 +02:00
if ( ! ( alpha_damage >= ZR_CLASS_ALPHA_DAMAGE_MIN && alpha_damage <= ZR_CLASS_ALPHA_DAMAGE_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_ALPHA_DAMAGE ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid alpha_damage at index %d: %d " , classindex , alpha_damage );
}
2009-04-07 04:44:37 +02:00
}
// Overlay path.
2009-04-25 14:19:14 +02:00
decl String : overlay_path [ PLATFORM_MAX_PATH ];
decl String : overlay [ PLATFORM_MAX_PATH ];
2009-08-13 18:31:21 +02:00
if ( strcopy ( overlay_path , sizeof ( overlay_path ), ClassData [ classindex ][ Class_OverlayPath ]) > 0 )
2009-04-07 04:44:37 +02:00
{
// Check if the file exists.
2009-04-11 01:56:22 +02:00
Format ( overlay , sizeof ( overlay ), " materials/%s.vmt " , overlay_path );
if ( ! FileExists ( overlay ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_OVERLAY_PATH ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid overlay_path at index %d. File not found: \" %s \" " , classindex , overlay_path );
}
2009-04-07 04:44:37 +02:00
}
}
// Field of view.
2009-08-13 18:31:21 +02:00
new fov = ClassData [ classindex ][ Class_Fov ];
2009-04-25 14:19:14 +02:00
if ( ! ( fov >= ZR_CLASS_FOV_MIN && fov <= ZR_CLASS_FOV_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_FOV ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid fov at index %d: %d " , classindex , fov );
}
2009-04-07 04:44:37 +02:00
}
// Napalm time.
2009-08-13 18:31:21 +02:00
new Float : napalm_time = ClassData [ classindex ][ Class_NapalmTime ];
2009-04-25 14:19:14 +02:00
if ( ! ( napalm_time >= ZR_CLASS_NAPALM_TIME_MIN && napalm_time <= ZR_CLASS_NAPALM_TIME_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_NAPALM_TIME ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid napalm_time at index %d: %0.2f " , classindex , napalm_time );
}
2009-04-25 14:19:14 +02:00
}
2009-08-13 18:31:21 +02:00
// Immunity mode (not implemented).
2009-04-25 14:19:14 +02:00
// Health.
2009-08-13 18:31:21 +02:00
new health = ClassData [ classindex ][ Class_Health ];
2009-04-25 14:19:14 +02:00
if ( ! ( health >= ZR_CLASS_HEALTH_MIN && health <= ZR_CLASS_HEALTH_MAX ))
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_HEALTH ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid health at index %d: %d " , classindex , health );
}
2009-04-07 04:44:37 +02:00
}
// Health regen interval.
2009-08-13 18:31:21 +02:00
new Float : regen_interval = ClassData [ classindex ][ Class_HealthRegenInterval ];
2009-06-22 01:09:51 +02:00
if ( ! ( regen_interval >= ZR_CLASS_REGEN_INTERVAL_MIN && regen_interval <= ZR_CLASS_REGEN_INTERVAL_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_HEALTH_REGEN_INTERVAL ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid health_regen_interval at index %d: %0.2f " , classindex , regen_interval );
}
2009-06-18 02:09:55 +02:00
}
// Health regen amount.
2009-08-13 18:31:21 +02:00
new regen_amount = ClassData [ classindex ][ Class_HealthRegenAmount ];
2009-06-22 01:09:51 +02:00
if ( ! ( regen_amount >= ZR_CLASS_REGEN_AMOUNT_MIN && regen_amount <= ZR_CLASS_REGEN_AMOUNT_MAX ))
2009-06-18 02:09:55 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_HEALTH_REGEN_AMOUNT ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid health_regen_amount at index %d: %d " , classindex , regen_amount );
}
2009-04-07 04:44:37 +02:00
}
// Health infect gain.
2009-08-13 18:31:21 +02:00
new infect_gain = ClassData [ classindex ][ Class_HealthInfectGain ];
2009-04-25 14:19:14 +02:00
if ( ! ( infect_gain >= ZR_CLASS_HEALTH_INFECT_GAIN_MIN && infect_gain <= ZR_CLASS_HEALTH_INFECT_GAIN_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_HEALTH_INFECT_GAIN ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid health_infect_gain at index %d: %d " , classindex , infect_gain );
}
2009-04-07 04:44:37 +02:00
}
// Kill bonus.
2009-08-13 18:31:21 +02:00
new kill_bonus = ClassData [ classindex ][ Class_KillBonus ];
2009-04-25 14:19:14 +02:00
if ( ! ( kill_bonus >= ZR_CLASS_KILL_BONUS_MIN && kill_bonus <= ZR_CLASS_KILL_BONUS_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_KILL_BONUS ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid kill_bonus at index %d: %d " , classindex , kill_bonus );
}
2009-04-07 04:44:37 +02:00
}
// Speed.
2009-08-13 18:31:21 +02:00
new Float : speed = ClassData [ classindex ][ Class_Speed ];
2010-07-04 17:58:27 +02:00
new Float : min ;
new Float : max ;
switch ( ClassSpeedMethod )
{
case ClassSpeed_LMV :
{
min = ZR_CLASS_SPEED_LMV_MIN ;
max = ZR_CLASS_SPEED_LMV_MAX ;
}
case ClassSpeed_Prop :
{
min = ZR_CLASS_SPEED_PROP_MIN ;
max = ZR_CLASS_SPEED_PROP_MAX ;
}
}
if ( ! ( speed >= min && speed <= max ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_SPEED ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid speed at index %d: %0.2f " , classindex , speed );
}
2009-04-07 04:44:37 +02:00
}
// Knockback.
2009-08-13 18:31:21 +02:00
new Float : knockback = ClassData [ classindex ][ Class_KnockBack ];
2009-04-25 14:19:14 +02:00
if ( ! ( knockback >= ZR_CLASS_KNOCKBACK_MIN && knockback <= ZR_CLASS_KNOCKBACK_MAX ))
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_KNOCKBACK ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid knockback at index %d: %0.2f " , classindex , knockback );
}
2009-04-25 14:19:14 +02:00
}
// Jump height.
2009-08-13 18:31:21 +02:00
new Float : jump_height = ClassData [ classindex ][ Class_JumpHeight ];
2009-04-25 14:19:14 +02:00
if ( ! ( jump_height >= ZR_CLASS_JUMP_HEIGHT_MIN && jump_height <= ZR_CLASS_JUMP_HEIGHT_MAX ))
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_JUMP_HEIGHT ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid jump_height at index %d: %0.2f " , classindex , jump_height );
}
2009-04-25 14:19:14 +02:00
}
// Jump distance.
2009-08-13 18:31:21 +02:00
new Float : jump_distance = ClassData [ classindex ][ Class_JumpDistance ];
2009-04-25 14:19:14 +02:00
if ( ! ( jump_distance >= ZR_CLASS_JUMP_DISTANCE_MIN && jump_distance <= ZR_CLASS_JUMP_DISTANCE_MAX ))
2009-04-07 04:44:37 +02:00
{
2009-06-22 01:09:51 +02:00
flags += ZR_CLASS_JUMP_DISTANCE ;
2010-08-06 14:24:10 +02:00
if ( logErrors )
{
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModule_Playerclasses , " Config Validation " , " Warning: Invalid jump_distance at index %d: %0.2f " , classindex , jump_distance );
}
2009-04-07 04:44:37 +02:00
}
return flags ;
2009-04-06 03:20:13 +02:00
}
2009-09-27 23:45:17 +02:00
/**
* Validates a set of editable attributes .
*
* @ param attributes Attribute set to validate .
* @ return 0 if successful , or a bit field ( positivie number ) of
* failed attributes .
*/
stock ClassValidateEditableAttributes ( attributes [ ClassEditableAttributes ])
{
new flags ;
// Alpha initial.
new alphaInitial = attributes [ ClassEdit_AlphaInitial ];
if ( alphaInitial >= 0 )
{
if ( ! ( alphaInitial >= ZR_CLASS_ALPHA_INITIAL_MIN && alphaInitial <= ZR_CLASS_ALPHA_INITIAL_MAX ))
{
flags += ZR_CLASS_ALPHA_INITIAL ;
}
}
// Alpha damaged.
new alphaDamaged = attributes [ ClassEdit_AlphaDamaged ];
if ( alphaDamaged >= 0 )
{
if ( ! ( alphaDamaged >= ZR_CLASS_ALPHA_DAMAGED_MIN && alphaDamaged <= ZR_CLASS_ALPHA_DAMAGED_MAX ))
{
flags += ZR_CLASS_ALPHA_DAMAGED ;
}
}
// Alpha damage.
new alphaDamage = attributes [ ClassEdit_AlphaDamage ];
if ( alphaDamage >= 0 )
{
if ( ! ( alphaDamage >= ZR_CLASS_ALPHA_DAMAGE_MIN && alphaDamage <= ZR_CLASS_ALPHA_DAMAGE_MAX ))
{
flags += ZR_CLASS_ALPHA_DAMAGE ;
}
}
// Overlay.
if ( ! StrEqual ( attributes [ ClassEdit_OverlayPath ], " nochange " , false ))
{
decl String : overlay_path [ PLATFORM_MAX_PATH ];
decl String : overlay [ PLATFORM_MAX_PATH ];
if ( strcopy ( overlay_path , sizeof ( overlay_path ), attributes [ ClassEdit_OverlayPath ]) > 0 )
{
// Check if the file exists.
Format ( overlay , sizeof ( overlay ), " materials/%s.vmt " , overlay_path );
if ( ! FileExists ( overlay ))
{
flags += ZR_CLASS_OVERLAY_PATH ;
}
}
}
// Fov.
new fov = attributes [ ClassEdit_Fov ];
if ( fov >= 0 )
{
if ( ! ( fov >= ZR_CLASS_FOV_MIN && fov <= ZR_CLASS_FOV_MAX ))
{
flags += ZR_CLASS_FOV ;
}
}
// Napalm time.
new Float : napalmTime = attributes [ ClassEdit_NapalmTime ];
if ( napalmTime >= 0.0 )
{
if ( ! ( napalmTime >= ZR_CLASS_NAPALM_TIME_MIN && napalmTime <= ZR_CLASS_NAPALM_TIME_MAX ))
{
flags += ZR_CLASS_NAPALM_TIME ;
}
}
// Immunity mode not implemented yet.
// Health regen interval.
new Float : healthRegenInterval = attributes [ ClassEdit_RegenInterval ];
if ( healthRegenInterval >= 0.0 )
{
if ( ! ( healthRegenInterval >= ZR_CLASS_REGEN_INTERVAL_MIN && healthRegenInterval <= ZR_CLASS_REGEN_INTERVAL_MAX ))
{
flags += ZR_CLASS_REGEN_INTERVAL ;
}
}
// Health regen amount.
new healthRegenAmount = attributes [ ClassEdit_RegenAmount ];
if ( healthRegenAmount >= 0 )
{
if ( ! ( healthRegenAmount >= ZR_CLASS_REGEN_AMOUNT_MIN && healthRegenAmount <= ZR_CLASS_REGEN_AMOUNT_MAX ))
{
flags += ZR_CLASS_REGEN_AMOUNT ;
}
}
// Infect gain.
new infectGain = attributes [ ClassEdit_InfectGain ];
if ( infectGain >= 0 )
{
if ( ! ( infectGain >= ZR_CLASS_HEALTH_INFECT_GAIN_MIN && infectGain <= ZR_CLASS_HEALTH_INFECT_GAIN_MAX ))
{
flags += ZR_CLASS_HEALTH_INFECT_GAIN ;
}
}
// Kill bonus.
new killBonus = attributes [ ClassEdit_KillBonus ];
if ( killBonus >= 0 )
{
if ( ! ( killBonus >= ZR_CLASS_KILL_BONUS_MIN && killBonus <= ZR_CLASS_KILL_BONUS_MAX ))
{
flags += ZR_CLASS_KILL_BONUS ;
}
}
// Speed.
new Float : speed = attributes [ ClassEdit_Speed ];
if ( speed >= 0 )
{
2010-07-04 17:58:27 +02:00
new Float : min ;
new Float : max ;
switch ( ClassSpeedMethod )
{
case ClassSpeed_LMV :
{
min = ZR_CLASS_SPEED_LMV_MIN ;
max = ZR_CLASS_SPEED_LMV_MAX ;
}
case ClassSpeed_Prop :
{
min = ZR_CLASS_SPEED_PROP_MIN ;
max = ZR_CLASS_SPEED_PROP_MAX ;
}
}
if ( ! ( speed >= min && speed <= max ))
2009-09-27 23:45:17 +02:00
{
flags += ZR_CLASS_SPEED ;
}
}
// Knock back.
new Float : knockBack = attributes [ ClassEdit_KnockBack ];
if ( knockBack > ZR_CLASS_KNOCKBACK_IGNORE )
{
if ( ! ( knockBack >= ZR_CLASS_KNOCKBACK_MIN && knockBack <= ZR_CLASS_KNOCKBACK_MAX ))
{
flags += ZR_CLASS_KNOCKBACK ;
}
}
// Jump heigt.
new Float : jumpHeight = attributes [ ClassEdit_JumpHeight ];
if ( jumpHeight >= 0.0 )
{
if ( ! ( jumpHeight >= ZR_CLASS_JUMP_HEIGHT_MIN && jumpHeight <= ZR_CLASS_JUMP_HEIGHT_MAX ))
{
flags += ZR_CLASS_JUMP_HEIGHT ;
}
}
// Jump distance.
new Float : jumpDistance = attributes [ ClassEdit_JumpDistance ];
if ( jumpDistance >= 0.0 )
{
if ( ! ( jumpDistance >= ZR_CLASS_JUMP_DISTANCE_MIN && jumpDistance <= ZR_CLASS_JUMP_DISTANCE_MAX ))
{
flags += ZR_CLASS_JUMP_DISTANCE ;
}
}
return flags ;
}
2009-04-06 03:20:13 +02:00
/**
2009-06-22 01:09:51 +02:00
* Checks if the specified class index is a valid index .
2009-04-06 03:20:13 +02:00
*
2012-09-08 22:34:31 +02:00
* @ param classIndex The class index to validate .
2009-04-06 03:20:13 +02:00
* @ return True if the class exist , false otherwise .
*/
2012-09-08 22:34:31 +02:00
stock bool : ClassValidateIndex ( classIndex )
2009-04-06 03:20:13 +02:00
{
2012-09-08 22:34:31 +02:00
if ( classIndex >= 0 && classIndex < ClassCount )
2009-04-06 03:20:13 +02:00
{
return true ;
}
else
{
return false ;
}
}
/**
* Compares the class team ID with a team ID .
*
* @ param index Index of the class in a class cache or a client index ,
* depending on the cache type specified .
* @ param teamid The team ID to compare with the class .
* @ 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
* data .
* ZR_CLASS_CACHE_PLAYER - Player cache . If this one is used ,
* index will be used as a client index .
* @ return True if equal , false otherwise .
*/
2009-05-30 04:17:01 +02:00
stock bool : ClassTeamCompare ( index , teamid , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-06 03:20:13 +02:00
{
switch ( cachetype )
{
case ZR_CLASS_CACHE_ORIGINAL :
{
2009-08-13 18:31:21 +02:00
if ( ClassData [ index ][ Class_Team ] == teamid )
2009-04-06 03:20:13 +02:00
{
return true ;
}
}
case ZR_CLASS_CACHE_MODIFIED :
{
2009-08-13 18:31:21 +02:00
if ( ClassDataCache [ index ][ Class_Team ] == teamid )
2009-04-06 03:20:13 +02:00
{
return true ;
}
}
case ZR_CLASS_CACHE_PLAYER :
{
2009-08-13 18:31:21 +02:00
if ( ClassPlayerCache [ index ][ Class_Team ] == teamid )
2009-04-06 03:20:13 +02:00
{
return true ;
}
}
}
return false ;
}
/**
* Gets the first class index of a class with the specified name ( not a case
* sensitive search ) .
*
* @ param name The name to search for .
* @ 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
* data .
* @ return The class index if successful , - 1 otherwise .
*/
2009-05-30 04:17:01 +02:00
stock ClassGetIndex ( const String : name [], cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-06 03:20:13 +02:00
{
decl String : current_name [ 64 ];
2012-09-08 22:34:31 +02:00
// Check if there are no classes, or reading from player cache.
if ( ClassCount == 0 || cachetype == ZR_CLASS_CACHE_PLAYER )
2009-04-06 03:20:13 +02:00
{
2012-09-08 22:34:31 +02:00
return - 1 ;
2009-04-06 03:20:13 +02:00
}
// Loop through all classes.
for ( new classindex = 0 ; classindex < ClassCount ; classindex ++ )
{
// Get its name and compare it with the specified class name.
2009-04-11 01:56:22 +02:00
ClassGetName ( classindex , current_name , sizeof ( current_name ), cachetype );
2009-04-06 03:20:13 +02:00
if ( strcmp ( name , current_name , false ) == 0 )
{
return classindex ;
}
}
// The class index wasn't found.
return - 1 ;
}
/**
* Gets the currently active class index that the player is using .
* Note : Does not check if the player is dead .
*
* @ param client The client index .
* @ return The active class index . - 1 on error or if a spectactor .
*/
2009-05-30 04:17:01 +02:00
stock ClassGetActiveIndex ( client )
2009-04-06 03:20:13 +02:00
{
2009-07-16 10:05:40 +02:00
new teamid ;
2009-04-06 03:20:13 +02:00
2009-04-25 14:19:14 +02:00
if ( ! ZRIsClientOnTeam ( client ))
2009-04-06 03:20:13 +02:00
{
// No active team.
return - 1 ;
}
2009-04-25 14:19:14 +02:00
// Check if the player currently is in admin mode.
if ( ClassPlayerInAdminMode [ client ])
2009-04-06 03:20:13 +02:00
{
2009-04-25 14:19:14 +02:00
teamid = ZR_CLASS_TEAM_ADMINS ;
2009-04-06 03:20:13 +02:00
}
else
{
2009-04-25 14:19:14 +02:00
// Not in admin mode, check if player is human or zombie.
2009-04-27 19:51:29 +02:00
if ( InfectIsClientHuman ( client ))
2009-04-25 14:19:14 +02:00
{
teamid = ZR_CLASS_TEAM_HUMANS ;
}
else
{
teamid = ZR_CLASS_TEAM_ZOMBIES ;
}
2009-04-06 03:20:13 +02:00
}
2009-04-25 14:19:14 +02:00
// Return the active class for the active team.
2009-04-11 01:56:22 +02:00
return ClassSelected [ client ][ teamid ];
2009-04-06 03:20:13 +02:00
}
2009-06-18 02:09:55 +02:00
/**
* Gets the multiplier for the specified team and attribute .
*
* @ param client The client index .
* @ param attribute Specifies what attribute multiplier to get .
* @ return Multiplier for the specified team and attribute . 1.0 if the
* client is in admin mode .
*/
stock Float : ClassGetAttributeMultiplier ( client , ClassMultipliers : attribute )
{
new teamid ;
// Check if player is not in admin mode.
if ( ! ClassPlayerInAdminMode [ client ])
{
// Not in admin mode, check if player is human or zombie.
if ( InfectIsClientHuman ( client ))
{
teamid = ZR_CLASS_TEAM_HUMANS ;
}
else
{
teamid = ZR_CLASS_TEAM_ZOMBIES ;
}
// Get multiplier for the specified team and attribute.
return Float : ClassMultiplierCache [ teamid ][ attribute ];
}
else
{
// Do not use multipliers on admin classes.
return 1.0 ;
}
}
2009-08-14 22:10:52 +02:00
/**
* 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 ;
}
2009-08-15 17:37:30 +02:00
// Check if class flags pass the flag filter.
2009-08-14 22:10:52 +02:00
if ( ! ClassFlagFilterMatch ( index , filter [ ClassFilter_RequireFlags ], filter [ ClassFilter_DenyFlags ], cachetype ))
{
return false ;
}
2009-08-15 17:37:30 +02:00
// Get class group name.
decl String : groupname [ 64 ];
groupname [ 0 ] = 0 ;
ClassGetGroup ( index , groupname , sizeof ( groupname ), cachetype );
2009-08-14 22:10:52 +02:00
// Check if a client is specified in the filter.
new client = filter [ ClassFilter_Client ];
if ( ZRIsClientValid ( client ))
{
2009-08-15 17:37:30 +02:00
// Check if a group is set on the class.
2009-08-14 22:10:52 +02:00
if ( strlen ( groupname ))
{
2009-08-15 17:37:30 +02:00
// Check if the client is not a member of that group.
2009-08-14 22:10:52 +02:00
if ( ! ZRIsClientInGroup ( client , groupname ))
{
return false ;
}
}
}
2009-08-15 17:37:30 +02:00
// 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 ;
}
}
2009-08-14 22:10:52 +02:00
// The class passed the filter.
return true ;
}
2009-06-22 01:09:51 +02:00
/**
* Check if a class pass the specified flag filters .
*
* @ param index Index of the class in a class cache or a client index ,
* depending on the cache type specified .
* @ param require Class flags to require . 0 for no filter .
* @ param deny Class flags to exclude . 0 for no filter .
* @ param cachetype Specifies what class cache to read from . Options :
* 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 : ClassFlagFilterMatch ( index , require , deny , cachetype )
{
new flags ;
2009-11-17 08:47:39 +01:00
new bool : requirepassed = false ;
new bool : denypassed = false ;
2009-06-22 01:09:51 +02:00
// Do quick check for optimization reasons: Check if no flags are specified.
if ( require == 0 && deny == 0 )
{
return true ;
}
// Cache flags.
flags = ClassGetFlags ( index , cachetype );
// Match require filter.
if ( require == 0 || flags & require )
{
// All required flags are set.
requirepassed = true ;
}
// Match deny filter.
2009-06-22 16:10:40 +02:00
if ( deny == 0 || ! ( flags & deny ))
2009-06-22 01:09:51 +02:00
{
// No denied flags are set.
denypassed = true ;
}
// Check if required and denied flags passed the filter.
if ( requirepassed && denypassed )
{
// The class pass the filter.
return true ;
}
2009-11-17 08:47:39 +01:00
// The class didn't pass the filter.
return false ;
2009-06-22 01:09:51 +02:00
}
2009-08-09 22:44:28 +02:00
/**
* Decides whether a class selection menu should be enabled . The decision is
* based on zr_class_allow_ * console variables .
*
2010-07-03 23:39:34 +02:00
* @ param team Optional . Team ID to match . Default is all .
* @ param filter Optional . Filter to use on classes .
* @ return True if allowed , false otherwise .
2009-08-09 22:44:28 +02:00
*/
2010-07-03 23:39:34 +02:00
bool : ClassAllowSelection ( client , team = - 1 , filter [ ClassFilter ] = ClassNoFilter )
2009-08-09 22:44:28 +02:00
{
// 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 );
2010-07-03 23:39:34 +02:00
// Only count admin mode classes if client is admin.
2009-08-09 22:44:28 +02:00
if ( isadmin )
{
2010-07-03 23:39:34 +02:00
adminexist = ClassCountTeam ( ZR_CLASS_TEAM_ADMINS , filter ) > 0 ;
2009-08-09 22:44:28 +02:00
}
// 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 ;
}
}
2009-04-06 03:20:13 +02:00
/**
* Gets all class indexes or from a specified team , and adds them to the
* specified array .
*
2009-06-19 02:31:05 +02:00
* @ param array The destination array to add class indexes .
* @ param teamfilter Optional . The team ID to filter . A negative value
* for no filter ( default ) .
2009-08-14 22:10:52 +02:00
* @ param filter Optional . Structure with filter settings .
2009-06-19 02:31:05 +02:00
* @ 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 data .
2009-04-06 03:20:13 +02:00
* @ return True on success . False on error or if no classes were added or
* found .
*/
2009-08-14 22:10:52 +02:00
stock bool : ClassAddToArray ( Handle : array , teamfilter = - 1 , filter [ ClassFilter ] = ClassNoFilter , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-06 03:20:13 +02:00
{
// Validate the array.
if ( array == INVALID_HANDLE )
{
return false ;
}
// Check if there are no classes.
if ( ClassCount == 0 )
{
return false ;
}
// Store a local boolean that says if the user specified a team filter or not.
2009-08-14 22:10:52 +02:00
new bool : hasteamfilter = bool : ( teamfilter >= 0 );
new classesadded ;
2009-04-06 03:20:13 +02:00
// Loop through all classes.
for ( new classindex = 0 ; classindex < ClassCount ; classindex ++ )
{
2009-08-14 22:10:52 +02:00
// Validate filter settings.
if ( ! ClassFilterMatch ( classindex , filter , cachetype ))
2009-04-06 03:20:13 +02:00
{
2009-08-14 22:10:52 +02:00
// The class is didn't pass the filter, skip class.
2009-06-19 02:31:05 +02:00
continue ;
}
2009-04-06 03:20:13 +02:00
// Check team filtering.
2009-08-14 22:10:52 +02:00
if ( hasteamfilter )
2009-04-06 03:20:13 +02:00
{
// Only add classes with matching team ID.
if ( ClassGetTeamID ( classindex , cachetype ) == teamfilter )
{
// Team ID match. Add class index to array.
PushArrayCell ( array , classindex );
2009-08-14 22:10:52 +02:00
classesadded ++ ;
2009-04-06 03:20:13 +02:00
}
}
else
{
// No filter. Add any class to the array.
PushArrayCell ( array , classindex );
2009-08-14 22:10:52 +02:00
classesadded ++ ;
2009-04-06 03:20:13 +02:00
}
}
2009-08-14 22:10:52 +02:00
if ( classesadded )
2009-04-06 03:20:13 +02:00
{
return true ;
}
else
{
// No classes were found/added.
return false ;
}
}
2009-04-18 02:22:13 +02:00
/**
* Counts total classes or classes in the specified team .
*
* @ param teamfilter Optional . The team ID to filter . Negative value for
* no filter ( default ) .
2009-08-14 22:10:52 +02:00
* @ param filter Optional . Structure with filter settings .
2009-04-18 02:22:13 +02:00
* @ 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 data .
* @ return Number of total classes or classes in the specified team .
*/
2009-08-14 22:10:52 +02:00
stock ClassCountTeam ( teamfilter = - 1 , filter [ ClassFilter ] = ClassNoFilter , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-18 02:22:13 +02:00
{
// Check if there are no classes.
if ( ClassCount == 0 )
{
return 0 ;
}
// Store a local boolean that says if the user specified a team filter or not.
2009-08-14 22:10:52 +02:00
new bool : hasteamfilter = bool : ( teamfilter >= 0 );
2009-04-18 02:22:13 +02:00
new count ;
// Loop through all classes.
for ( new classindex = 0 ; classindex < ClassCount ; classindex ++ )
{
2009-08-14 22:10:52 +02:00
// Validate filter settings.
if ( ! ClassFilterMatch ( classindex , filter , cachetype ))
2009-04-18 02:22:13 +02:00
{
2009-08-14 22:10:52 +02:00
// The class is didn't pass the filter, skip class.
2009-06-19 02:31:05 +02:00
continue ;
}
2009-04-18 02:22:13 +02:00
// Check team filtering.
2009-08-14 22:10:52 +02:00
if ( hasteamfilter )
2009-04-18 02:22:13 +02:00
{
// Only add classes with matching team ID.
if ( ClassGetTeamID ( classindex , cachetype ) == teamfilter )
{
// Team ID match. Increment counter.
count ++ ;
}
}
else
{
// No filter. Increment counter.
count ++ ;
}
}
// Return number of classes found.
return count ;
}
2009-04-06 03:20:13 +02:00
/**
* Gets a random class index from a specified team or from all classes .
*
2009-06-19 02:31:05 +02:00
* @ param teamfilter Optional . The team ID to filter . A negative value
* for no filter ( default ) .
2009-08-14 22:10:52 +02:00
* @ param filter Optional . Structure with filter settings .
2009-06-19 02:31:05 +02:00
* @ 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 data .
2009-04-06 03:20:13 +02:00
* @ return The class index if successful , or - 1 on error .
*/
2009-08-14 22:10:52 +02:00
stock ClassGetRandomClass ( teamfilter = - 1 , filter [ ClassFilter ] = ClassNoSpecialClasses , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-06 03:20:13 +02:00
{
new Handle : classarray ;
new arraycount ;
new randnum ;
2009-06-22 18:11:31 +02:00
new buffer ;
2009-04-06 03:20:13 +02:00
classarray = CreateArray ();
// Try to get a class list.
2009-08-14 22:10:52 +02:00
if ( ClassAddToArray ( classarray , teamfilter , filter , cachetype ))
2009-04-06 03:20:13 +02:00
{
// Get a random index from the new class array.
arraycount = GetArraySize ( classarray );
randnum = GetRandomInt ( 0 , arraycount - 1 );
// Return the value at the random index.
2009-06-22 18:11:31 +02:00
buffer = GetArrayCell ( classarray , randnum );
CloseHandle ( classarray );
return buffer ;
2009-04-06 03:20:13 +02:00
}
else
{
// Failed to get a random class.
2009-06-22 18:11:31 +02:00
CloseHandle ( classarray );
2009-04-06 03:20:13 +02:00
return - 1 ;
}
}
/**
* Gets the first class index , or the first class index with the specified team
* ID .
*
2009-06-19 02:31:05 +02:00
* @ param teamfilter Optional . The team ID to filter . A negative value
* for no filter ( default ) .
2009-08-14 22:10:52 +02:00
* @ param filter Optional . Structure with filter settings .
2009-06-19 02:31:05 +02:00
* @ 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 data .
2009-04-06 03:20:13 +02:00
* @ return The first class index , or the first class index with the specified
* team ID . - 1 on error .
*/
2009-08-14 22:10:52 +02:00
stock ClassGetFirstClass ( teamfilter = - 1 , filter [ ClassFilter ] = ClassNoSpecialClasses , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-06 03:20:13 +02:00
{
// Check if there are no classes.
if ( ClassCount == 0 )
{
return false ;
}
2009-08-14 22:10:52 +02:00
new bool : hasteamfilter = bool : ( teamfilter >= 0 );
2009-04-06 03:20:13 +02:00
// Loop through all classes.
for ( new classindex = 0 ; classindex < ClassCount ; classindex ++ )
{
2009-08-14 22:10:52 +02:00
// Validate filter settings.
if ( ! ClassFilterMatch ( classindex , filter , cachetype ))
2009-06-19 02:31:05 +02:00
{
2009-08-14 22:10:52 +02:00
// The class is didn't pass the filter, skip class.
2009-04-06 03:20:13 +02:00
continue ;
}
2009-08-14 22:10:52 +02:00
if ( hasteamfilter )
2009-04-06 03:20:13 +02:00
{
if ( teamfilter == ClassGetTeamID ( classindex , cachetype ))
{
// Team ID match. Return the class index.
return classindex ;
}
}
else
{
// No team filter. Return the class index.
return classindex ;
}
}
return - 1 ;
}
2009-04-11 01:56:22 +02:00
/**
* Gets the first class marked as default for the specified team .
*
2009-06-19 02:31:05 +02:00
* @ param teamid The team ID .
2009-08-14 22:10:52 +02:00
* @ param filter Optional . Structure with filter settings . Default
* is to deny classes with special flags
2009-06-22 01:09:51 +02:00
* ( ZR_CLASS_SPECIALFLAGS ) .
2009-06-19 02:31:05 +02:00
* @ 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 data .
2009-04-11 01:56:22 +02:00
* @ return The first default class index . - 1 on error .
*/
2009-08-14 22:10:52 +02:00
stock ClassGetDefaultClass ( teamid , filter [ ClassFilter ] = ClassNoSpecialClasses , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-11 01:56:22 +02:00
{
new Handle : classarray ;
new arraycount ;
new classindex ;
classarray = CreateArray ();
// Get all classes from the specified team.
2009-08-14 22:10:52 +02:00
if ( ! ClassAddToArray ( classarray , teamid , filter , cachetype ))
2009-04-11 01:56:22 +02:00
{
// Failed to get classes.
2009-06-22 18:11:31 +02:00
CloseHandle ( classarray );
2009-04-11 01:56:22 +02:00
return - 1 ;
}
// Loop through all classes and return the first class marked as team default.
arraycount = GetArraySize ( classarray );
for ( new i = 0 ; i < arraycount ; i ++ )
{
// Get class index from the array.
classindex = GetArrayCell ( classarray , i );
// Check if the current class is marked as team default.
if ( ClassGetTeamDefault ( classindex , cachetype ))
{
// Default class found.
2009-06-22 18:11:31 +02:00
CloseHandle ( classarray );
2009-04-11 01:56:22 +02:00
return classindex ;
}
}
2009-06-22 18:11:31 +02:00
CloseHandle ( classarray );
2009-04-11 01:56:22 +02:00
return - 1 ;
}
2009-04-06 03:20:13 +02:00
/**
* Gets the default class index for the specified team configured to be used
* when players join the server .
*
* @ param teamid The team ID .
2009-08-15 17:37:30 +02:00
* @ param filter Optional . Structure with filter settings . Default is to
* deny classes with special flags ( ZR_CLASS_SPECIALFLAGS ) .
2009-04-06 03:20:13 +02:00
* @ 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
* data .
* @ return The class index of the default class for the specified team if
* successful . - 1 on critical errors . Otherwise it will try to fall
* back on the first class in the specified team .
*/
2009-08-15 17:37:30 +02:00
stock ClassGetDefaultSpawnClass ( teamid , filter [ ClassFilter ] = ClassNoSpecialClasses , cachetype = ZR_CLASS_CACHE_MODIFIED )
2009-04-06 03:20:13 +02:00
{
decl String : classname [ 64 ];
new classindex ;
// Get the default class name from the correct CVAR depending on teamid.
switch ( teamid )
{
case ZR_CLASS_TEAM_ZOMBIES :
{
2009-04-20 02:56:26 +02:00
GetConVarString ( g_hCvarsList [ CVAR_CLASSES_DEFAULT_ZOMBIE ], classname , sizeof ( classname ));
2009-04-06 03:20:13 +02:00
}
case ZR_CLASS_TEAM_HUMANS :
{
2009-04-20 02:56:26 +02:00
GetConVarString ( g_hCvarsList [ CVAR_CLASSES_DEFAULT_HUMAN ], classname , sizeof ( classname ));
2009-04-06 03:20:13 +02:00
}
case ZR_CLASS_TEAM_ADMINS :
{
2009-10-31 03:39:00 +01:00
GetConVarString ( g_hCvarsList [ CVAR_CLASSES_DEFAULT_ADMIN_MODE ], classname , sizeof ( classname ));
2009-04-06 03:20:13 +02:00
}
default :
{
// Invalid team ID.
return - 1 ;
}
}
// Check if the class name isn't empty.
2009-04-11 01:56:22 +02:00
if ( strlen ( classname ) > 0 )
2009-04-06 03:20:13 +02:00
{
// Check if the user set "random" as default class.
2009-08-14 22:10:52 +02:00
if ( StrEqual ( classname , " random " , false ))
2009-04-06 03:20:13 +02:00
{
2009-06-22 01:09:51 +02:00
// Get a list of all classes with the specified team ID. Deny
// classes with special flags.
2009-08-15 17:37:30 +02:00
classindex = ClassGetRandomClass ( teamid , filter , cachetype );
2009-04-06 03:20:13 +02:00
// Validate the result, in case there were errors.
if ( ClassValidateIndex ( classindex ))
{
return classindex ;
}
else
{
// Invalid index. The ClassGetRandomClass function is pretty
// failsafe. So if we can't get a class index here, it's a
// critical error. No reason to fall back on other solutions.
return - 1 ;
}
}
else
{
// The user set a spesific class.
// Try to get the class index with the specified class name.
2009-04-11 01:56:22 +02:00
classindex = ClassGetIndex ( classname , cachetype );
2009-04-06 03:20:13 +02:00
// Validate the class index and check if the team IDs match.
if ( ClassValidateIndex ( classindex ) && ( teamid == ClassGetTeamID ( classindex , cachetype )))
{
return classindex ;
}
else
{
// 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.
2009-08-15 17:37:30 +02:00
classindex = ClassGetFirstClass ( teamid , filter , cachetype );
2009-04-06 03:20:13 +02:00
2009-06-01 23:29:26 +02:00
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 );
2009-04-06 03:20:13 +02:00
// Validate the new index.
if ( ClassValidateIndex ( classindex ))
{
// Log a warning.
2009-10-27 22:53:03 +01:00
//LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Playerclasses, "Default Spawn Class", "Warning: The default class name \"%s\" does not exist or matches the team ID.", classname);
2009-04-06 03:20:13 +02:00
return classindex ;
}
else
{
2009-08-14 22:10:52 +02:00
// Something went wrong. This is a critical error. There's
// probably missing classes with no special flags set.
2009-04-06 03:20:13 +02:00
return - 1 ;
}
}
}
}
else
{
2009-04-11 01:56:22 +02:00
// Blank class name, get the default class and return the index.
2009-08-15 17:37:30 +02:00
return ClassGetDefaultClass ( teamid , filter , cachetype );
2009-04-06 03:20:13 +02:00
}
}