PkmnLib.NET/PkmnLib.Static/StatisticSet.cs

302 lines
9.2 KiB
C#
Raw Normal View History

2024-07-27 14:26:45 +00:00
using System.Diagnostics.CodeAnalysis;
2024-07-20 11:51:52 +00:00
namespace PkmnLib.Static;
2024-07-20 14:12:39 +00:00
/// <summary>
/// A set of statistics that cannot be changed.
/// </summary>
/// <typeparam name="T">The size of the integer to be used</typeparam>
public record ImmutableStatisticSet<T>
2024-07-20 11:51:52 +00:00
where T : struct
{
/// <summary>
/// The health points stat value.
/// </summary>
public T Hp { get; protected set; }
/// <summary>
/// The physical attack stat value.
/// </summary>
public T Attack { get; protected set; }
/// <summary>
/// The physical defense stat value.
/// </summary>
public T Defense { get; protected set; }
/// <summary>
/// The special attack stat value.
/// </summary>
public T SpecialAttack { get; protected set; }
/// <summary>
/// The special defense stat value.
/// </summary>
public T SpecialDefense { get; protected set; }
/// <summary>
/// The speed stat value.
/// </summary>
public T Speed { get; protected set; }
2024-07-20 14:12:39 +00:00
/// <inheritdoc cref="ImmutableStatisticSet{T}"/>
public ImmutableStatisticSet(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed)
2024-07-20 11:51:52 +00:00
{
Hp = hp;
Attack = attack;
Defense = defense;
SpecialAttack = specialAttack;
SpecialDefense = specialDefense;
Speed = speed;
}
2024-07-20 14:12:39 +00:00
/// <summary>
/// Gets a statistic from the set.
/// </summary>
2024-07-20 11:51:52 +00:00
public T GetStatistic(Statistic stat)
{
return stat switch
{
Statistic.Hp => Hp,
Statistic.Attack => Attack,
Statistic.Defense => Defense,
Statistic.SpecialAttack => SpecialAttack,
Statistic.SpecialDefense => SpecialDefense,
Statistic.Speed => Speed,
_ => throw new ArgumentException("Invalid statistic.")
};
}
}
2024-07-20 14:12:39 +00:00
/// <summary>
/// A set of statistics that can be changed.
/// </summary>
/// <typeparam name="T"></typeparam>
public record StatisticSet<T> : ImmutableStatisticSet<T>
2024-07-20 11:51:52 +00:00
where T : struct
{
2024-07-20 14:12:39 +00:00
/// <inheritdoc cref="StatisticSet{T}"/>
2024-07-20 11:51:52 +00:00
public StatisticSet(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed) : base(hp, attack,
defense, specialAttack, specialDefense, speed)
{
}
2024-07-27 14:26:45 +00:00
protected T Add(T a, T b) => (T)Convert.ChangeType(Convert.ToInt32(a) + Convert.ToInt32(b), typeof(T));
protected T Subtract(T a, T b) => (T)Convert.ChangeType(Convert.ToInt32(a) - Convert.ToInt32(b), typeof(T));
2024-07-20 14:12:39 +00:00
/// <summary>
/// Modifies a statistic in the set.
/// </summary>
2024-07-27 14:26:45 +00:00
public virtual void SetStatistic(Statistic stat, T value)
2024-07-20 11:51:52 +00:00
{
switch (stat)
{
case Statistic.Hp:
Hp = value;
break;
case Statistic.Attack:
Attack = value;
break;
case Statistic.Defense:
Defense = value;
break;
case Statistic.SpecialAttack:
SpecialAttack = value;
break;
case Statistic.SpecialDefense:
SpecialDefense = value;
break;
case Statistic.Speed:
Speed = value;
break;
default:
throw new ArgumentException("Invalid statistic.");
}
}
2024-07-20 14:12:39 +00:00
/// <summary>
/// Increases a statistic in the set by a value.
/// </summary>
2024-07-27 14:26:45 +00:00
public virtual bool IncreaseStatistic(Statistic stat, T value)
2024-07-20 11:51:52 +00:00
{
switch (stat)
{
case Statistic.Hp:
2024-07-27 14:26:45 +00:00
Hp = Add(Hp, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.Attack:
2024-07-27 14:26:45 +00:00
Attack = Add(Attack, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.Defense:
2024-07-27 14:26:45 +00:00
Defense = Add(Defense, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.SpecialAttack:
2024-07-27 14:26:45 +00:00
SpecialAttack = Add(SpecialAttack, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.SpecialDefense:
2024-07-27 14:26:45 +00:00
SpecialDefense = Add(SpecialDefense, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.Speed:
2024-07-27 14:26:45 +00:00
Speed = Add(Speed, value);
2024-07-20 11:51:52 +00:00
break;
default:
throw new ArgumentException("Invalid statistic.");
}
2024-07-27 14:26:45 +00:00
return true;
2024-07-20 11:51:52 +00:00
}
2024-07-20 14:12:39 +00:00
/// <summary>
/// Decreases a statistic in the set by a value.
/// </summary>
2024-07-27 14:26:45 +00:00
public virtual bool DecreaseStatistic(Statistic stat, T value)
2024-07-20 11:51:52 +00:00
{
switch (stat)
{
case Statistic.Hp:
2024-07-27 14:26:45 +00:00
Hp = Subtract(Hp, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.Attack:
2024-07-27 14:26:45 +00:00
Attack = Subtract(Attack, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.Defense:
2024-07-27 14:26:45 +00:00
Defense = Subtract(Defense, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.SpecialAttack:
2024-07-27 14:26:45 +00:00
SpecialAttack = Subtract(SpecialAttack, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.SpecialDefense:
2024-07-27 14:26:45 +00:00
SpecialDefense = Subtract(SpecialDefense, value);
2024-07-20 11:51:52 +00:00
break;
case Statistic.Speed:
2024-07-27 14:26:45 +00:00
Speed = Subtract(Speed, value);
2024-07-20 11:51:52 +00:00
break;
default:
throw new ArgumentException("Invalid statistic.");
}
2024-07-27 14:26:45 +00:00
return true;
}
}
/// <summary>
/// A set of statistics that can be changed, but are clamped to a minimum and maximum value.
/// </summary>
public abstract record ClampedStatisticSet<T> : StatisticSet<T>
where T : struct, IComparable<T>
{
/// <inheritdoc />
[SuppressMessage("ReSharper", "VirtualMemberCallInConstructor")]
protected ClampedStatisticSet(T hp, T attack, T defense, T specialAttack, T specialDefense, T speed) : base(hp,
attack, defense, specialAttack, specialDefense, speed)
{
if (Min.CompareTo(Max) > 0)
throw new ArgumentException("Minimum value must be less than or equal to maximum value.");
Hp = Clamp(Hp, Min, Max);
Attack = Clamp(Attack, Min, Max);
Defense = Clamp(Defense, Min, Max);
SpecialAttack = Clamp(SpecialAttack, Min, Max);
SpecialDefense = Clamp(SpecialDefense, Min, Max);
Speed = Clamp(Speed, Min, Max);
}
private static T Clamp(T value, T min, T max)
{
if (value.CompareTo(min) < 0)
return min;
if (value.CompareTo(max) > 0)
return max;
return value;
}
/// <summary>
/// The minimum value for the statistics.
/// </summary>
protected abstract T Min { get; }
/// <summary>
/// The maximum value for the statistics.
/// </summary>
protected abstract T Max { get; }
/// <inheritdoc />
public override void SetStatistic(Statistic stat, T value) => base.SetStatistic(stat, Clamp(value, Min, Max));
/// <inheritdoc />
public override bool IncreaseStatistic(Statistic stat, T value)
{
var current = GetStatistic(stat);
var newValue = Add(current, value);
if (newValue.CompareTo(Max) > 0)
value = Subtract(Max, current);
if (value.CompareTo(default) == 0)
return false;
return base.IncreaseStatistic(stat, value);
}
/// <inheritdoc />
public override bool DecreaseStatistic(Statistic stat, T value)
{
var current = GetStatistic(stat);
var newValue = Subtract(current, value);
if (newValue.CompareTo(Min) < 0)
value = Subtract(current, Min);
if (value.CompareTo(default) == 0)
return false;
return base.DecreaseStatistic(stat, value);
}
}
/// <summary>
/// A set of statistics that can be changed, but are clamped to a minimum and maximum value of -6 and 6.
/// </summary>
public record StatBoostStatisticSet : ClampedStatisticSet<sbyte>
{
/// <inheritdoc />
protected override sbyte Min => -6;
/// <inheritdoc />
protected override sbyte Max => 6;
/// <inheritdoc cref="StatBoostStatisticSet"/>
public StatBoostStatisticSet(sbyte hp, sbyte attack, sbyte defense, sbyte specialAttack, sbyte specialDefense,
sbyte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
{
}
}
/// <summary>
/// A set of statistics that can be changed, but are clamped to a minimum and maximum value of 0 and 31.
/// </summary>
public record IndividualValueStatisticSet : ClampedStatisticSet<byte>
{
/// <inheritdoc />
protected override byte Min => 0;
/// <inheritdoc />
protected override byte Max => 31;
/// <inheritdoc cref="IndividualValueStatisticSet"/>
public IndividualValueStatisticSet(byte hp, byte attack, byte defense, byte specialAttack, byte specialDefense,
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
{
}
}
/// <summary>
/// A set of statistics that can be changed, but are clamped to a minimum and maximum value of 0 and 252.
/// </summary>
public record EffortValueStatisticSet : ClampedStatisticSet<byte>
{
/// <inheritdoc />
protected override byte Min => 0;
/// <inheritdoc />
protected override byte Max => 252;
/// <inheritdoc cref="EffortValueStatisticSet"/>
public EffortValueStatisticSet(byte hp, byte attack, byte defense, byte specialAttack, byte specialDefense,
byte speed) : base(hp, attack, defense, specialAttack, specialDefense, speed)
{
2024-07-20 11:51:52 +00:00
}
}