KFStatOutput: Difference between revisions

From Tripwire Interactive Wiki
Jump to navigation Jump to search
(Created page with "This is my stat generator for the killing floor weapon pages. --~~~~ <blockquote><pre>//==========================================================...")
 
m (Added melee headshot and notes)
Line 10: Line 10:
//
//
// * Cannot detect penetration for all weapons.
// * Cannot detect penetration for all weapons.
//
// * (!) Cannot obtain hunting shotgun (or crossbow) reload speed
//
//
// INFO
// INFO
Line 40: Line 42:
function bool IsTrueFire(class<WeaponFire> Fire)
function bool IsTrueFire(class<WeaponFire> Fire)
{
{
    if (Fire.Name == 'NoFire'
if (Fire.Name == 'NoFire'
        || Fire.Name == 'ShotgunLightFire'
|| Fire.Name == 'ShotgunLightFire'
        || Fire.Name == 'SingleALTFire'
|| Fire.Name == 'SingleALTFire'
        )
)
        return false;
return false;
   
    return true;
return true;
}
}


function bool IsMeleeFire(class<WeaponFire> Fire)
function bool IsMeleeFire(class<WeaponFire> Fire)
{
{
    if (Fire == none)
if (Fire == none)
        return false;
return false;
    if (class<KFMeleeFire>(Fire) != none)
if (class<KFMeleeFire>(Fire) != none)
        return true;
return true;
    return false;
return false;
}
}


function bool IgnoresLoad(class<WeaponFire> Fire)
function bool IgnoresLoad(class<WeaponFire> Fire)
{
{
    if (class<MP7MAltFire>(Fire) != none
if (class<MP7MAltFire>(Fire) != none
        || class<M7A3MAltFire>(Fire) != none)
|| class<M7A3MAltFire>(Fire) != none)
       
        return true;
return true;
   
    return false;
return false;
}
}


function OutputStatNum(string Title, float Stat, optional float AltStat)
function OutputStatNum(string Title, float Stat, optional float AltStat)
{
{
    OutputStat(Title, string(Stat), string(AltStat));
OutputStat(Title, string(Stat), string(AltStat));
}
}


function OutputStat(string Title, string Stat, optional string AltStat)
function OutputStat(string Title, string Stat, optional string AltStat)
{
{
    local int A, x;
local int A, x;
   
    // Adjust stat name
// Adjust stat name
    Title $= ":";
Title $= ":";
    A = Len(Title);
A = Len(Title);
    if (A < 14)
if (A < 14)
    {
{
        for (x = 0; x < 14 - A; x++)
for (x = 0; x < 14 - A; x++)
            Title $= " ";
Title $= " ";
    }
}
   
    if (Fire[1] != none && AltStat != "")
if (Fire[1] != none && AltStat != "")
        Log(Title $ Stat @ "(" $ AltStat $ ")");
Log(Title $ Stat @ "(" $ AltStat $ ")");
    else
else
        Log(Title $ Stat);
Log(Title $ Stat);
}
}


