1
0
KF2-Dev-Scripts/KFGame/Classes/KFPerk_Commando.uc
2020-12-13 18:01:13 +03:00

738 lines
26 KiB
Ucode

//=============================================================================
// KFPerk_Commando
//=============================================================================
// The commando perk class
//=============================================================================
// Killing Floor 2
// Copyright (C) 2015 Tripwire Interactive LLC
// - Christian "schneidzekk" Schneider
//=============================================================================
class KFPerk_Commando extends KFPerk
hidecategories(Mobile, Object, Debug, Advanced, Physics, Actor, Attachment, Display)
native;
//`include(KFOnlineStats.uci)
//Passives
var private const PerkSkill WeaponDamage; // weapon dmg modifier
var private const PerkSkill CloakedEnemyDetection; // Can see cloaked zeds x UUs far (100UUs = 100cm = 1m)
var private const PerkSkill ZedTimeExtension; // How many times a zed time ext can happen
var private const PerkSkill ReloadSpeed; // 2% increase every 5 levels (max 10% increase)
var private const PerkSkill CallOut; // allow teammates to see cloaked units
var private const PerkSkill NightVision; // Night vision
var private const PerkSkill Recoil; // Recoil reduction
var private const float RapidFireFiringRate; // Faster firing rate in % NOTE:This is needed for combinations with the Skill: RapidFire (Damage and Rate)
var private const float BackupWeaponSwitchModifier;
var private const float HealthArmorModifier;
/** Temp HUD */
var Texture2d WhiteMaterial;
enum ECommandoSkills
{
ECommandoTacticalReload,
ECommandoLargeMags,
ECommandoBackup,
ECommandoImpact,
ECommandoHealthIncrease,
ECommandoAmmoVest,
ECommandoHollowPoints,
ECommandoEatLead,
ECommandoProfessional,
ECommandoRapidFire
};
/** On spawn, modify owning pawn based on perk selection */
function SetPlayerDefaults( Pawn PlayerPawn )
{
local float NewArmor;
super.SetPlayerDefaults( PlayerPawn );
if( OwnerPawn.Role == ROLE_Authority && IsHealthIncreaseActive() )
{
NewArmor = OwnerPawn.default.MaxArmor * static.GetHealthArmorModifier();
OwnerPawn.AddArmor( Round( NewArmor ) );
}
}
/*********************************************************************************************
* @name Passive skills functions
********************************************************************************************* */
/**
* @brief Modifies the damage dealt
*
* @param InDamage damage
* @param DamageCauser weapon or projectile (optional)
* @param MyKFPM the zed damaged (optional)
* @param DamageInstigator responsible controller (optional)
* @param class DamageType the damage type used (optional)
*/
simulated function ModifyDamageGiven( out int InDamage, optional Actor DamageCauser, optional KFPawn_Monster MyKFPM, optional KFPlayerController DamageInstigator, optional class<KFDamageType> DamageType, optional int HitZoneIdx )
{
local KFWeapon KFW;
local float TempDamage;
TempDamage = InDamage;
if( DamageCauser != none )
{
KFW = GetWeaponFromDamageCauser( DamageCauser );
}
if( (KFW != none && IsWeaponOnPerk( KFW,, self.class )) || (DamageType != none && IsDamageTypeOnPerk( DamageType )) )
{
TempDamage += InDamage * GetPassiveValue( WeaponDamage, CurrentLevel );
if( IsRapidFireActive() )
{
`QALog( "RapidFire Damage" @ KFW @ GetPercentage( InDamage, InDamage * GetSkillValue( PerkSkills[ECommandoRapidFire] )), bLogPerk );
TempDamage += InDamage * GetSkillValue( PerkSkills[ECommandoRapidFire] );
}
}
//Specific exclusion of grenades here so as not to cause issues in other areas of the code that would have required more extensive changes.
// Basically, GetWeaponFromDamageCauser should never have been returning the equipped weapon for grenades, but now that we
// have the perks so tied into using that, it's easier to just specifically fix commando here.
if( KFW != none && !DamageCauser.IsA('KFProj_Grenade'))
{
if( IsBackupActive() && (IsBackupWeapon( KFW ) || KFW.Class.Name == 'KFWeap_Pistol_Dual9mm') )
{
`QALog( "Backup Damage" @ KFW @ GetPercentage( InDamage, InDamage * GetSkillValue( PerkSkills[ECommandoBackup] )), bLogPerk );
TempDamage += InDamage * GetSkillValue( PerkSkills[ECommandoBackup] );
}
if( IsWeaponOnPerk( KFW,, self.class ) )
{
if( IsHollowPointsActive() )
{
`QALog( "Hollow points DMG" @ KFW @ GetPercentage(InDamage, InDamage * GetSkillValue( PerkSkills[ECommandoHollowPoints] )), bLogPerk );
TempDamage += InDamage * GetSkillValue( PerkSkills[ECommandoHollowPoints] );
}
}
}
`QALog( "Total Damage Given" @ DamageType @ KFW @ GetPercentage( InDamage, FCeil(TempDamage) ), bLogPerk );
InDamage = FCeil(TempDamage);
}
/**
* @brief how far away we can see stalkers
*
* @return range in UUs
*/
simulated function float GetCloakDetectionRange()
{
return GetPassiveValue( CloakedEnemyDetection, CurrentLevel );
}
/**
* @brief How long can we extend zed time?
* @details Zed time extended by 1 second starting at level 0
* and every milestone level thereafter to a maximum of 5 seconds
* @param Level the perk's level
* @return zed time extension in seconds
*/
simulated static function float GetZedTimeExtension( byte Level )
{
if( Level >= RANK_5_LEVEL )
{
return default.ZedTimeExtension.MaxValue;
}
else if( Level >= RANK_4_LEVEL )
{
return default.ZedTimeExtension.StartingValue + 4 * default.ZedTimeExtension.Increment;
}
else if( Level >= RANK_3_LEVEL )
{
return default.ZedTimeExtension.StartingValue + 3 * default.ZedTimeExtension.Increment;
}
else if( Level >= RANK_2_LEVEL )
{
return default.ZedTimeExtension.StartingValue + 2 * default.ZedTimeExtension.Increment;
}
else if( Level >= RANK_1_LEVEL )
{
return default.ZedTimeExtension.StartingValue + default.ZedTimeExtension.Increment;
}
return 1.0f;
}
/**
* @brief Calculates the additional ammo per perk level
*
* @param Level Current perk level
* @return additional ammo
*/
simulated private final static function float GetExtraReloadSpeed( int Level )
{
return default.ReloadSpeed.Increment * FFloor( float( Level ) / 5.f );
}
/**
* @brief Modifies the reload speed for commando weapons
*
* @param ReloadDuration Length of the reload animation
* @param GiveAmmoTime Time after the weapon actually gets some ammo
*/
simulated function float GetReloadRateScale( KFWeapon KFW )
{
if( IsWeaponOnPerk( KFW,, self.class ) )
{
return 1.f - GetExtraReloadSpeed( CurrentLevel );
}
return 1.f;
}
/**
* @brief modifies the players health 1% per level
*
* @param InHealth health
*/
function ModifyHealth( out int InHealth )
{
local float TempHealth;
if( IsHealthIncreaseActive() )
{
TempHealth = InHealth;
TempHealth += InHealth * GetSkillValue( PerkSkills[ECommandoHealthIncrease] );
InHealth = Round(TempHealth);
`QALog( "Health Increase" @ InHealth, bLogPerk );
}
}
/**
* @brief Modifies the pawn's MaxArmor
*
* @param MaxArmor the maximum armor value
*/
function ModifyArmor( out byte MaxArmor )
{
local float TempArmor;
if( IsHealthIncreaseActive() )
{
TempArmor = MaxArmor;
TempArmor += MaxArmor * GetSkillValue( PerkSkills[ECommandoHealthIncrease] );
MaxArmor = Round( TempArmor );
}
}
/*********************************************************************************************
* @name Selectable skills functions
********************************************************************************************* */
/**
* @brief Should the tactical reload skill adjust the reload speed
*
* @param KFW weapon in use
* @return true/false
*/
simulated function bool GetUsingTactialReload( KFWeapon KFW )
{
return ( IsTacticalReloadActive() && (IsWeaponOnPerk( KFW,, self.class ) || IsBackupWeapon( KFW )) );
}
/**
* @brief Modifies mag capacity and count
*
* @param KFW the weapon
* @param MagazineCapacity modified mag capacity
* @param WeaponPerkClass the weapon's associated perk class (optional)
*/
simulated function ModifyMagSizeAndNumber( KFWeapon KFW, out int MagazineCapacity, optional array< Class<KFPerk> > WeaponPerkClass, optional bool bSecondary=false, optional name WeaponClassname )
{
local float TempCapacity;
TempCapacity = MagazineCapacity;
if( !bSecondary && IsWeaponOnPerk( KFW, WeaponPerkClass, self.class ) && (KFW == none || !KFW.bNoMagazine) )
{
if( IsLargeMagActive() )
{
TempCapacity += MagazineCapacity * GetSkillValue( PerkSkills[ECommandoLargeMags] );
}
if( IsEatLeadActive() )
{
TempCapacity += MagazineCapacity * GetSkillValue( PerkSkills[ECommandoEatLead] );
}
}
MagazineCapacity = Round(TempCapacity);
}
/**
* @brief Modifies the max spare ammo
*
* @param KFW The weapon
* @param MaxSpareAmmo ammo amount
* @param TraderItem the weapon's associated trader item info
*/
simulated function ModifyMaxSpareAmmoAmount( KFWeapon KFW, out int MaxSpareAmmo, optional const out STraderItem TraderItem, optional bool bSecondary=false )
{
local float TempMaxSpareAmmoAmount;
if( IsAmmoVestActive() && (IsWeaponOnPerk( KFW, TraderItem.AssociatedPerkClasses, self.class ) ||
IsBackupWeapon( KFW )) )
{
TempMaxSpareAmmoAmount = MaxSpareAmmo;
TempMaxSpareAmmoAmount += MaxSpareAmmo * GetSkillValue( PerkSkills[ECommandoAmmoVest] );
MaxSpareAmmo = Round( TempMaxSpareAmmoAmount );
}
}
static simulated private function bool Is9mm( KFWeapon KFW )
{
return KFW != none && KFW.default.bIsBackupWeapon && !KFW.IsMeleeWeapon();
}
/**
* @brief Skills can modify the zed time time dilation
*
* @param StateName used weapon's state
* @return time dilation modifier
*/
simulated function float GetZedTimeModifier( KFWeapon W )
{
local name StateName;
StateName = W.GetStateName();
if( IsProfessionalActive() && (IsWeaponOnPerk( W,, self.class ) || IsBackupWeapon( W )) )
{
if( StateName == 'Reloading' ||
StateName == 'AltReloading' )
{
return 1.f;
}
else if( StateName == 'WeaponPuttingDown' || StateName == 'WeaponEquipping' )
{
return 0.3f;
}
}
if( CouldRapidFireActive() && (Is9mm(W) || IsWeaponOnPerk( W,, self.class )) && ZedTimeModifyingStates.Find( StateName ) != INDEX_NONE )
{
return RapidFireFiringRate;
}
return 0.f;
}
/**
* @brief Specific modifier for the Minigun Windup rotation
*
* @return time dilation modifier
*/
simulated function float GetZedTimeModifierForWindUp()
{
if( CouldRapidFireActive() )
{
return RapidFireFiringRate;
}
return 0.f;
}
/**
* @brief skills and weapons can modify the stumbling power
* @return stumpling power modifier
*/
function float GetStumblePowerModifier( optional KFPawn KFP, optional class<KFDamageType> DamageType, optional out float CooldownModifier, optional byte BodyPart )
{
local KFWeapon KFW;
KFW = GetOwnerWeapon();
if( IsImpactActive() && IsWeaponOnPerk( KFW,, self.class ) )
{
return GetSkillValue( PerkSkills[ECommandoImpact] );
}
return 0.f;
}
/**
* @brief The Backup skill modifies the weapon switch speed
*
* @param ModifiedSwitchTime Duration of putting down or equipping the weapon
*/
simulated function ModifyWeaponSwitchTime( out float ModifiedSwitchTime )
{
if( IsBackupActive() )
{
`QALog( "Backup switch weapon increase:" @ GetPercentage( ModifiedSwitchTime, ModifiedSwitchTime * GetBackupWeaponSwitchModifier() ), bLogPerk );
ModifiedSwitchTime -= ModifiedSwitchTime * static.GetBackupWeaponSwitchModifier();
}
}
simulated final static function float GetBackupWeaponSwitchModifier()
{
return default.BackupWeaponSwitchModifier;
}
/**
* @brief Modifies the weapon's recoil
*
* @param CurrentRecoilModifier percent recoil lowered
*/
simulated function ModifyRecoil( out float CurrentRecoilModifier, KFWeapon KFW )
{
if (IsWeaponOnPerk(KFW, , self.class))
{
CurrentRecoilModifier *= (1.f - GetPassiveValue(Recoil, CurrentLevel));
}
}
private static function float GetHealthArmorModifier()
{
return default.HealthArmorModifier;
}
/*********************************************************************************************
* @name Getters
********************************************************************************************* */
/**
* @brief Checks if call out skill is active
*
* @return true/false
*/
simulated function bool IsCallOutActive()
{
return true;
}
/**
* @brief Checks if night vision skill is active
*
* @return true/false
*/
simulated function bool HasNightVision()
{
return true;
}
/**
* @brief Checks if rapid fire skill is active and if we are in zed time
*
* @return true/false
*/
simulated protected function bool IsRapidFireActive()
{
return PerkSkills[ECommandoRapidFire].bActive && WorldInfo.TimeDilation < 1.f && IsPerkLevelAllowed(ECommandoRapidFire);
}
simulated protected function bool CouldRapidFireActive()
{
return PerkSkills[ECommandoRapidFire].bActive && IsPerkLevelAllowed(ECommandoRapidFire);
}
/**
* @brief Checks if large mag skill is active
*
* @return true/false
*/
simulated final private function bool IsLargeMagActive()
{
return PerkSkills[ECommandoLargeMags].bActive && IsPerkLevelAllowed(ECommandoLargeMags);
}
/**
* @brief Checks if backup damage skill is active
*
* @return true/false
*/
simulated final private function bool IsBackupActive()
{
return PerkSkills[ECommandoBackup].bActive && IsPerkLevelAllowed(ECommandoBackup);
}
/**
* @brief Checks if Hollow Points skill is active
*
* @return true/false
*/
simulated private function bool IsHollowPointsActive()
{
return PerkSkills[ECommandoHollowPoints].bActive && IsPerkLevelAllowed(ECommandoHollowPoints);
}
/**
* @brief Checks if tactical reload skill is active (client & server)
*
* @return true/false
*/
simulated final private function bool IsTacticalReloadActive()
{
return PerkSkills[ECommandoTacticalReload].bActive && IsPerkLevelAllowed(ECommandoTacticalReload);
}
/**
* @brief Checks if impact skill is active
*
* @return true/false
*/
final private function bool IsImpactActive()
{
return PerkSkills[ECommandoImpact].bActive && IsPerkLevelAllowed(ECommandoImpact);
}
/**
* @brief Checks if health increase skill is active
*
* @return true/false
*/
final private function bool IsHealthIncreaseActive()
{
return PerkSkills[ECommandoHealthIncrease].bActive && IsPerkLevelAllowed(ECommandoHealthIncrease);
}
/**
* @brief Checks if auto fire skill is active
*
* @return true/false
*/
final private function bool IsEatLeadActive()
{
return PerkSkills[ECommandoEatLead].bActive && IsPerkLevelAllowed(ECommandoEatLead);
}
/**
* @brief Checks if ammo vest skill is active
*
* @return true/false
*/
final private function bool IsAmmoVestActive()
{
return PerkSkills[ECommandoAmmoVest].bActive && IsPerkLevelAllowed(ECommandoAmmoVest);
}
/**
* @brief Checks if professional skill is active
*
* @return true/false
*/
simulated final private function bool IsProfessionalActive()
{
return PerkSkills[ECommandoProfessional].bActive && IsPerkLevelAllowed(ECommandoProfessional);
}
/*********************************************************************************************
* @name Hud/UI
********************************************************************************************* */
simulated static function GetPassiveStrings( out array<string> PassiveValues, out array<string> Increments, byte Level )
{
PassiveValues[0] = Round( GetPassiveValue( default.WeaponDamage, Level) * 100 ) $ "%";
PassiveValues[1] = Round( GetPassiveValue( default.CloakedEnemyDetection, Level ) / 100 ) $ "m"; // Divide by 100 to convert unreal units to meters
PassiveValues[2] = string(Round( GetZedTimeExtension( Level )));
PassiveValues[3] = Round( GetExtraReloadSpeed( Level ) * 100 ) $ "%";
PassiveValues[4] = Round(GetPassiveValue( default.Recoil, Level ) * 100) $ "%";
PassiveValues[5] = "";
Increments[0] = "["@Left( string( default.WeaponDamage.Increment * 100 ), InStr(string(default.WeaponDamage.Increment * 100), ".") + 2 ) $"% /" @default.LevelString @"]";
Increments[1] = "["@ Int(default.CloakedEnemyDetection.StartingValue / 100 ) @"+" @Int(default.CloakedEnemyDetection.Increment / 100 ) $"m /" @default.LevelString @"]";
Increments[2] = "["@Round(default.ZedTimeExtension.StartingValue) @"+" @Round(default.ZedTimeExtension.Increment) @" / 5" @default.LevelString @"]";
Increments[3] = "["@Left( string( default.ReloadSpeed.Increment * 100 ), InStr(string(default.ReloadSpeed.Increment * 100), ".") + 2 ) $ "% / 5" @ default.LevelString @ "]";
Increments[4] = "[" @ Left( string( default.Recoil.Increment * 100 ), InStr(string(default.Recoil.Increment * 100), ".") + 2 )$ "% /" @ default.LevelString @ "]";
Increments[5] = "";
}
/*********************************************************************************************
* @name Stats/XP
********************************************************************************************* */
/**
* @brief how much XP is earned by a stalker kill depending on the game's difficulty
*
* @param Difficulty current game difficulty
* @return XP earned
*/
simulated static function int GetStalkerKillXP( byte Difficulty )
{
return default.SecondaryXPModifier[Difficulty];
}
/*********************************************************************************************
* @name Temp Hud things
********************************************************************************************* */
simulated function DrawSpecialPerkHUD(Canvas C)
{
local KFPawn_Monster KFPM;
local vector ViewLocation, ViewDir;
local float DetectionRangeSq, ThisDot;
local float HealthBarLength, HealthbarHeight;
if( CheckOwnerPawn() )
{
DetectionRangeSq = Square( GetPassiveValue(CloakedEnemyDetection, CurrentLevel) );
HealthbarLength = FMin( 50.f * (float(C.SizeX) / 1024.f), 50.f );
HealthbarHeight = FMin( 6.f * (float(C.SizeX) / 1024.f), 6.f );
ViewLocation = OwnerPawn.GetPawnViewLocation();
ViewDir = vector( OwnerPawn.GetViewRotation() );
foreach WorldInfo.AllPawns( class'KFPawn_Monster', KFPM )
{
if( !KFPM.CanShowHealth()
|| !KFPM.IsAliveAndWell()
|| `TimeSince(KFPM.Mesh.LastRenderTime) > 0.1f
|| VSizeSQ(KFPM.Location - ViewLocation) > DetectionRangeSq )
{
continue;
}
ThisDot = ViewDir dot Normal(KFPM.Location - ViewLocation);
if( ThisDot > 0.f )
{
DrawZedHealthbar( C, KFPM, ViewLocation, HealthbarHeight, HealthbarLength );
}
}
}
}
simulated function DrawZedHealthbar(Canvas C, KFPawn_Monster KFPM, vector CameraLocation, float HealthbarHeight, float HealthbarLength )
{
local vector ScreenPos, TargetLocation;
local float HealthScale;
if( KFPM.bCrawler && KFPM.Floor.Z <= -0.7f && KFPM.Physics == PHYS_Spider )
{
TargetLocation = KFPM.Location + vect(0,0,-1) * KFPM.GetCollisionHeight() * 1.2 * KFPM.CurrentBodyScale;
}
else
{
TargetLocation = KFPM.Location + vect(0,0,1) * KFPM.GetCollisionHeight() * 1.2 * KFPM.CurrentBodyScale;
}
ScreenPos = C.Project( TargetLocation );
if( ScreenPos.X < 0 || ScreenPos.X > C.SizeX || ScreenPos.Y < 0 || ScreenPos.Y > C.SizeY )
{
return;
}
if( `FastTracePhysX(TargetLocation, CameraLocation) )
{
HealthScale = FClamp( float(KFPM.Health) / float(KFPM.HealthMax), 0.f, 1.f );
C.EnableStencilTest( true );
C.SetDrawColor(0, 0, 0, 255);
C.SetPos( ScreenPos.X - HealthBarLength * 0.5, ScreenPos.Y );
C.DrawTile( WhiteMaterial, HealthbarLength, HealthbarHeight, 0, 0, 32, 32 );
C.SetDrawColor( 237, 8, 0, 255 );
C.SetPos( ScreenPos.X - HealthBarLength * 0.5 + 1.0, ScreenPos.Y + 1.0 );
C.DrawTile( WhiteMaterial, (HealthBarLength - 2.0) * HealthScale, HealthbarHeight - 2.0, 0, 0, 32, 32 );
C.EnableStencilTest( false );
}
}
/*********************************************************************************************
* @name Logging / debug
********************************************************************************************* */
/** Log What type of reload the weapon would use given ammo count */
private simulated function name LogTacticalReload()
{
local KFWeapon KFW;
KFW = GetOwnerWeapon();
return KFW.GetReloadAnimName( GetUsingTactialReload(KFW) );
}
/** QA Logging - Report Perk Info */
simulated function LogPerkSkills()
{
super.LogPerkSkills();
if( bLogPerk )
{
/** `log( "PASSIVE PERKS" );
`log( "-Weapon Damage Modifier:" @ GetPassiveValue( WeaponDamage, CurrentLevel ) * 100 $"%" );
`log( "-Cloak Detection Range:" @ GetPassiveValue(CloakedEnemyDetection, CurrentLevel)/100 @"Meters" );
`log( "-Health Bar Detection Range:" @ GetPassiveValue(HealthBarDetection, CurrentLevel) /100 @"Meters" );
`log( "-ZED Time Extension:" @ GetZedTimeExtension( CurrentLevel ) @"Seconds" );
`log( "-Health Increase:" @ GetPassiveValue(ExtraHealth, CurrentLevel) $"%" );
`log( "Skill Tree" );
`log( "-Nightvision Active:" @ HasNightVision() );
`log( "-Call Active:" @ IsCallOutActive() );
`log( "-Large Mags:" @ PerkSkills[ECommandoLargeMags].bActive );
`log( "-Backup:" @ PerkSkills[DECommandoBackup.bActive );
`log( "-Single Fire:" @ PerkSkills[ECommandoSingleFire].bActive );
`log( "-Tactical Reload:" @ PerkSkills[ECommandoTacticalReload].bActive @ LogTacticalReload() );
`log( "-Impact:" @ PerkSkills[ECommandoImpact].bActive );
`log( "-Autofire:" @ PerkSkills[ECommandoAutoFireDamage].bActive );
`log( "-Rapid Fire:" @ PerkSkills[ECommandoRapidFireDamage].bActive );
`log( "-Professional:" @ PerkSkills[ECommandoProfessional].bActive );*/
}
}
DefaultProperties
{
bCanSeeCloakedZeds=true
PerkIcon=Texture2D'UI_PerkIcons_TEX.UI_PerkIcon_Commando'
ProgressStatID=STATID_Cmdo_Progress
PerkBuildStatID=STATID_Cmdo_Build
PrimaryWeaponDef=class'KFWeapDef_AR15'
KnifeWeaponDef=class'KFweapDef_Knife_Commando'
GrenadeWeaponDef=class'KFWeapDef_Grenade_Commando'
RapidFireFiringRate=0.5f
BackupWeaponSwitchModifier=0.5
HealthArmorModifier=0.25
ZedTimeModifyingStates(0)="WeaponFiring"
ZedTimeModifyingStates(1)="WeaponBurstFiring"
ZedTimeModifyingStates(2)="WeaponSingleFiring"
ZedTimeModifyingStates(3)="WeaponWindingUp"
SecondaryXPModifier(0)=3
SecondaryXPModifier(1)=5
SecondaryXPModifier(2)=6
SecondaryXPModifier(3)=9
WhiteMaterial=Texture2D'EngineResources.WhiteSquareTexture'
WeaponDamage=(Name="Weapon Damage",Increment=0.01,Rank=0,StartingValue=0.0f,MaxValue=0.25)
CloakedEnemyDetection=(Name="Cloaked Enemy Detection Range",Increment=200.f,Rank=0,StartingValue=1000.f,MaxValue=6000.f)
ZedTimeExtension=(Name="Zed Time Extension",Increment=1.f,Rank=0,StartingValue=1.f,MaxValue=6.f)
ReloadSpeed=(Name="Reload Speed",Increment=0.02,Rank=0,StartingValue=0.0f,MaxValue=0.10)
CallOut=(Name="Call Out",Increment=2.f,Rank=0,StartingValue=0.f,MaxValue=50.f)
NightVision=(Name="Night Vision",Increment=0.f,Rank=0,StartingValue=0.f,MaxValue=0.f)
Recoil=(Name="Recoil",Increment=0.02f,Rank=0,StartingValue=0.0f,MaxValue=0.5f)
PerkSkills(ECommandoTacticalReload)=(Name="TacticalReload",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_TacticalReload",Increment=0.f,Rank=0,StartingValue=0.f,MaxValue=0.f)
PerkSkills(ECommandoLargeMags)=(Name="LargeMags",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_LargeMag",Increment=0.f,Rank=0,StartingValue=0.5f,MaxValue=0.5f)
PerkSkills(ECommandoBackup)=(Name="Backup",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_Backup",Increment=0.f,Rank=0,StartingValue=0.85f,MaxValue=0.85f) //1.1
PerkSkills(ECommandoImpact)=(Name="Impact",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_Impact",Increment=0.f,Rank=0,StartingValue=1.5,MaxValue=1.5)
PerkSkills(ECommandoHealthIncrease)=(Name="HealthIncrease",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_HP",Increment=0.f,Rank=0,StartingValue=0.25,MaxValue=0.25)
PerkSkills(ECommandoAmmoVest)=(Name="AmmoVest",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_AmmoVest",Increment=0.f,Rank=0,StartingValue=0.2f,MaxValue=0.2f)
PerkSkills(ECommandoHollowPoints)=(Name="HollowPoints",IconPath="UI_PerkTalent_TEX.Commando.UI_Talents_Commando_SingleFire",Increment=0.f,Rank=0,StartingValue=0.3f,MaxValue=0.3f)
PerkSkills(ECommandoEatLead)=(Name="EatLead",IconPath="UI_PerkTalent_TEX.Commando.UI_Talents_Commando_AutoFire",Increment=0.f,Rank=0,StartingValue=1.0f,MaxValue=1.0f) //0.5
PerkSkills(ECommandoProfessional)=(Name="Professional",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_Professional")
PerkSkills(ECommandoRapidFire)=(Name="RapidFire",IconPath="UI_PerkTalent_TEX.commando.UI_Talents_Commando_RapidFire",Increment=0.f,Rank=0,StartingValue=0.03,MaxValue=0.03)
// Skill tracking
HitAccuracyHandicap=0.0
HeadshotAccuracyHandicap=-3.0
AutoBuyLoadOutPath=(class'KFWeapDef_AR15', class'KFWeapDef_Bullpup', class'KFWeapDef_AK12', class'KFWeapDef_SCAR', class'KFWeapDef_MedicRifleGrenadeLauncher')
// Prestige Rewards
PrestigeRewardItemIconPaths[0]="WEP_SkinSet_Prestige01_Item_TEX.knives.CommandoKnife_PrestigePrecious_Mint_large"
PrestigeRewardItemIconPaths[1]="WEP_SkinSet_Prestige02_Item_TEX.tier01.AR15_PrestigePrecious_Mint_large"
PrestigeRewardItemIconPaths[2]="WEP_skinset_prestige03_itemtex.tier02.L85A2_PrestigePrecious_Mint_large"
PrestigeRewardItemIconPaths[3]="wep_skinset_prestige04_itemtex.tier03.AK12_PrestigePrecious_Mint_Large"
PrestigeRewardItemIconPaths[4]="WEP_SkinSet_Prestige05_Item_TEX.tier04.Scar_PrestigePrecious_Mint_large"
}