Partial Player class handling player statistics and result tracking. Defines enums for PlayerStat, StatFormat, ResultStat, modifier types, stores base and modified stat values, applies modifiers (set/add/mult) with priorities, syncs selected stats over network, formats stat strings for UI, tracks DPS and result stats, and updates time-based progress counters.
using System;
using static System.Runtime.InteropServices.JavaScript.JSType;
public enum ModifierType { Set, Add, Mult }
public class ModifierData
{
public float value;
public ModifierType type;
public float priority;
public ModifierData( float _value, ModifierType _type, float _priority = 0f )
{
value = _value;
type = _type;
priority = _priority;
}
}
public enum PlayerStat
{
AttackTime, AttackSpeed, ReloadTime, ReloadSpeed, MaxAmmoCount, BulletDamage, BulletForce, Kickback, MoveSpeedMultiplier, [Title( "Bullets Per Shot" )] NumProjectiles, BulletSpread, ShotInaccuracy, BulletSpeed, BulletLifetime,
BulletNumPiercing, BulletNumBouncing, CritChance, CritMultiplier, CritMultipleChance, LowHealthDamageMultiplier, NumPerkChoices, HealthRegen, HealthRegenStill, HealthDrain, DamageReductionPercent, PushStrength, CoinAttractRange, CoinAttractStrength,
PowerupAttractRange, PowerupAttractStrength, Luck, MaxHp, NumDashes, NumTempDashes, DashInvulnTime, DashCooldown, DashProgress, DashStrength, ShootFireIgniteChance, FireDamage, FireLifetime, FireSpreadChance, ShootFreezeChance, FreezeLifetime,
[Title( "Freeze Slow Amount" )] FreezeTimeScale, FreezeFireDamageMultiplier, LastAmmoDamageMultiplier, FearLifetime, FearDamageMultiplier, BulletDamageGrow,
BulletDistanceDamage, NumRerollsPerLevel, FullHealthDamageMultiplier, DamagePerEarlierShot, DamageForSpeed, OverallDamageMultiplier, NonBulletDamageMultiplier, ExplosionSizeMultiplier, GrenadeVelocity, ExplosionDamageMultiplier,
BulletDamageMultiplier, NonExplosionDamageIncreasePercent, BombStickyStrength, ExplosionFearChance, FearDrainPercent, FearPainPercent, BarrelChanceAdditional, //ExplosionDamageReductionPercent
AttackSpeedStill, ReloadSpeedStill, FearDropGrenadeChance, FrozenShardsNum, NoDashInvuln, GrenadesCanCrit, BulletMoveRandomly, CanChangeDashDirection,
BulletHomingRadius, BulletReturning, Blink, BlinkToCursor, ReloadingMovespeedMultiplier, ShootingMovespeedMultiplier, Friction, DashSlashBulletDamagePercent,
CameraDistance, KeyBrokenE, FpsMode, ExistingPerkChance, RarerPerkChance, RadiusMultiplier,
BulletExtraPierceChance, BulletExtraBounceChance, BulletExtraBounceAmount, BulletSplashChance, BulletSplashDamagePercent, RadiationDelay, RadiationHealAmount, RadiationRepelAmount,
XpGainMultiplier, BulletHitStreakDmg, ClipDamageBonus, HealthyUnitDamagePercent, BackstabBonusDamagePercent, BossSpawnSecondsEarly,
ExtraProjectileChance, ExtraProjectileNum, BoomerangSelfDamagePercent, BoomerangeExtraDmg, BoomerangBounceSelfNum, BulletRandomDamagePercentMin, BulletRandomDamagePercentMax, Scale, BulletBounceDamageIncrease,
BulletBounceResetLifetime, FearVoodoo, ShotDamageMult, ShotDamageAdd, NextBulletDamageMult, BacksideDamageReductionPercent, UpsideDown,
DamagePercentPerBanished, BulletCanHitShooter, BulletSteering, BulletBounceTargetChance, RandomBulletAngleInSpread, AlternateAimDir, PoisonDamage, ShootPoisonChance,
PoisonFinishDamagePercent, PoisonDieSpreadChance, PoisonDmgNearbyIncrease, PoisonTickTimeModifier, PoisonNumHitsToRemove, AdditionalLightningChains, LevelUpExistingPerkChance, IgnoreSelfDamageWhenInvuln, InvulnAmount,
RarityIncreaseCommon, RarityIncreaseUncommon, RarityIncreaseRare, RarityIncreaseEpic, RarityIncreaseMythic, RarityIncreaseLegendary, RarityIncreaseUnique,
RarityIncreaseCurse,
CopyNextPerk, TurnSpeed, JumpNotDash, LandingHpDmgPercent,
ArcBulletsStill, BulletArcHeight, ArcBulletDamageAdd, ArcBulletSpeedMult, ArcBulletBounces, ArcBulletsBounceGround, StillBulletDamageAdd,
FearDamageReductionPercent, FullHpDamageReductionPercent, SelfDmgReductionPercent, ArmorDamageReductionPercent, StillDamageReductionPercent,
IsBerserk, NthShotNumBullets, NthShotReq, NthShotParallelReq, NthShotParallelNumBullets, FirstShotNumExtraBullets, FreeRerollTime, AcidHealHpPercent, //FreezeDoubleDmg,
ShotNum, NumShotsWithoutBulletHitGround, TotalShotNum, ClipNum, CantShoot, BulletOverflowPercent, AlternatePlayerDamagePercent, CoupDeGracePercent, TakeFriendlyDmg,
OverrideNumPerkChoices, CantMove, CantMoveWhileChoosing, MaxHpCap, BasicZombieDmgMod, PoisonFlammable, SpearPoison, ExplosionMagnet, ExplosionInward, ChooseTimeLimit, ZeroRerollDmgMult,
FireDmgStack, FearArmorActive, HealthPacksHurt, ReverseMoveControls, ReverseAimControls, ArmorRerollCost, DisableXpBarTransition,
CritStreak, CritStreakDmgAmount, NumLandmineBulletsPerAmmo, LandmineRepelPlayerAmount, HealthPackExtraHp,
MoveAlignmentForwardMultiplier, MoveAlignmentBackwardMultiplier,
ShootMultipleProjectilesParallel, ClickAddPerk, ClickRemovePerk, SkipPerkNumRerolls, CanChooseRandomPerk,
PunchBullets, PunchDamagePercent, PunchNumExtraHits, LastPunchForceMultiplier,
//PerkChanceCommon, PerkChanceUncommon, PerkChanceRare, PerkChanceEpic, PerkChanceMythic, PerkChanceLegendary, PerkChanceUnique,
OnlyShootWithMouse1, AutoAim,
DrainUntil1Hp, PreventDeathOver1Hp, LoseHpBeforeArmorAt1Hp, HealEffectiveness, LowHealthHealEffectiveness,
//DetectionRangeModifier,
ZigZagWalkFactor, TurretShootDelay,
CurseUnknownPerkChance,
BulletAimAtCursorChance, KillMagnetizeCoinChance,
BulletHealTeammateChance, BulletHealTeammateAmount, BulletHealTeammateDmgMult,
DodgeChance, LowHealthDodgeChance, DodgeExtraAttempts, DodgeGuaranteedNum, DodgeNextAttack,
ShootRandomDirChance, DashRandomDirChance, BulletForceRandomDir,
FlatDamageTakenIncrease, SelfCritChance, FlatDmgReductionThreshold,
CoinHealAmount, HealthpackXpPercent, CoinFlatDmgAmount,
CurseXpRepel, InvisibleEnemyChance,
ArtillerySupplyChance,
OrbiterBladeHitInterval, OrbiterBladeStopTime, OrbiterBladeBulletChance, OrbiterBladeSpeedMultiplier,
EnemySpawnTimeModifier, MovementRelativeToAimDir, DontCauseDmgNumbers,
BarrelHazardChance, BarrelLootChance, ShieldMinDmg, MorePerkChoicesChance, MorePerkChoicesNumChances, NumChoicesHurt, GemPerkChoiceChance,
EnemyMeleeForceAdd, FlyingSkullMultiHit, CantShootWhileMoving,
DashFailSelfDmg,
RerollOnlyOnePerkChoice,
UnpausedChoosing,
PreventPausing,
PerspectiveCamera,
RotationalRecoil,
ExplosionDamageTakenMultiplier,
NumBulletsHitGround, ShootExplosiveBullets,
HpBarHidden,
EnemySpawnNearPlayer,
PunchLifestealPercent,
NumEnemiesKilled, TotalHealed, NumTimesDied,
// display
InvulnAfterHurtTimeDisplay, DodgeAoeDamagePercent, DodgeHealChance, DodgeReloadChance, HpRegenDisplay, HpRegenPerKillDisplay, RerollHealDisplay,
XpDamageDisplay, BulletHomingRadiusDisplay, FearOnMeleeCooldownDisplay, FreezeOnMeleeCooldownDisplay, DelayedRecoveryPercentDisplay, DelayedRecoveryDelayDisplay,
FreezeStrengthDisplay,
//MaxHpDisplay,
}
public enum StatFormat
{
Int, IntDiff, Decimals1, Decimals1Plus, Decimals2, Percentage, PercentageDecimals1, PercentageDecimals2, PercentageInverse, PercentageDiff, PercentageAddDiff, PercentageAddDiffInverse, Seconds1, Seconds2, Degrees, PerSecond1, PerSecond2, PerDistance1, Distance1, Distance2,
}
public enum ResultStat
{
NumKills, NumMinibossKills, NumDeaths,
HpHealed, HpHealedOther,
DmgDealtTotal, DmgDealtBullet, DmgDealtFire, DmgDealtPoison, DmgDealtExplosion, DmgDealtBoomerang, DmgDealtRadiation, DmgDealtSpear, DmgDealtThorns, DmgDealtPunch, DmgDealtShock, DmgDealtAcid, DmgDealtOrbitingBlade, DmgDealtBulletSplash, DmgDealtDashSlash, DmgDealtXpShrapnel, DmgDealtMark,
DmgDealtOther,
DmgTakenTotal, DmgTakenBullet, DmgTakenSelf, DmgTakenMelee, DmgTakenProjectile, DmgTakenProjectileHoming, DmgTakenFire, DmgTakenExplosion, DmgTakenSpikerHead, DmgTakenAcid, DmgTakenShock, DmgTakenPoison, DmgTakenShockwave, DmgTakenLavaPuddle,
DmgTakenOther,
ArmorGained,
PerkLeveledUp, NewPerk, CursesGot, PerkCommon, PerkUncommon, PerkRare, PerkEpic, PerkMythic, PerkLegendary, PerkUnique,
NumTimesReroll, NumTimesBanish, HealthpacksGot, MagnetsGot, BarrelsDestroyed, ChestsOpened, EvilChestsOpened,
TimesDashed, TimesDodged, BulletCreated, NumTimesReloaded, ShieldsLost, TimesChained, ExplosionsCaused, Crit, NumEnemiesExecuted, EnemiesFrozen, MetersMoved,
LargestDmgDealt,
DmgDealtToBoss,
DmgTakenFromBoss, DmgTakenFromMiniboss, DmgTakenFromZombie, DmgTakenFromZombieElite, DmgTakenFromExploder, DmgTakenFromExploderElite, DmgTakenFromExploderMini,
DmgTakenFromSpitter, DmgTakenFromSpitterElite, DmgTakenFromSpiker, DmgTakenFromSpikerElite, DmgTakenFromRunner, DmgTakenFromRunnerElite, DmgTakenFromCharger, DmgTakenFromChargerElite,
DmgTakenFromSword, DmgTakenFromBarrelExploding, DmgTakenFromChestEvil, DmgTakenFromFence,
KilledByBoss, KilledByMiniboss, KilledByZombie, KilledByZombieElite, KilledByExploder, KilledByExploderElite, KilledByExploderMini,
KilledBySpitter, KilledBySpitterElite, KilledBySpiker, KilledBySpikerElite, KilledByRunner, KilledByRunnerElite, KilledByCharger, KilledByChargerElite,
KilledBySword, KilledByBarrelExploding, KilledByChestEvil, KilledByFence,
KilledBySelf,
KillBoss, KillMiniboss, KillZombie, KillZombieElite, KillExploder, KillExploderElite, KillExploderMini,
KillSpitter, KillSpitterElite, KillSpiker, KillSpikerElite, KillRunner, KillRunnerElite, KillCharger, KillChargerElite,
KillSword, KillBarrel, KillBarrelExploding, KillChestEvil,
Divider, None,
//KilledBy,
}
public partial class Player
{
public Dictionary<PlayerStat, float> Stats = new();
public Dictionary<PlayerStat, float> OriginalStatValues = new();
private Dictionary<IStatModifier, Dictionary<PlayerStat, ModifierData>> _statModifiers = new();
public int ModifierHash { get; set; }
[Sync] private NetDictionary<PlayerStat, float> _syncStats { get; set; } = new();
private List<PlayerStat> _syncedStats = new() {
PlayerStat.BossSpawnSecondsEarly, PlayerStat.ExplosionMagnet, PlayerStat.ExplosionInward, PlayerStat.CoinAttractRange, PlayerStat.CoinAttractStrength,
PlayerStat.TakeFriendlyDmg, PlayerStat.UpsideDown, PlayerStat.XpGainMultiplier, PlayerStat.BarrelChanceAdditional,
PlayerStat.FrozenShardsNum, PlayerStat.FireLifetime, PlayerStat.FireSpreadChance, PlayerStat.FireDmgStack, PlayerStat.FearDropGrenadeChance, PlayerStat.PoisonDmgNearbyIncrease, //PlayerStat.FreezeDoubleDmg,
PlayerStat.ExplosionFearChance, PlayerStat.FearLifetime,
PlayerStat.FreezeFireDamageMultiplier, PlayerStat.FreezeFireDamageMultiplier, PlayerStat.FearDamageMultiplier, PlayerStat.BackstabBonusDamagePercent, PlayerStat.HealthyUnitDamagePercent,
PlayerStat.AlternatePlayerDamagePercent, PlayerStat.CoupDeGracePercent, PlayerStat.AcidHealHpPercent,
PlayerStat.OverallDamageMultiplier, PlayerStat.NonBulletDamageMultiplier, PlayerStat.LowHealthDamageMultiplier, PlayerStat.FullHealthDamageMultiplier, PlayerStat.DamagePercentPerBanished, PlayerStat.ZeroRerollDmgMult,
PlayerStat.InvulnAmount, PlayerStat.NoDashInvuln, PlayerStat.KillMagnetizeCoinChance, PlayerStat.NumEnemiesKilled, PlayerStat.CurseXpRepel, PlayerStat.LandmineRepelPlayerAmount, PlayerStat.EnemySpawnTimeModifier,
PlayerStat.DontCauseDmgNumbers, PlayerStat.BarrelHazardChance, PlayerStat.BarrelLootChance, PlayerStat.FpsMode, PlayerStat.CameraDistance,
PlayerStat.MaxHp, PlayerStat.HealthRegen, PlayerStat.HealthRegenStill, PlayerStat.HpRegenDisplay, PlayerStat.HealthDrain, PlayerStat.HealEffectiveness, PlayerStat.LowHealthHealEffectiveness,
PlayerStat.FlyingSkullMultiHit, PlayerStat.PunchBullets, PlayerStat.ArcBulletsStill, PlayerStat.MaxAmmoCount, PlayerStat.RadiusMultiplier,
PlayerStat.NumDashes,
PlayerStat.TotalShotNum,
PlayerStat.ChooseTimeLimit, PlayerStat.SkipPerkNumRerolls, PlayerStat.CanChooseRandomPerk, PlayerStat.ArmorRerollCost, PlayerStat.FreeRerollTime,
PlayerStat.DisableXpBarTransition, PlayerStat.HpBarHidden,
PlayerStat.EnemySpawnNearPlayer,
//PlayerStat.DetectionRangeModifier,
};
public float GetSyncStat( PlayerStat stat )
{
if ( _syncStats.ContainsKey( stat ) )
return _syncStats[stat];
return 0f;
}
public float GetUiStat( PlayerStat stat )
{
return IsProxy ? GetSyncStat( stat ) : Stats[stat];
}
public HashSet<PlayerStat> StatsToDisplay = new();
public HashSet<PlayerStat> DefaultValueStatsToDisplay = new();
public float DpsStat { get; private set; }
private Queue<(float time, float damage)> _dpsTimes = new();
private const float DPS_INTERVAL = 5f;
[Sync] public NetDictionary<ResultStat, float> ResultStats { get; set; } = new();
[Sync] public ResultStat LastKilledBy { get; set; }
protected void InitStats()
{
foreach ( int i in Enum.GetValues( typeof( PlayerStat ) ) )
Stats[(PlayerStat)i] = 0f;
Stats[PlayerStat.MaxHp] = 100f;
Stats[PlayerStat.AttackTime] = 0.15f;
Stats[PlayerStat.MaxAmmoCount] = 5f;
Stats[PlayerStat.ReloadTime] = 1.5f;
Stats[PlayerStat.ReloadSpeed] = 1f;
Stats[PlayerStat.AttackSpeed] = 1f;
Stats[PlayerStat.BulletDamage] = 5f;
Stats[PlayerStat.BulletForce] = 10f;
Stats[PlayerStat.MoveSpeedMultiplier] = 1f;
Stats[PlayerStat.NumProjectiles] = 1f;
Stats[PlayerStat.BulletSpread] = 30f;
Stats[PlayerStat.ShotInaccuracy] = 5f;
Stats[PlayerStat.BulletSpeed] = 440f;
Stats[PlayerStat.BulletLifetime] = 0.72f;
Stats[PlayerStat.Luck] = 1f;
Stats[PlayerStat.CritChance] = 0.05f;
Stats[PlayerStat.CritMultiplier] = 1.5f;
Stats[PlayerStat.LowHealthDamageMultiplier] = 1f;
Stats[PlayerStat.FullHealthDamageMultiplier] = 1f;
Stats[PlayerStat.NumDashes] = 1f;
Stats[PlayerStat.DashCooldown] = 3.8f;
Stats[PlayerStat.DashInvulnTime] = 0.25f;
Stats[PlayerStat.DashStrength] = 250f;
Stats[PlayerStat.FireDamage] = 2.5f;
Stats[PlayerStat.FireLifetime] = 5.0f;
Stats[PlayerStat.FreezeLifetime] = 4f;
Stats[PlayerStat.FreezeTimeScale] = 0.55f;
Stats[PlayerStat.FreezeFireDamageMultiplier] = 1f;
Stats[PlayerStat.FearLifetime] = 3f;
Stats[PlayerStat.FearDamageMultiplier] = 1f;
Stats[PlayerStat.CoinAttractRange] = 155f;
Stats[PlayerStat.CoinAttractStrength] = 220f;
Stats[PlayerStat.PowerupAttractRange] = 155f;
Stats[PlayerStat.PowerupAttractStrength] = 220f;
Stats[PlayerStat.NumPerkChoices] = 3f;
Stats[PlayerStat.PushStrength] = 200f;
Stats[PlayerStat.LastAmmoDamageMultiplier] = 1f;
//Stats[PlayerStat.NumRerollsPerLevel] = 1f;
Stats[PlayerStat.OverallDamageMultiplier] = 1f;
Stats[PlayerStat.NonBulletDamageMultiplier] = 1f;
Stats[PlayerStat.ExplosionSizeMultiplier] = 1f;
Stats[PlayerStat.GrenadeVelocity] = 300f;
Stats[PlayerStat.ExplosionDamageMultiplier] = 1f;
Stats[PlayerStat.BulletDamageMultiplier] = 1f;
Stats[PlayerStat.AttackSpeedStill] = 1f;
Stats[PlayerStat.ReloadSpeedStill] = 1f;
Stats[PlayerStat.ReloadingMovespeedMultiplier] = 1f;
Stats[PlayerStat.ShootingMovespeedMultiplier] = 1f;
Stats[PlayerStat.Friction] = 8.5f;
Stats[PlayerStat.CameraDistance] = 800f;
Stats[PlayerStat.RadiusMultiplier] = 1f;
Stats[PlayerStat.RadiationDelay] = 1f;
Stats[PlayerStat.XpGainMultiplier] = 1f;
Stats[PlayerStat.HealthyUnitDamagePercent] = 1f;
Stats[PlayerStat.Scale] = 1f;
Stats[PlayerStat.PoisonDamage] = 1.2f;
Stats[PlayerStat.PoisonTickTimeModifier] = 1f;
Stats[PlayerStat.PoisonNumHitsToRemove] = 1f;
Stats[PlayerStat.TurnSpeed] = 10f;
//Stats[PlayerStat.DetectionRangeModifier] = 1f;
Stats[PlayerStat.MoveAlignmentForwardMultiplier] = 1f;
Stats[PlayerStat.MoveAlignmentBackwardMultiplier] = 1f;
Stats[PlayerStat.ArcBulletSpeedMult] = 1f;
Stats[PlayerStat.HealEffectiveness] = 1f;
Stats[PlayerStat.LowHealthHealEffectiveness] = 1f;
Stats[PlayerStat.TurretShootDelay] = 0.75f;
Stats[PlayerStat.BulletHealTeammateDmgMult] = 1f;
Stats[PlayerStat.OrbiterBladeHitInterval] = 0.7f;
Stats[PlayerStat.OrbiterBladeSpeedMultiplier] = 1f;
Stats[PlayerStat.EnemySpawnTimeModifier] = 1f;
Stats[PlayerStat.ShotDamageMult] = 1f;
//Stats[PlayerStat.MaxHpDisplay] = Stats[PlayerStat.MaxHp];
_statModifiers.Clear();
OriginalStatValues.Clear();
OriginalStatValues[PlayerStat.RarityIncreaseCommon] = 0f;
OriginalStatValues[PlayerStat.RarityIncreaseUncommon] = 0f;
OriginalStatValues[PlayerStat.RarityIncreaseRare] = 0f;
OriginalStatValues[PlayerStat.RarityIncreaseEpic] = 0f;
OriginalStatValues[PlayerStat.RarityIncreaseMythic] = 0f;
OriginalStatValues[PlayerStat.RarityIncreaseLegendary] = 0f;
OriginalStatValues[PlayerStat.RarityIncreaseUnique] = 0f;
ModifierHash = 0;
StatsToDisplay = new() {
//PlayerStat.MaxHp,
//PlayerStat.MaxHpDisplay,
//PlayerStat.DodgeChance,
PlayerStat.DodgeExtraAttempts,
PlayerStat.DodgeAoeDamagePercent,
PlayerStat.DodgeHealChance,
PlayerStat.DodgeReloadChance,
PlayerStat.InvulnAfterHurtTimeDisplay,
PlayerStat.DamageReductionPercent,
PlayerStat.BacksideDamageReductionPercent,
//PlayerStat.ExplosionDamageReductionPercent,
PlayerStat.FullHpDamageReductionPercent,
PlayerStat.SelfDmgReductionPercent,
PlayerStat.CritChance,
PlayerStat.CritMultiplier,
PlayerStat.BulletHomingRadiusDisplay,
PlayerStat.BulletSplashChance,
PlayerStat.BulletSplashDamagePercent,
PlayerStat.BulletOverflowPercent,
PlayerStat.BulletDamageGrow,
PlayerStat.BulletDistanceDamage,
PlayerStat.BulletHealTeammateAmount,
//PlayerStat.Friction,
PlayerStat.NumDashes,
PlayerStat.DashCooldown,
PlayerStat.DashStrength,
//PlayerStat.DashInvulnTime,
PlayerStat.BulletForce,
PlayerStat.Kickback,
PlayerStat.BulletSpread,
PlayerStat.ShotInaccuracy,
PlayerStat.BulletLifetime,
PlayerStat.BulletSpeed,
PlayerStat.NumPerkChoices,
PlayerStat.ExistingPerkChance,
PlayerStat.LevelUpExistingPerkChance,
PlayerStat.RarityIncreaseCommon,
PlayerStat.RarityIncreaseUncommon,
PlayerStat.RarityIncreaseRare,
PlayerStat.RarityIncreaseEpic,
PlayerStat.RarityIncreaseMythic,
PlayerStat.RarityIncreaseLegendary,
PlayerStat.RarityIncreaseUnique,
//PlayerStat.PerkChanceCommon,
//PlayerStat.PerkChanceUncommon,
//PlayerStat.PerkChanceRare,
//PlayerStat.PerkChanceEpic,
//PlayerStat.PerkChanceMythic,
//PlayerStat.PerkChanceLegendary,
//PlayerStat.PerkChanceUnique,
PlayerStat.NumRerollsPerLevel,
PlayerStat.ArmorRerollCost,
PlayerStat.RerollHealDisplay,
PlayerStat.HealthPackExtraHp,
PlayerStat.CoinAttractRange,
//PlayerStat.CoinAttractStrength,
PlayerStat.XpGainMultiplier,
PlayerStat.XpDamageDisplay,
PlayerStat.CoinHealAmount,
PlayerStat.PushStrength,
PlayerStat.TurnSpeed,
//PlayerStat.DetectionRangeModifier,
PlayerStat.ShootFireIgniteChance,
PlayerStat.FireDamage,
PlayerStat.FireLifetime,
PlayerStat.FireSpreadChance,
PlayerStat.ShootFreezeChance,
PlayerStat.FreezeStrengthDisplay,
PlayerStat.FreezeLifetime,
PlayerStat.FreezeOnMeleeCooldownDisplay,
PlayerStat.FreezeFireDamageMultiplier,
PlayerStat.ShootPoisonChance,
PlayerStat.PoisonDamage,
PlayerStat.PoisonFinishDamagePercent,
PlayerStat.PoisonDieSpreadChance,
PlayerStat.FearLifetime,
PlayerStat.FearDamageMultiplier,
PlayerStat.FearOnMeleeCooldownDisplay,
PlayerStat.FearDamageReductionPercent,
//PlayerStat.DelayedRecoveryPercentDisplay,
//PlayerStat.DelayedRecoveryDelayDisplay,
PlayerStat.DashSlashBulletDamagePercent,
PlayerStat.ExplosionDamageMultiplier,
PlayerStat.ExplosionSizeMultiplier,
PlayerStat.RadiusMultiplier,
PlayerStat.CameraDistance,
PlayerStat.Scale,
PlayerStat.HealthyUnitDamagePercent,
PlayerStat.BackstabBonusDamagePercent,
PlayerStat.AlternatePlayerDamagePercent,
};
DefaultValueStatsToDisplay = new() {
PlayerStat.BulletDamage,
PlayerStat.MaxAmmoCount,
PlayerStat.NumProjectiles,
PlayerStat.CritChance,
PlayerStat.CritMultiplier,
//PlayerStat.DashCooldown,
//PlayerStat.DashInvulnTime,
//PlayerStat.NumRerollsPerLevel,
//PlayerStat.PerkChanceCommon,
//PlayerStat.PerkChanceUncommon,
//PlayerStat.PerkChanceRare,
//PlayerStat.PerkChanceEpic,
//PlayerStat.PerkChanceMythic,
//PlayerStat.PerkChanceLegendary,
//PlayerStat.PerkChanceUnique,
};
_dpsTimes.Clear();
DpsStat = 0f;
foreach ( var statType in _syncedStats )
_syncStats[statType] = Stats[statType];
//RefreshPerkRarityChances();
ResultStats.Clear();
LastKilledBy = ResultStat.None;
}
public void AddDefaultValueStat( PlayerStat playerStat )
{
DefaultValueStatsToDisplay.Add( playerStat );
}
public void RemoveDefaultValueStat( PlayerStat playerStat )
{
DefaultValueStatsToDisplay.Remove( playerStat );
}
// An upgrade modifying the same stat type again will overwrite the previous value it set
public void Modify( IStatModifier caller, PlayerStat statType, float value, ModifierType type, float priority = 0f, bool refresh = true )
{
if ( !_statModifiers.ContainsKey( caller ) )
_statModifiers.Add( caller, new Dictionary<PlayerStat, ModifierData>() );
_statModifiers[caller][statType] = new ModifierData( value, type, priority );
if ( refresh )
RefreshProperty( statType );
}
public void StopModifying( IStatModifier caller, PlayerStat statType, bool refresh = true )
{
if ( !_statModifiers.ContainsKey( caller ) )
return;
if ( _statModifiers[caller].ContainsKey( statType ) )
{
_statModifiers[caller].Remove( statType );
if ( refresh )
RefreshProperty( statType );
}
}
public void RemoveModifiers( IStatModifier caller )
{
if ( !_statModifiers.ContainsKey( caller ) ) return;
var dict = _statModifiers[caller];
_statModifiers.Remove( caller );
foreach ( var pair in dict )
RefreshProperty( pair.Key );
}
public void AdjustBaseStat( PlayerStat statType, float amount, bool refresh = true )
{
if ( !OriginalStatValues.ContainsKey( statType ) )
OriginalStatValues.Add( statType, Stats[statType] );
OriginalStatValues[statType] += amount;
if ( refresh )
RefreshProperty( statType );
}
public float GetOriginalStatValue( PlayerStat statType )
{
if ( OriginalStatValues.ContainsKey( statType ) )
return OriginalStatValues[statType];
return Stats[statType];
}
void RefreshProperty( PlayerStat statType )
{
if ( !OriginalStatValues.ContainsKey( statType ) )
{
OriginalStatValues.Add( statType, Stats[statType] );
//if ( statType == PlayerStat.MaxHp )
// OriginalStatValues.Add( PlayerStat.MaxHpDisplay, Stats[statType] );
}
float curr_value = OriginalStatValues[statType];
float curr_set = curr_value;
bool should_set = false;
float curr_priority = 0f;
float total_add = 0f;
float total_mult = 1f;
foreach ( IStatModifier caller in _statModifiers.Keys )
{
var dict = _statModifiers[caller];
if ( dict.ContainsKey( statType ) )
{
var mod_data = dict[statType];
switch ( mod_data.type )
{
case ModifierType.Set:
if ( mod_data.priority >= curr_priority )
{
curr_set = mod_data.value;
curr_priority = mod_data.priority;
should_set = true;
}
break;
case ModifierType.Add:
total_add += mod_data.value;
break;
case ModifierType.Mult:
total_mult *= mod_data.value;
// Note: The downside with adding mults together is when combining stuff like Shotgun (-35% bullet dmg) then PiercingUpgrade (-55% bullet dmg).
// Adding to become -90% dmg feels wrong as it more than ~halves (-55%) your remaining dmg.
//if(mod_data.value >= 1f)
// total_mult += (mod_data.value - 1f);
//else
// total_mult -= (1f - mod_data.value);
// positive mults and negative mults could be handled differently, adding together positive ones while multiplying negative ones
// If you want adding and subtracting the same absolute number to cancel out, maybe you want something logarithmic: damage = base * MathF.Pow(2f, modifier / 100f); This modifier would start at 0 to give 1x base damage. You'd add or subtract from it when getting an upgrade. Each 100 you add would double the result, and each 100 you subtract would halve it.
break;
}
}
}
if ( should_set )
curr_value = curr_set;
//curr_value = Math.Max( curr_value + total_add, 0f );
curr_value = curr_value + total_add;
curr_value *= Math.Max( total_mult, 0f );
Stats[statType] = curr_value;
if ( statType == PlayerStat.MaxHp )
{
if ( Stats[PlayerStat.MaxHpCap] > 0f && Stats[statType] > Stats[PlayerStat.MaxHpCap] )
Stats[statType] = Stats[PlayerStat.MaxHpCap];
if ( Stats[statType] < Stats[PlayerStat.MaxHpCap] )
Stats[PlayerStat.MaxHpCap] = Stats[statType];
//Stats[PlayerStat.MaxHpDisplay] = Stats[statType];
if ( Stats[PlayerStat.MaxHp] < 1 )
Stats[statType] = 1;
if ( Health > Stats[statType] )
Health = Stats[statType];
}
if ( statType == PlayerStat.BulletDamage )
{
if ( Stats[PlayerStat.BulletDamage] < MIN_BULLET_DAMAGE )
Stats[PlayerStat.BulletDamage] = MIN_BULLET_DAMAGE;
}
if ( statType == PlayerStat.NumDashes )
{
var maxDashes = Math.Max( (int)Stats[PlayerStat.NumDashes], 0 );
if ( NumDashesAvailable > maxDashes )
NumDashesAvailable = maxDashes;
if ( maxDashes == 0 )
{
DashTimer = Stats[PlayerStat.DashCooldown];
DashRechargeProgress = 0f;
}
}
if ( statType == PlayerStat.NumTempDashes )
{
NumTempDashesAvailable = Math.Max( (int)Stats[PlayerStat.NumTempDashes], 0 );
}
//if ( statType == PlayerStat.RarityIncreaseCommon || statType == PlayerStat.RarityIncreaseUncommon || statType == PlayerStat.RarityIncreaseRare || statType == PlayerStat.RarityIncreaseEpic || statType == PlayerStat.RarityIncreaseMythic || statType == PlayerStat.RarityIncreaseLegendary|| statType == PlayerStat.RarityIncreaseUnique )
// RefreshPerkRarityChances();
if ( _syncedStats.Contains( statType ) )
_syncStats[statType] = Stats[statType];
ModifierHash++;
}
void HandleDpsStat()
{
if ( !Manager.Instance.IsGameOver )
{
while ( _dpsTimes.Count > 0 && Time.Now > _dpsTimes.Peek().time + DPS_INTERVAL )
_dpsTimes.Dequeue();
DpsStat = 0f;
foreach ( var data in _dpsTimes )
DpsStat += data.damage;
DpsStat /= DPS_INTERVAL;
}
}
//void RefreshPerkRarityChances()
//{
// var totalWeight = 0f;
// for ( int i = 1; i <= 7; i++ )
// {
// Rarity rarity = (Rarity)i;
// totalWeight += PerkManager.GetWeightForRarity( rarity, this, isCurse: false );
// }
// for ( int i = 1; i <= 7; i++ )
// {
// Rarity rarity = (Rarity)i;
// PlayerStat stat = GetPerkChanceStatForRarity( rarity );
// var value = PerkManager.GetWeightForRarity( rarity, this, isCurse: false ) / totalWeight;
// Stats[stat] = value;
// }
//}
//PlayerStat GetPerkChanceStatForRarity( Rarity rarity )
//{
// switch ( rarity )
// {
// case Rarity.Common: default: return PlayerStat.PerkChanceCommon;
// case Rarity.Uncommon: return PlayerStat.PerkChanceUncommon;
// case Rarity.Rare: return PlayerStat.PerkChanceRare;
// case Rarity.Epic: return PlayerStat.PerkChanceEpic;
// case Rarity.Mythic: return PlayerStat.PerkChanceMythic;
// case Rarity.Legendary: return PlayerStat.PerkChanceLegendary;
// case Rarity.Unique: return PlayerStat.PerkChanceUnique;
// }
//}
/// <summary>
/// Formats a stat value according to the specified display format, automatically handling original value comparison for diff formats.
/// </summary>
/// <param name="statType">The stat to format</param>
/// <param name="displayType">The format type to use</param>
/// <returns>Formatted string representation of the stat</returns>
public string GetStatStr( PlayerStat statType, StatFormat displayType = StatFormat.Int )
{
float current = Stats[statType];
switch ( displayType )
{
default:
return GetStatStr( current, displayType );
case StatFormat.IntDiff:
return GetStatStr( current, displayType, GetOriginalStatValue( statType ) );
case StatFormat.PercentageDiff:
return GetStatStr( current, displayType, GetOriginalStatValue( statType ) );
case StatFormat.PercentageAddDiffInverse:
return GetStatStr( current, displayType, GetOriginalStatValue( statType ) );
case StatFormat.PerSecond1:
return GetStatStr( current, displayType, GetOriginalStatValue( statType ) );
}
}
/// <summary>
/// Formats a numeric value according to the specified display format.
/// </summary>
/// <param name="current">The current value to format</param>
/// <param name="displayType">The format type to use</param>
/// <param name="original">The original value for comparison (used in diff formats)</param>
/// <returns>Formatted string representation of the value</returns>
public string GetStatStr( float current, StatFormat displayType = StatFormat.Int, float original = 0f )
{
switch ( displayType )
{
case StatFormat.Int:
return (MathF.Round( current )).ToString();
case StatFormat.IntDiff:
if ( current > original )
return $"+{MathF.Round( current - original )}";
else if ( current < original )
return $"-{MathF.Round( original - current )}";
else
return $"+0";
case StatFormat.Decimals1:
return current.ToString( "0.#" );
case StatFormat.Decimals1Plus:
return $"{(current < 0f ? "" : "+")}{current.ToString( "0.#" )}";
case StatFormat.Decimals2:
return current.ToString( "0.##" );
case StatFormat.Percentage:
return $"{MathF.Round( current * 100f )}%";
case StatFormat.PercentageDecimals1:
return $"{(current * 100f).ToString( "0.#" )}%";
case StatFormat.PercentageDecimals2:
return $"{(current * 100f).ToString( "0.##" )}%";
case StatFormat.PercentageInverse:
return $"{MathF.Round( (1f - current) * 100f )}%";
case StatFormat.PercentageDiff:
if ( current > original )
return $"+{MathF.Round( ((current / original) - 1f) * 100f )}%";
else if ( current < original )
return $"-{MathF.Round( (1f - (current / original)) * 100f )}%";
else
return $"+0%";
case StatFormat.PercentageAddDiff:
if ( current > original )
return $"+{MathF.Round( (current - original) * 100f )}%";
else if ( current < original )
return $"{MathF.Round( (current - original) * 100f )}%";
else
return $"+0%";
case StatFormat.PercentageAddDiffInverse:
if ( current > original )
return $"-{MathF.Round( (current - original) * 100f )}%";
else if ( current < original )
return $"+{MathF.Abs( MathF.Round( (current - original) * 100f ) )}%";
else
return $"+0%";
case StatFormat.Seconds1:
return $"{current.ToString( "0.#" )}s";
case StatFormat.Seconds2:
return $"{current.ToString( "0.##" )}s";
case StatFormat.Degrees:
return $"{MathF.Round( current )}°";
case StatFormat.PerSecond1:
if ( current > original )
return $"+{current.ToString( "0.#" )}/s";
else if ( current < original )
return $"{current.ToString( "0.#" )}/s";
else
return $"0/s";
case StatFormat.PerSecond2:
if ( current > original )
return $"+{current.ToString( "0.##" )}/s";
else if ( current < original )
return $"{current.ToString( "0.##" )}/s";
else
return $"0/s";
case StatFormat.PerDistance1:
if ( current > original )
return $"+{current.ToString( "0.#" )}/m";
else if ( current < original )
return $"{current.ToString( "0.#" )}/m";
else
return $"0/m";
case StatFormat.Distance1:
return $"{current.ToString( "0.#" )}m";
case StatFormat.Distance2:
return $"{current.ToString( "0.##" )}m";
default:
return "";
}
}
public void AddResultsStat( ResultStat stat, float value )
{
if ( Manager.Instance.IsGameOver || stat == ResultStat.None )
return;
if ( ResultStats.ContainsKey( stat ) )
{
ResultStats[stat] += value;
}
else
{
ResultStats[stat] = value;
}
}
[Rpc.Owner]
public void AddResultsStatRpc( ResultStat stat, float value )
{
AddResultsStat( stat, value );
}
public void SetResultsStat( ResultStat stat, float value )
{
if ( Manager.Instance.IsGameOver )
return;
ResultStats[stat] = value;
}
[Rpc.Owner]
public void SetResultsStatRpc( ResultStat stat, float value )
{
SetResultsStat( stat, value );
}
public ResultStat GetResultsStatType( DamageType damageType, bool dealt )
{
var resultsType = dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenOther;
if ( damageType == DamageType.Bullet ) resultsType = ( dealt ? ResultStat.DmgDealtBullet : ResultStat.DmgTakenBullet );
else if ( damageType == DamageType.Melee || damageType == DamageType.MeleeRunnerBite ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenMelee);
else if ( damageType == DamageType.Self ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenSelf);
else if ( damageType == DamageType.Fire ) resultsType = ( dealt ? ResultStat.DmgDealtFire : ResultStat.DmgTakenFire );
else if ( damageType == DamageType.Poison || damageType == DamageType.PoisonFinish ) resultsType = ( dealt ? ResultStat.DmgDealtPoison : ResultStat.DmgTakenPoison );
else if ( damageType == DamageType.Thorns ) resultsType = ( dealt ? ResultStat.DmgDealtThorns : ResultStat.DmgTakenOther );
else if ( damageType == DamageType.DashSlash ) resultsType = (dealt ? ResultStat.DmgDealtDashSlash : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.Punch ) resultsType = ( dealt ? ResultStat.DmgDealtPunch : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.Shock ) resultsType = ( dealt ? ResultStat.DmgDealtShock : ResultStat.DmgTakenShock );
else if ( damageType == DamageType.Explosion ) resultsType = ( dealt ? ResultStat.DmgDealtExplosion : ResultStat.DmgTakenExplosion );
else if ( damageType == DamageType.Boomerang ) resultsType = ( dealt ? ResultStat.DmgDealtBoomerang : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.SpitterProjectile ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenProjectile);
else if ( damageType == DamageType.SpitterProjectileHoming ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenProjectileHoming);
else if ( damageType == DamageType.SpikerHead ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenSpikerHead);
else if ( damageType == DamageType.Shockwave ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenShockwave);
else if ( damageType == DamageType.OrbitingBlade ) resultsType = (dealt ? ResultStat.DmgDealtOrbitingBlade : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.Spear ) resultsType = (dealt ? ResultStat.DmgDealtSpear : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.LavaPuddle ) resultsType = (dealt ? ResultStat.DmgDealtOther : ResultStat.DmgTakenLavaPuddle);
else if ( damageType == DamageType.XpShrapnel ) resultsType = (dealt ? ResultStat.DmgDealtXpShrapnel : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.Radiation ) resultsType = (dealt ? ResultStat.DmgDealtRadiation : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.Acid ) resultsType = (dealt ? ResultStat.DmgDealtAcid : ResultStat.DmgTakenAcid);
else if ( damageType == DamageType.BulletSplash ) resultsType = (dealt ? ResultStat.DmgDealtBulletSplash : ResultStat.DmgTakenOther);
else if ( damageType == DamageType.Mark ) resultsType = (dealt ? ResultStat.DmgDealtMark : ResultStat.DmgTakenOther);
return resultsType;
}
public float GetResultsStatAmount( ResultStat resultStat )
{
return ResultStats.ContainsKey( resultStat ) ? ResultStats[resultStat] : 0f;
}
public float GetResultsStatSum( List<ResultStat> resultStatTypes )
{
var sum = 0f;
foreach( var resultStatType in resultStatTypes )
sum += GetResultsStatAmount( resultStatType );
return sum;
}
private float _stillTimeAccumulator;
private float _bossTimeAccumulator;
private float _oneHpTimeAccumulator;
void UpdateStats()
{
if( IsDead )
return;
AddResultsStat( ResultStat.MetersMoved, TotalVelocity.Length * Utils.Unit2Meter * Time.Delta );
if ( !IsMoving )
{
_stillTimeAccumulator += Time.Delta;
int wholeSeconds = (int)_stillTimeAccumulator;
if ( wholeSeconds > 0 )
{
ProgressManager.IncrementStat( ProgressStat.SecondsStandingStill, wholeSeconds );
_stillTimeAccumulator -= wholeSeconds;
}
}
if ( Manager.Instance.HasSpawnedBoss )
{
_bossTimeAccumulator += Time.Delta;
int bossWholeSeconds = (int)_bossTimeAccumulator;
if ( bossWholeSeconds > 0 )
{
ProgressManager.IncrementStat( ProgressStat.SecondsAfterBoss, bossWholeSeconds );
_bossTimeAccumulator -= bossWholeSeconds;
}
}
if ( Health <= 1f )
{
_oneHpTimeAccumulator += Time.Delta;
int oneHpWholeSeconds = (int)_oneHpTimeAccumulator;
if ( oneHpWholeSeconds > 0 )
{
ProgressManager.IncrementStat( ProgressStat.SecondsAtOneHp, oneHpWholeSeconds );
_oneHpTimeAccumulator -= oneHpWholeSeconds;
}
}
}
public void AddEnemyDamageResultStat(EnemyType enemyType, float damage )
{
if ( enemyType == EnemyType.None )
return;
AddResultsStat( GetEnemyDamageResultStat(enemyType), damage );
}
public static ResultStat GetEnemyDamageResultStat( EnemyType enemyType )
{
if ( enemyType == EnemyType.Boss ) return ResultStat.DmgTakenFromBoss;
else if ( Manager.IsEnemyTypeMiniboss( enemyType ) ) return ResultStat.DmgTakenFromMiniboss;
else if ( enemyType == EnemyType.Zombie || enemyType == EnemyType.ZombieTemporary ) return ResultStat.DmgTakenFromZombie;
else if ( enemyType == EnemyType.ZombieElite ) return ResultStat.DmgTakenFromZombieElite;
else if ( enemyType == EnemyType.Exploder ) return ResultStat.DmgTakenFromExploder;
else if ( enemyType == EnemyType.ExploderElite ) return ResultStat.DmgTakenFromExploderElite;
else if ( enemyType == EnemyType.ExploderMini ) return ResultStat.DmgTakenFromExploderMini;
else if ( enemyType == EnemyType.Spitter ) return ResultStat.DmgTakenFromSpitter;
else if ( enemyType == EnemyType.SpitterElite ) return ResultStat.DmgTakenFromSpitterElite;
else if ( enemyType == EnemyType.Spiker ) return ResultStat.DmgTakenFromSpiker;
else if ( enemyType == EnemyType.SpikerElite ) return ResultStat.DmgTakenFromSpikerElite;
else if ( enemyType == EnemyType.Runner ) return ResultStat.DmgTakenFromRunner;
else if ( enemyType == EnemyType.RunnerElite ) return ResultStat.DmgTakenFromRunnerElite;
else if ( enemyType == EnemyType.Charger ) return ResultStat.DmgTakenFromCharger;
else if ( enemyType == EnemyType.ChargerElite ) return ResultStat.DmgTakenFromChargerElite;
else if ( enemyType == EnemyType.Sword ) return ResultStat.DmgTakenFromSword;
else if ( enemyType == EnemyType.BarrelExploding ) return ResultStat.DmgTakenFromBarrelExploding;
else if ( enemyType == EnemyType.ChestEvil ) return ResultStat.DmgTakenFromChestEvil;
return ResultStat.None;
}
public static ResultStat GetEnemyKilledByResultStat( EnemyType enemyType )
{
if ( enemyType == EnemyType.Boss ) return ResultStat.KilledByBoss;
else if ( Manager.IsEnemyTypeMiniboss( enemyType ) ) return ResultStat.KilledByMiniboss;
else if ( enemyType == EnemyType.Zombie || enemyType == EnemyType.ZombieTemporary ) return ResultStat.KilledByZombie;
else if ( enemyType == EnemyType.ZombieElite ) return ResultStat.KilledByZombieElite;
else if ( enemyType == EnemyType.Exploder ) return ResultStat.KilledByExploder;
else if ( enemyType == EnemyType.ExploderElite ) return ResultStat.KilledByExploderElite;
else if ( enemyType == EnemyType.ExploderMini ) return ResultStat.KilledByExploderMini;
else if ( enemyType == EnemyType.Spitter ) return ResultStat.KilledBySpitter;
else if ( enemyType == EnemyType.SpitterElite ) return ResultStat.KilledBySpitterElite;
else if ( enemyType == EnemyType.Spiker ) return ResultStat.KilledBySpiker;
else if ( enemyType == EnemyType.SpikerElite ) return ResultStat.KilledBySpikerElite;
else if ( enemyType == EnemyType.Runner ) return ResultStat.KilledByRunner;
else if ( enemyType == EnemyType.RunnerElite ) return ResultStat.KilledByRunnerElite;
else if ( enemyType == EnemyType.Charger ) return ResultStat.KilledByCharger;
else if ( enemyType == EnemyType.ChargerElite ) return ResultStat.KilledByChargerElite;
else if ( enemyType == EnemyType.Sword ) return ResultStat.KilledBySword;
else if ( enemyType == EnemyType.BarrelExploding ) return ResultStat.KilledByBarrelExploding;
else if ( enemyType == EnemyType.ChestEvil ) return ResultStat.KilledByChestEvil;
return ResultStat.None;
}
public static Color GetResultStatColorForEnemy( ResultStat resultStat )
{
resultStat = ConvertKilledToDamageResultStat( resultStat );
switch( resultStat )
{
case ResultStat.DmgTakenFromZombie: return new Color( 0f, 0.75f, 0f );
case ResultStat.DmgTakenFromZombieElite: return new Color( 0f, 0.5f, 0.3f );
case ResultStat.DmgTakenFromExploder: return new Color( 0.75f, 0f, 0f );
case ResultStat.DmgTakenFromExploderElite: return new Color( 0.5f, 0f, 0f );
case ResultStat.DmgTakenFromExploderMini: return new Color( 0.65f, 0f, 0.6f );
case ResultStat.DmgTakenFromSpitter: return new Color( 0.4f, 0.6f, 1f );
case ResultStat.DmgTakenFromSpitterElite: return new Color( 1f, 0f, 0.1f );
case ResultStat.DmgTakenFromSpiker: return new Color( 1f, 0f, 0.8f );
case ResultStat.DmgTakenFromSpikerElite: return new Color( 0.8f, 0f, 0.3f );
case ResultStat.DmgTakenFromCharger: return new Color( 0.85f, 0.6f, 0.3f );
case ResultStat.DmgTakenFromChargerElite: return new Color( 1f, 0.2f, 0.3f );
case ResultStat.DmgTakenFromRunner: return new Color( 0.3f, 0.3f, 0.3f );
case ResultStat.DmgTakenFromRunnerElite: return new Color( 0.3f, 0.3f, 0.3f, 0.8f );
case ResultStat.DmgTakenFromMiniboss: return new Color( 0.9f, 0.5f, 0.5f );
case ResultStat.DmgTakenFromBoss: return new Color( 0f, 0.75f, 1f );
case ResultStat.DmgTakenFromBarrelExploding: return new Color( 1f, 0.1f, 0f );
case ResultStat.DmgTakenFromChestEvil: return new Color( 0.7f, 0f, 0f );
case ResultStat.DmgTakenFromFence: return new Color( 0.6f, 0.55f, 0.4f );
case ResultStat.DmgTakenSelf: return new Color( 1f, 0f, 1f );
default: return Color.White;
}
}
public static string GetResultStatIconForEnemy( ResultStat resultStat )
{
resultStat = ConvertKilledToDamageResultStat( resultStat );
switch ( resultStat )
{
case ResultStat.DmgTakenFromZombie: return "enemy_zombie";
case ResultStat.DmgTakenFromZombieElite: return "enemy_zombie_elite";
case ResultStat.DmgTakenFromExploder: return "enemy_exploder";
case ResultStat.DmgTakenFromExploderElite: return "enemy_exploder_elite";
case ResultStat.DmgTakenFromExploderMini: return "enemy_exploder_mini_2";
case ResultStat.DmgTakenFromSpitter: return "enemy_spitter";
case ResultStat.DmgTakenFromSpitterElite: return "enemy_spitter_elite";
case ResultStat.DmgTakenFromSpiker: return "enemy_spiker";
case ResultStat.DmgTakenFromSpikerElite: return "enemy_spiker_elite";
case ResultStat.DmgTakenFromCharger: return "enemy_charger";
case ResultStat.DmgTakenFromChargerElite: return "enemy_charger_elite";
case ResultStat.DmgTakenFromRunner: return "enemy_runner";
case ResultStat.DmgTakenFromRunnerElite: return "enemy_runner_elite";
case ResultStat.DmgTakenFromMiniboss: return "kill_miniboss";
case ResultStat.DmgTakenFromBoss: return "boss";
case ResultStat.DmgTakenFromBarrelExploding: return "enemy_barrel_exploding";
case ResultStat.DmgTakenFromChestEvil: return "chest_evil";
case ResultStat.DmgTakenFromFence: return "enemy_fence";
case ResultStat.DmgTakenSelf: return "enemy_self";
default: return "blank";
}
}
public static string GetNameForEnemyResultStat( ResultStat resultStat )
{
resultStat = ConvertKilledToDamageResultStat( resultStat );
switch ( resultStat )
{
case ResultStat.DmgTakenFromZombie: return "Zombie";
case ResultStat.DmgTakenFromZombieElite: return "Elite Zombie";
case ResultStat.DmgTakenFromExploder: return "Exploder";
case ResultStat.DmgTakenFromExploderElite: return "Elite Exploder";
case ResultStat.DmgTakenFromExploderMini: return "Mini Exploder";
case ResultStat.DmgTakenFromSpitter: return "Spitter";
case ResultStat.DmgTakenFromSpitterElite: return "Elite Spitter";
case ResultStat.DmgTakenFromSpiker: return "Spiker";
case ResultStat.DmgTakenFromSpikerElite: return "Elite Spiker";
case ResultStat.DmgTakenFromCharger: return "Charger";
case ResultStat.DmgTakenFromChargerElite: return "Elite Charger";
case ResultStat.DmgTakenFromRunner: return "Werewolf";
case ResultStat.DmgTakenFromRunnerElite: return "Elite Werewolf";
case ResultStat.DmgTakenFromMiniboss: return "Miniboss";
case ResultStat.DmgTakenFromBoss: return "Boss";
case ResultStat.DmgTakenFromBarrelExploding: return "Exploding Barrel";
case ResultStat.DmgTakenFromChestEvil: return "Evil Chest";
case ResultStat.DmgTakenFromFence: return "Fence";
case ResultStat.DmgTakenSelf: return "Self";
default: return "Unknown";
}
}
public static ResultStat ConvertKilledToDamageResultStat( ResultStat resultStat )
{
switch ( resultStat )
{
case ResultStat.KilledByZombie: return ResultStat.DmgTakenFromZombie;
case ResultStat.KilledByZombieElite: return ResultStat.DmgTakenFromZombieElite;
case ResultStat.KilledByExploder: return ResultStat.DmgTakenFromExploder;
case ResultStat.KilledByExploderElite: return ResultStat.DmgTakenFromExploderElite;
case ResultStat.KilledByExploderMini: return ResultStat.DmgTakenFromExploderMini;
case ResultStat.KilledBySpitter: return ResultStat.DmgTakenFromSpitter;
case ResultStat.KilledBySpitterElite: return ResultStat.DmgTakenFromSpitterElite;
case ResultStat.KilledBySpiker: return ResultStat.DmgTakenFromSpiker;
case ResultStat.KilledBySpikerElite: return ResultStat.DmgTakenFromSpikerElite;
case ResultStat.KilledByCharger: return ResultStat.DmgTakenFromCharger;
case ResultStat.KilledByChargerElite: return ResultStat.DmgTakenFromChargerElite;
case ResultStat.KilledByRunner: return ResultStat.DmgTakenFromRunner;
case ResultStat.KilledByRunnerElite: return ResultStat.DmgTakenFromRunnerElite;
case ResultStat.KilledByMiniboss: return ResultStat.DmgTakenFromMiniboss;
case ResultStat.KilledByBoss: return ResultStat.DmgTakenFromBoss;
case ResultStat.KilledByBarrelExploding: return ResultStat.DmgTakenFromBarrelExploding;
case ResultStat.KilledByChestEvil: return ResultStat.DmgTakenFromChestEvil;
case ResultStat.KilledByFence: return ResultStat.DmgTakenFromFence;
case ResultStat.KilledBySelf: return ResultStat.DmgTakenSelf;
default: return resultStat;
}
}
}