function PostBeginPlay()
function PostBeginPlay()
{
{
    local string Name;
local string Name;
     local int Cost;
     local string Perk;
    local int Weight;
local int Cost;
    local int Capacity[2];
local int Weight;
    local int MagazineSize[2];
local int Capacity[2];
    local float FireRate[2];
local int MagazineSize[2];
    local float ReloadSpeed[2];
local float FireRate[2];
    local float Spread[2];
local float ReloadSpeed[2];
    local int Damage[2];
local float Spread[2];
    local float DamageRadius[2];
local int Damage[2];
    local float HeadMultiplier[2];
local float DamageRadius[2];
    local int Pellets[2];
local float HeadMultiplier[2];
    local int MaxPens[2];
local int Pellets[2];
    local float PenReduction[2];
local int MaxPens[2];
   
local float PenReduction[2];
    local int i, x;
   
local int i, x;
    // Main loop
    for (i = 0; class'KFLevelRules'.default.ItemForSale[i] != none; i++)
// Main loop
    {
for (i = 0; class'KFLevelRules'.default.ItemForSale[i] != none; i++)
        Pickup = class<KFWeaponPickup>(class'KFLevelRules'.default.ItemForSale[i]);
{
        if (Pickup != none)
Pickup = class<KFWeaponPickup>(class'KFLevelRules'.default.ItemForSale[i]);
        {
if (Pickup != none)
            Weapon = class<KFWeapon>(Pickup.default.InventoryType);
{
            if (Weapon != none)
Weapon = class<KFWeapon>(Pickup.default.InventoryType);
            {
if (Weapon != none)
                for (x = 0; x < 2; x++)
{
                {
for (x = 0; x < 2; x++)
                    if (Weapon.default.FireModeClass[x] != none && IsTrueFire(Weapon.default.FireModeClass[x]))
{
                        Fire[x] = Weapon.default.FireModeClass[x];
if (Weapon.default.FireModeClass[x] != none && IsTrueFire(Weapon.default.FireModeClass[x]))
                    else
Fire[x] = Weapon.default.FireModeClass[x];
                        Fire[x] = none;
else
                }
Fire[x] = none;
                       
}
                GetName(Name);
                 GetCost(Cost);
GetName(Name);
                GetWeight(Weight);
                 GetPerk(Perk);
                GetCapacity(Capacity);
GetCost(Cost);
                GetMagazineSize(MagazineSize);
GetWeight(Weight);
                GetFireRate(FireRate);
GetCapacity(Capacity);
                GetReloadSpeed(ReloadSpeed);
GetMagazineSize(MagazineSize);
                GetSpread(Spread);
GetFireRate(FireRate);
                GetDamage(Damage);
GetReloadSpeed(ReloadSpeed);
                GetDamageRadius(DamageRadius);
GetSpread(Spread);
                GetHeadMultiplier(HeadMultiplier);
GetDamage(Damage);
                GetPellets(Pellets);
GetDamageRadius(DamageRadius);
                GetMaxPens(MaxPens);
GetHeadMultiplier(HeadMultiplier);
                GetPenReduction(PenReduction);
GetPellets(Pellets);
               
GetMaxPens(MaxPens);
                OutputStat  ("Name", Name);
GetPenReduction(PenReduction);
                OutputStatNum("Cost", Cost);
                OutputStatNum("Weight", Weight);
OutputStat  ("Name", Name);
                OutputStatNum("Capacity", Capacity[0], Capacity[1]);
OutputStat ("Perk", Perk);
                OutputStatNum("Magazine", MagazineSize[0], MagazineSize[1]);
OutputStatNum("Cost", Cost);
                OutputStatNum("Fire rate", FireRate[0], FireRate[1]);
OutputStatNum("Weight", Weight);
                OutputStatNum("Reload sp", ReloadSpeed[0], ReloadSpeed[1]);
OutputStatNum("Capacity", Capacity[0], Capacity[1]);
                OutputStatNum("Spread", Spread[0], Spread[1]);
OutputStatNum("Magazine", MagazineSize[0], MagazineSize[1]);
                OutputStatNum("Damage", Damage[0], Damage[1]);
OutputStatNum("Fire rate", FireRate[0], FireRate[1]);
                OutputStatNum("Radius", DamageRadius[0], DamageRadius[0]);
OutputStatNum("Reload sp", ReloadSpeed[0], ReloadSpeed[1]);
                OutputStatNum("Head", HeadMultiplier[0], HeadMultiplier[1] );
OutputStatNum("Spread", Spread[0], Spread[1]);
                OutputStatNum("Pellets", Pellets[0], Pellets[1]);
OutputStatNum("Damage", Damage[0], Damage[1]);
                OutputStatNum("Max pens", MaxPens[0], MaxPens[1]);
OutputStatNum("Radius", DamageRadius[0], DamageRadius[0]);
                OutputStatNum("Pen reduc", PenReduction[0], PenReduction[1]);
OutputStatNum("Head", HeadMultiplier[0], HeadMultiplier[1] );
                Log("");
OutputStatNum("Pellets", Pellets[0], Pellets[1]);
            }
OutputStatNum("Max pens", MaxPens[0], MaxPens[1]);
        }
OutputStatNum("Pen reduc", PenReduction[0], PenReduction[1]);
    }
Log("");
   
}
    Destroy();
}
}
Destroy();
}
}


