Sboku/Arena/UpgradeHolder.cs
using System;
using System.Collections.Generic;
namespace Sandbox.Sboku.Arena;
[Group("Sboku Arena")]
public class UpgradeHolder : Component
{
#region Leveling
public const int LevelCap = 5;
[Property]
public int FreePoints { get; set; } = 1;
public Powerup Speed { get; private set; }
public Powerup Damage { get; private set; }
public Powerup Armor { get; private set; }
public UpgradeHolder()
{
Clear();
}
public class Powerup
{
private int level;
public int Level { get => level; set => Set(ref level, value); }
public string Display { get; }
private UpgradeHolder holder;
public Powerup(UpgradeHolder holder, string display)
{
this.holder = holder;
Display = display;
}
private void Set(ref int field, int value)
=> holder.Set(ref field, value);
public void Inc()
=> Level++;
public void Dec()
=> Level--;
}
private void Set(ref int field, int value)
{
var dif = value - field;
if (Math.Abs(dif) != 1)
{
throw new ArgumentException("Level must be only incremented or decremented");
}
if (dif > 0)
{
if (field < LevelCap && FreePoints > 0)
{
FreePoints--;
field++;
}
}
else
{
if (field > 0)
{
FreePoints++;
field--;
}
}
}
public void DistributeRandomly()
{
var points = FreePoints;
var indexes = new List<int> { 0, 1, 2 };
while (points > 0)
{
var selected = indexes[Game.Random.Next(indexes.Count)];
switch (selected)
{
case 0:
points--;
Speed.Inc();
if (Speed.Level >= LevelCap)
indexes.Remove(selected);
break;
case 1:
points--;
Damage.Inc();
if (Damage.Level >= LevelCap)
indexes.Remove(selected);
break;
case 2:
points--;
Armor.Inc();
if (Armor.Level >= LevelCap)
indexes.Remove(selected);
break;
}
}
}
public void Clear()
{
FreePoints = 1;
Speed = new(this, "Speed");
Damage = new(this, "Damage");
Armor = new(this, "Armor");
}
#endregion
#region Powerups
public enum Level { A, B, C, D, E, F }
public Level SpeedClass { get => IntToLevel(Speed.Level); }
public Level DamageClass { get => IntToLevel(Damage.Level); }
public Level ArmorClass { get => IntToLevel(Armor.Level); }
private Level IntToLevel(int level) => level switch
{
0 => Level.F,
1 => Level.E,
2 => Level.D,
3 => Level.C,
4 => Level.B,
5 => Level.A,
_ => throw new NotImplementedException("No level for " + level + " number")
};
public float SpeedMultiplier { get => SpeedClass switch
{
Level.A => 2f,
Level.B => 1.6f,
Level.C => 1.3f,
Level.D => 1.0f,
Level.E => 0.75f,
Level.F => 0.5f,
_ => throw new NotImplementedException("No multiplier for " + SpeedClass),
};
}
public float DamageMultiplier { get => DamageClass switch
{
Level.A => 4f,
Level.B => 3f,
Level.C => 2f,
Level.D => 1.3f,
Level.E => 1.1f,
Level.F => 1f,
_ => throw new NotImplementedException("No multiplier for " + DamageClass),
};
}
public float ArmorMultiplier { get => ArmorClass switch
{
Level.A => 0.2f,
Level.B => 0.35f,
Level.C => 0.5f,
Level.D => 0.6f,
Level.E => 0.8f,
Level.F => 1f,
_ => throw new System.NotImplementedException("No multiplier for " + ArmorClass),
};
}
#endregion
}