Line 171: Line 176:
function GetName(out string Name)
function GetName(out string Name)
{
{
    Name = Pickup.default.ItemName;
Name = Pickup.default.ItemName;
}
 
function GetPerk(out string Perk)
{
// CorrespondingPerkIndex
}
}


function GetCost(out int Cost)
function GetCost(out int Cost)
{
{
    Cost = Pickup.default.Cost;
Cost = Pickup.default.Cost;
}
}


function GetWeight(out int Weight)
function GetWeight(out int Weight)
{
{
    Weight = Pickup.default.Weight;
Weight = Pickup.default.Weight;
}
}


function GetCapacity(out int Capacity[2], optional int Index)
function GetCapacity(out int Capacity[2], optional int Index)
{
{
    Capacity[Index] = 0;
Capacity[Index] = 0;
    if (Index == 0) GetCapacity(Capacity, 1);
if (Index == 0) GetCapacity(Capacity, 1);


    if (Fire[Index] != none && !IsMeleeFire(Fire[Index]) && Fire[Index].default.AmmoClass != none)
if (Fire[Index] != none && !IsMeleeFire(Fire[Index]) && Fire[Index].default.AmmoClass != none)
        Capacity[Index] = Fire[Index].default.AmmoClass.default.MaxAmmo;
Capacity[Index] = Fire[Index].default.AmmoClass.default.MaxAmmo;
}
}


function GetMagazineSize(out int MagazineSize[2])
function GetMagazineSize(out int MagazineSize[2])
{
{
    MagazineSize[0] = Weapon.default.MagCapacity;
MagazineSize[0] = Weapon.default.MagCapacity;
    MagazineSize[1] = 0; // Can't be obtained normally
MagazineSize[1] = 0; // Can't be obtained normally
}
}


function GetFireRate(out float FireRate[2], optional int Index)
function GetFireRate(out float FireRate[2], optional int Index)
{
{
    FireRate[Index] = 0;
FireRate[Index] = 0;
    if (Index == 0) GetFirerate(FireRate, 1);
if (Index == 0) GetFirerate(FireRate, 1);


    if (Fire[Index] != none)
if (Fire[Index] != none)
        FireRate[Index] = Fire[Index].default.FireRate;
FireRate[Index] = Fire[Index].default.FireRate;
}
}


function GetReloadSpeed(out float ReloadSpeed[2], optional int Index)
function GetReloadSpeed(out float ReloadSpeed[2], optional int Index)
{
{
    ReloadSpeed[Index] = 0;
ReloadSpeed[Index] = 0;
    if (Index == 0) GetReloadSpeed(ReloadSpeed, 1);
if (Index == 0) GetReloadSpeed(ReloadSpeed, 1);
   
    if (Fire[Index] != none)
if (Fire[Index] != none)
        ReloadSpeed[Index] = Weapon.default.ReloadRate; // (3)
ReloadSpeed[Index] = Weapon.default.ReloadRate; // (3)
}
}


function GetSpread(out float Spread[2], optional int Index)
function GetSpread(out float Spread[2], optional int Index)
{
{
    Spread[Index] = 0;
Spread[Index] = 0;
    if (Index == 0) GetSpread(Spread, 1);
if (Index == 0) GetSpread(Spread, 1);
   
    if (Fire[Index] != none)
if (Fire[Index] != none)
        Spread[Index] = Fire[Index].default.Spread;
Spread[Index] = Fire[Index].default.Spread;
}
}


function GetDamage(out int Damage[2], optional int Index)
function GetDamage(out int Damage[2], optional int Index)
{
{
    Damage[Index] = 0;
Damage[Index] = 0;
    if (Index == 0) GetDamage(Damage, 1);
if (Index == 0) GetDamage(Damage, 1);


    if (Fire[Index] != none)
if (Fire[Index] != none)
    {
{
        if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
            Damage[Index] = class<InstantFire>(Fire[Index]).default.DamageMax;
Damage[Index] = class<InstantFire>(Fire[Index]).default.DamageMax;
        else if(class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
else if(class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
        {
{
            if (class<MP7MMedicGun>(Weapon) != none)
if (class<MP7MMedicGun>(Weapon) != none)
                Damage[Index] = class<MP7MMedicGun>(Weapon).default.HealBoostAmount;
Damage[Index] = class<MP7MMedicGun>(Weapon).default.HealBoostAmount;
            else if (class<M7A3MMedicGun>(Weapon) != none)
else if (class<M7A3MMedicGun>(Weapon) != none)
                Damage[Index] = class<M7A3MMedicGun>(Weapon).default.HealBoostAmount;
Damage[Index] = class<M7A3MMedicGun>(Weapon).default.HealBoostAmount;
            else
else
                Damage[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.Damage;
Damage[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.Damage;
        }
}
        else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
        {
{
            Damage[Index] = class<KFMeleeFire>(Fire[Index]).default.DamageConst +
Damage[Index] = class<KFMeleeFire>(Fire[Index]).default.DamageConst +
                class<KFMeleeFire>(Fire[Index]).default.MaxAdditionalDamage;
class<KFMeleeFire>(Fire[Index]).default.MaxAdditionalDamage;
        }
}
    }
}
}
}


function GetDamageRadius(out float DamageRadius[2], optional int Index)
function GetDamageRadius(out float DamageRadius[2], optional int Index)
{
{
    local class<DamageType> DT;
local class<DamageType> DT;
   
    DamageRadius[Index] = 0;
DamageRadius[Index] = 0;
    if (Index == 0) GetDamageRadius(DamageRadius, 1);
if (Index == 0) GetDamageRadius(DamageRadius, 1);
   
    if (Fire[Index] != none && class<BaseProjectileFire>(Fire[Index]) != none)
if (Fire[Index] != none && class<BaseProjectileFire>(Fire[Index]) != none)
    {
{
        DT = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.MyDamageType;
DT = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.MyDamageType;
        if (class<KFWeaponDamageType>(DT) != none)
if (class<KFWeaponDamageType>(DT) != none)
        {
{
            if (class<KFWeaponDamageType>(DT).default.bIsExplosive)
if (class<KFWeaponDamageType>(DT).default.bIsExplosive)
                DamageRadius[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.DamageRadius;
DamageRadius[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.DamageRadius;
        }
}
    }
}
}
}


function GetHeadMultiplier(out float HeadMultiplier[2], optional int Index)
function GetHeadMultiplier(out float HeadMultiplier[2], optional int Index)
{
{
    local class<Projectile> P;
local class<Projectile> P;


    HeadMultiplier[Index] = 1.0;
HeadMultiplier[Index] = 1.0;
    if (Index == 0) GetHeadMultiplier(HeadMultiplier, 1);
if (Index == 0) GetHeadMultiplier(HeadMultiplier, 1);
   
    if (Fire[Index] != none)
if (Fire[Index] != none)
    {
{
        if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
        {
{
            if (class<KFWeaponDamageType>(class<InstantFire>(Fire[Index]).default.DamageType) != none)
if (class<KFWeaponDamageType>(class<InstantFire>(Fire[Index]).default.DamageType) != none)
                HeadMultiplier[Index] = class<KFWeaponDamageType>(
HeadMultiplier[Index] = class<KFWeaponDamageType>(
                    class<InstantFire>(Fire[Index]).default.DamageType).default.HeadShotDamageMult;
class<InstantFire>(Fire[Index]).default.DamageType).default.HeadShotDamageMult;
        }
}
        else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
        {
{
            P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
           
            if (class<ShotgunBullet>(P) != none) // MOST PROJECTILES
if (class<ShotgunBullet>(P) != none) // MOST PROJECTILES
                HeadMultiplier[Index] = class<ShotgunBullet>(P).default.HeadShotDamageMult;
HeadMultiplier[Index] = class<ShotgunBullet>(P).default.HeadShotDamageMult;
            else if (class<CrossbowArrow>(P) != none) // CROSSBOW
else if (class<CrossbowArrow>(P) != none) // CROSSBOW
                HeadMultiplier[Index] = class<CrossbowArrow>(P).default.HeadShotDamageMult;
HeadMultiplier[Index] = class<CrossbowArrow>(P).default.HeadShotDamageMult;
            else if (class<HuskGunProjectile>(P) != none) // HUSK GUN
else if (class<HuskGunProjectile>(P) != none) // HUSK GUN
                HeadMultiplier[Index] = class<HuskGunProjectile>(P).default.HeadShotDamageMult;
HeadMultiplier[Index] = class<HuskGunProjectile>(P).default.HeadShotDamageMult;
            else if (class<M99Bullet>(P) != none) // M99
else if (class<M99Bullet>(P) != none) // M99
                HeadMultiplier[Index] = class<M99Bullet>(P).default.HeadShotDamageMult;
HeadMultiplier[Index] = class<M99Bullet>(P).default.HeadShotDamageMult;
        }
}
    }
else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
{
if (class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass) != none)
HeadMultiplier[Index] = class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass).default.HeadShotDamageMult;
}
}
}
}


function GetPellets(out int Pellets[2], optional int Index)
function GetPellets(out int Pellets[2], optional int Index)
{
{
    Pellets[Index] = 0;
Pellets[Index] = 0;
    if (Index == 0) GetPellets(Pellets, 1);
if (Index == 0) GetPellets(Pellets, 1);


    if (Fire[Index] != none && class<KFShotgunFire>(Fire[Index]) != none)
if (Fire[Index] != none && class<KFShotgunFire>(Fire[Index]) != none)
    {
{
        if (IgnoresLoad(Fire[Index])) // (1) see note
if (IgnoresLoad(Fire[Index])) // (1) see note
            Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire;
Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire;
        else
else
        Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire *
Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire *
            class<BaseProjectileFire>(Fire[Index]).default.AmmoPerFire;
class<BaseProjectileFire>(Fire[Index]).default.AmmoPerFire;
    }
}
}
}


function GetMaxPens(out int MaxPens[2], optional int Index)
function GetMaxPens(out int MaxPens[2], optional int Index)
{
{
    local class<Projectile> P;
local class<Projectile> P;


    MaxPens[Index] = 0;
MaxPens[Index] = 0;
    if (Index == 0) GetMaxPens(MaxPens, 1);
if (Index == 0) GetMaxPens(MaxPens, 1);
   
    if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
    {
{
        // (2) Deagle, MK23, 44Magnum
// (2) Deagle, MK23, 44Magnum
    }
}
    else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
    {
{
        P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
       
        if (class<ShotgunBullet>(P) != none)
if (class<ShotgunBullet>(P) != none)
            MaxPens[Index] = class<ShotgunBullet>(P).default.MaxPenetrations;
MaxPens[Index] = class<ShotgunBullet>(P).default.MaxPenetrations;
    }
}
}
}


function GetPenReduction(out float PenReduction[2], optional int Index)
function GetPenReduction(out float PenReduction[2], optional int Index)
{
{
    local class<Projectile> P;
local class<Projectile> P;


    PenReduction[Index] = 0;
PenReduction[Index] = 0;
    if (Index == 0) GetPenReduction(PenReduction, 1);
if (Index == 0) GetPenReduction(PenReduction, 1);
   
    if (class<BaseProjectileFire>(Fire[Index]) != none)
if (class<BaseProjectileFire>(Fire[Index]) != none)
    {
{
        P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
        if (class<ShotgunBullet>(P) != none)
if (class<ShotgunBullet>(P) != none)
            PenReduction[Index] = class<ShotgunBullet>(P).default.PenDamageReduction;
PenReduction[Index] = class<ShotgunBullet>(P).default.PenDamageReduction;
    }
}
}
}


defaultproperties
defaultproperties
{
{
    GroupName="KFStatOutputMut"
GroupName="KFStatOutputMut"
    FriendlyName"KFStatOutput"
FriendlyName"KFStatOutput"
    Description="..."
Description="..."
}</pre></blockquote>
}</pre></blockquote>

Revision as of 02:00, 12 October 2012

This is my stat generator for the killing floor weapon pages. --Benjamin (talk) 20:42, 11 October 2012 (EDT)

//=============================================================================
// Weapon stat generator	12-October-2012	Benjamin
//
// KNOWN ISSUES
//
//		* Cannot detect where different fire modes share the same
//		ammo (boomstick)
//
//		* Cannot detect penetration for all weapons.
//
//		* (!) Cannot obtain hunting shotgun (or crossbow) reload speed
//
// INFO
//
// All instant-fire weapons rely on the DamageType for the head shot
// multiplier.
//
// Any projectiles that derive from ShotgunBullet.uc use 'HeadShotDamageMult' 
// as the head damage multiplier. The following projectiles implement their own
// with the same name:
//
// CrossbowArrow.uc
// HuskGunProjectile.uc
// M99Bullet.uc
//
// NOTES
//
// (1) Certain classes don't use AmmoPerFire: MP7MAltFire, M7A3MAltFire
// (2) Hardcoded penetration values: Deagle, MK23, 44Magnum 
//	* Also crossbow and M99
// (3) Weapons only have a single ReloadRate stat
//=============================================================================

class KFStatOutputMut extends Mutator;

var class<KFWeaponPickup> Pickup;
var class<KFWeapon> Weapon;
var class<WeaponFire> Fire[2];

function bool IsTrueFire(class<WeaponFire> Fire)
{
	if (Fire.Name == 'NoFire'
		|| Fire.Name == 'ShotgunLightFire'
		|| Fire.Name == 'SingleALTFire'
		)
		return false;
	
	return true;
}

function bool IsMeleeFire(class<WeaponFire> Fire)
{
	if (Fire == none)
		return false;
	if (class<KFMeleeFire>(Fire) != none)
		return true;
	return false;
}

function bool IgnoresLoad(class<WeaponFire> Fire)
{
	if (class<MP7MAltFire>(Fire) != none
		|| class<M7A3MAltFire>(Fire) != none)
		
		return true;
	
	return false;
}

function OutputStatNum(string Title, float Stat, optional float AltStat)
{
	OutputStat(Title, string(Stat), string(AltStat));
}

function OutputStat(string Title, string Stat, optional string AltStat)
{
	local int A, x;
	
	// Adjust stat name
	Title $= ":";
	A = Len(Title);
	if (A < 14)
	{
		for (x = 0; x < 14 - A; x++)
			Title $= " ";
	}
	
	if (Fire[1] != none && AltStat != "")
		Log(Title $ Stat @ "(" $ AltStat $ ")");
	else
		Log(Title $ Stat);
}

function PostBeginPlay()
{
	local string	Name;
    local string	Perk;
	local int		Cost;
	local int		Weight;
	local int		Capacity[2];
	local int		MagazineSize[2];
	local float		FireRate[2];
	local float		ReloadSpeed[2];
	local float		Spread[2];
	local int		Damage[2];
	local float		DamageRadius[2];
	local float		HeadMultiplier[2];
	local int		Pellets[2];
	local int		MaxPens[2];
	local float		PenReduction[2];
	
	local int i, x;
	
	// Main loop
	for (i = 0; class'KFLevelRules'.default.ItemForSale[i] != none; i++)
	{
		Pickup = class<KFWeaponPickup>(class'KFLevelRules'.default.ItemForSale[i]);
		if (Pickup != none)
		{
			Weapon = class<KFWeapon>(Pickup.default.InventoryType);
			if (Weapon != none)
			{
				for (x = 0; x < 2; x++)
				{
					if (Weapon.default.FireModeClass[x] != none && IsTrueFire(Weapon.default.FireModeClass[x]))
						Fire[x] = Weapon.default.FireModeClass[x];
					else
						Fire[x] = none;
				}
						
				GetName(Name);
                GetPerk(Perk);
				GetCost(Cost);
				GetWeight(Weight);
				GetCapacity(Capacity);
				GetMagazineSize(MagazineSize);
				GetFireRate(FireRate);
				GetReloadSpeed(ReloadSpeed);
				GetSpread(Spread);
				GetDamage(Damage);
				GetDamageRadius(DamageRadius);
				GetHeadMultiplier(HeadMultiplier);
				GetPellets(Pellets);
				GetMaxPens(MaxPens);
				GetPenReduction(PenReduction);
				
				OutputStat   ("Name", 		Name);
				OutputStat	 ("Perk",		Perk);	
				OutputStatNum("Cost", 		Cost);
				OutputStatNum("Weight",	 	Weight);
				OutputStatNum("Capacity", 	Capacity[0], Capacity[1]);
				OutputStatNum("Magazine", 	MagazineSize[0], MagazineSize[1]);
				OutputStatNum("Fire rate", 	FireRate[0], FireRate[1]);
				OutputStatNum("Reload sp",	ReloadSpeed[0], ReloadSpeed[1]);
				OutputStatNum("Spread", 	Spread[0], Spread[1]);
				OutputStatNum("Damage", 	Damage[0], Damage[1]);
				OutputStatNum("Radius", 	DamageRadius[0], DamageRadius[0]);
				OutputStatNum("Head", 		HeadMultiplier[0], HeadMultiplier[1] );
				OutputStatNum("Pellets", 	Pellets[0], Pellets[1]);
				OutputStatNum("Max pens",	MaxPens[0], MaxPens[1]);
				OutputStatNum("Pen reduc",	PenReduction[0], PenReduction[1]);
				Log("");
			}
		}
	}
	
	Destroy();
}

///////////////////////////////////////////////////////////////////////////////
// STAT CALCULATION
///////////////////////////////////////////////////////////////////////////////

function GetName(out string Name)
{
	Name = Pickup.default.ItemName;
}

function GetPerk(out string Perk)
{
	// CorrespondingPerkIndex
}

function GetCost(out int Cost)
{
	Cost = Pickup.default.Cost;
}

function GetWeight(out int Weight)
{
	Weight = Pickup.default.Weight;
}

function GetCapacity(out int Capacity[2], optional int Index)
{
	Capacity[Index] = 0;
	if (Index == 0) GetCapacity(Capacity, 1);

	if (Fire[Index] != none && !IsMeleeFire(Fire[Index]) && Fire[Index].default.AmmoClass != none)
		Capacity[Index] = Fire[Index].default.AmmoClass.default.MaxAmmo;	
}

function GetMagazineSize(out int MagazineSize[2])
{
	MagazineSize[0] = Weapon.default.MagCapacity;
	MagazineSize[1] = 0; // Can't be obtained normally
}

function GetFireRate(out float FireRate[2], optional int Index)
{
	FireRate[Index] = 0;
	if (Index == 0) GetFirerate(FireRate, 1);

	if (Fire[Index] != none)
		FireRate[Index] = Fire[Index].default.FireRate;
}

function GetReloadSpeed(out float ReloadSpeed[2], optional int Index)
{
	ReloadSpeed[Index] = 0;
	if (Index == 0) GetReloadSpeed(ReloadSpeed, 1);
	
	if (Fire[Index] != none)
		ReloadSpeed[Index] = Weapon.default.ReloadRate; // (3)
}

function GetSpread(out float Spread[2], optional int Index)
{
	Spread[Index] = 0;
	if (Index == 0) GetSpread(Spread, 1);
	
	if (Fire[Index] != none)
		Spread[Index] = Fire[Index].default.Spread;
}

function GetDamage(out int Damage[2], optional int Index)
{
	Damage[Index] = 0;
	if (Index == 0) GetDamage(Damage, 1);	

	if (Fire[Index] != none)
	{
		if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
			Damage[Index] = class<InstantFire>(Fire[Index]).default.DamageMax;
		else if(class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
		{
			if (class<MP7MMedicGun>(Weapon) != none)
				Damage[Index] = class<MP7MMedicGun>(Weapon).default.HealBoostAmount;
			else if (class<M7A3MMedicGun>(Weapon) != none)
				Damage[Index] = class<M7A3MMedicGun>(Weapon).default.HealBoostAmount;
			else
				Damage[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.Damage;
		}
		else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
		{
			Damage[Index] = class<KFMeleeFire>(Fire[Index]).default.DamageConst +
				class<KFMeleeFire>(Fire[Index]).default.MaxAdditionalDamage;
		}
	}
}

function GetDamageRadius(out float DamageRadius[2], optional int Index)
{
	local class<DamageType> DT;
	
	DamageRadius[Index] = 0;
	if (Index == 0) GetDamageRadius(DamageRadius, 1);
	
	if (Fire[Index] != none && class<BaseProjectileFire>(Fire[Index]) != none)
	{
		DT = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.MyDamageType;
		if (class<KFWeaponDamageType>(DT) != none)
		{
			if (class<KFWeaponDamageType>(DT).default.bIsExplosive)
				DamageRadius[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass.default.DamageRadius;
		}
	}
}

function GetHeadMultiplier(out float HeadMultiplier[2], optional int Index)
{
	local class<Projectile> P;

	HeadMultiplier[Index] = 1.0;
	if (Index == 0) GetHeadMultiplier(HeadMultiplier, 1);
	
	if (Fire[Index] != none)
	{
		if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
		{
			if (class<KFWeaponDamageType>(class<InstantFire>(Fire[Index]).default.DamageType) != none)
				HeadMultiplier[Index] = class<KFWeaponDamageType>(
					class<InstantFire>(Fire[Index]).default.DamageType).default.HeadShotDamageMult;
		}
		else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
		{
			P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
			
			if (class<ShotgunBullet>(P) != none) // MOST PROJECTILES
				HeadMultiplier[Index] = class<ShotgunBullet>(P).default.HeadShotDamageMult;
			else if (class<CrossbowArrow>(P) != none) // CROSSBOW
				HeadMultiplier[Index] = class<CrossbowArrow>(P).default.HeadShotDamageMult;
			else if (class<HuskGunProjectile>(P) != none) // HUSK GUN
				HeadMultiplier[Index] = class<HuskGunProjectile>(P).default.HeadShotDamageMult;
			else if (class<M99Bullet>(P) != none) // M99
				HeadMultiplier[Index] = class<M99Bullet>(P).default.HeadShotDamageMult;
		}
		else if (class<KFMeleeFire>(Fire[Index]) != none) // MELEE
		{
			if (class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass) != none)
				HeadMultiplier[Index] = class<DamTypeMelee>(class<KFMeleeFire>(Fire[Index]).default.hitDamageClass).default.HeadShotDamageMult;
		}
	}
}

function GetPellets(out int Pellets[2], optional int Index)
{
	Pellets[Index] = 0;
	if (Index == 0) GetPellets(Pellets, 1);

	if (Fire[Index] != none && class<KFShotgunFire>(Fire[Index]) != none)
	{
		if (IgnoresLoad(Fire[Index])) // (1) see note
			Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire;
		else
		Pellets[Index] = class<BaseProjectileFire>(Fire[Index]).default.ProjPerFire *
			class<BaseProjectileFire>(Fire[Index]).default.AmmoPerFire;
	}
}

function GetMaxPens(out int MaxPens[2], optional int Index)
{
	local class<Projectile> P;

	MaxPens[Index] = 0;
	if (Index == 0) GetMaxPens(MaxPens, 1);
	
	if (class<InstantFire>(Fire[Index]) != none) // HITSCAN
	{
		// (2) Deagle, MK23, 44Magnum
	}
	else if (class<BaseProjectileFire>(Fire[Index]) != none) // PROJECTILE
	{
		P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
		
		if (class<ShotgunBullet>(P) != none)
			MaxPens[Index] = class<ShotgunBullet>(P).default.MaxPenetrations;
	}
}

function GetPenReduction(out float PenReduction[2], optional int Index)
{
	local class<Projectile> P;

	PenReduction[Index] = 0;
	if (Index == 0) GetPenReduction(PenReduction, 1);
	
	if (class<BaseProjectileFire>(Fire[Index]) != none)
	{
		P = class<BaseProjectileFire>(Fire[Index]).default.ProjectileClass;
		if (class<ShotgunBullet>(P) != none)
			PenReduction[Index] = class<ShotgunBullet>(P).default.PenDamageReduction;
	}
}

defaultproperties
{
	GroupName="KFStatOutputMut"
	FriendlyName"KFStatOutput"
	Description="..."
}