PkmnLib.NET/PkmnLib.Static/Species/Form.cs

205 lines
5.8 KiB
C#
Raw Normal View History

2024-07-20 11:51:52 +00:00
using System.Collections.Immutable;
using PkmnLib.Static.Utils;
using PkmnLib.Static.Utils.Errors;
namespace PkmnLib.Static.Species;
/// <summary>
/// A form is a variant of a specific species. A species always has at least one form, but can have
/// many more.
/// </summary>
2024-07-20 14:12:39 +00:00
public interface IForm : INamedValue
2024-07-20 11:51:52 +00:00
{
/// <summary>
/// The height of the form in meters.
/// </summary>
float Height { get; }
/// <summary>
/// The weight of the form in kilograms.
/// </summary>
float Weight { get; }
/// <summary>
2024-07-20 14:12:39 +00:00
/// The base amount of experience that is gained when beating a Pokémon with this form.
2024-07-20 11:51:52 +00:00
/// </summary>
uint BaseExperience { get; }
/// <summary>
2024-07-20 14:12:39 +00:00
/// The normal types a Pokémon with this form has.
2024-07-20 11:51:52 +00:00
/// </summary>
IReadOnlyList<TypeIdentifier> Types { get; }
/// <summary>
2024-07-20 14:12:39 +00:00
/// The inherent values of a form of species that are used for the stats of a Pokémon.
2024-07-20 11:51:52 +00:00
/// </summary>
2024-07-20 14:12:39 +00:00
ImmutableStatisticSet<ushort> BaseStats { get; }
2024-07-20 11:51:52 +00:00
/// <summary>
2024-07-20 14:12:39 +00:00
/// The possible abilities a Pokémon with this form can have.
2024-07-20 11:51:52 +00:00
/// </summary>
IReadOnlyList<StringKey> Abilities { get; }
/// <summary>
2024-07-20 14:12:39 +00:00
/// The possible hidden abilities a Pokémon with this form can have.
2024-07-20 11:51:52 +00:00
/// </summary>
IReadOnlyList<StringKey> HiddenAbilities { get; }
/// <summary>
2024-07-20 14:12:39 +00:00
/// The moves a Pokémon with this form can learn.
2024-07-20 11:51:52 +00:00
/// </summary>
ILearnableMoves Moves { get; }
/// <summary>
/// Arbitrary flags can be set on a form for scripting use.
/// </summary>
ImmutableHashSet<StringKey> Flags { get; }
/// <summary>
/// Get a type of the form at a certain index.
/// </summary>
2024-07-28 10:52:17 +00:00
TypeIdentifier GetType(int index);
2024-07-20 11:51:52 +00:00
/// <summary>
/// Gets a single base stat value.
/// </summary>
ushort GetBaseStat(Statistic stat);
/// <summary>
/// Find the index of an ability that can be on this form.
/// </summary>
AbilityIndex? FindAbilityIndex(IAbility ability);
/// <summary>
/// Gets an ability from the form.
/// </summary>
2024-07-28 10:52:17 +00:00
StringKey GetAbility(AbilityIndex index);
2024-07-20 11:51:52 +00:00
/// <summary>
/// Gets a random ability from the form.
/// </summary>
StringKey GetRandomAbility(IRandom rand);
/// <summary>
/// Gets a random hidden ability from the form.
/// </summary>
StringKey GetRandomHiddenAbility(IRandom rand);
/// <summary>
/// Check if the form has a specific flag set.
/// </summary>
bool HasFlag(string key);
}
/// <inheritdoc />
public class FormImpl : IForm
{
/// <inheritdoc cref="FormImpl" />
2025-03-02 16:19:57 +00:00
public FormImpl(StringKey name, float height, float weight, uint baseExperience, IEnumerable<TypeIdentifier> types,
ImmutableStatisticSet<ushort> baseStats, IEnumerable<StringKey> abilities,
2024-07-20 11:51:52 +00:00
IEnumerable<StringKey> hiddenAbilities, ILearnableMoves moves, ImmutableHashSet<StringKey> flags)
{
Name = name;
Height = height;
Weight = weight;
BaseExperience = baseExperience;
Types = [..types];
BaseStats = baseStats;
Abilities = [..abilities];
HiddenAbilities = [..hiddenAbilities];
Moves = moves;
Flags = flags;
2025-03-02 16:19:57 +00:00
2024-07-20 11:51:52 +00:00
if (Types.Count == 0)
throw new ArgumentException("A form must have at least one type.");
if (Abilities.Count == 0)
throw new ArgumentException("A form must have at least one ability.");
}
/// <inheritdoc />
public StringKey Name { get; }
/// <inheritdoc />
public float Height { get; }
/// <inheritdoc />
public float Weight { get; }
/// <inheritdoc />
public uint BaseExperience { get; }
/// <inheritdoc />
public IReadOnlyList<TypeIdentifier> Types { get; }
/// <inheritdoc />
2024-07-20 14:12:39 +00:00
public ImmutableStatisticSet<ushort> BaseStats { get; }
2024-07-20 11:51:52 +00:00
/// <inheritdoc />
public IReadOnlyList<StringKey> Abilities { get; }
/// <inheritdoc />
public IReadOnlyList<StringKey> HiddenAbilities { get; }
/// <inheritdoc />
public ILearnableMoves Moves { get; }
/// <inheritdoc />
public ImmutableHashSet<StringKey> Flags { get; }
/// <inheritdoc />
2024-07-28 10:52:17 +00:00
public TypeIdentifier GetType(int index)
2024-07-20 11:51:52 +00:00
{
if (index < 0 || index >= Types.Count)
2024-07-28 10:52:17 +00:00
throw new OutOfRangeException("Type", index, Types.Count);
2024-07-20 11:51:52 +00:00
return Types[index];
}
/// <inheritdoc />
public ushort GetBaseStat(Statistic stat) => BaseStats.GetStatistic(stat);
/// <inheritdoc />
public AbilityIndex? FindAbilityIndex(IAbility ability)
{
for (var i = 0; i < Abilities.Count && i < 255; i++)
{
if (Abilities[i] == ability.Name)
2025-03-02 16:19:57 +00:00
{
2024-07-20 11:51:52 +00:00
return new AbilityIndex
{
IsHidden = false,
2024-08-23 07:24:00 +00:00
Index = (byte)i,
2024-07-20 11:51:52 +00:00
};
2025-03-02 16:19:57 +00:00
}
2024-07-20 11:51:52 +00:00
}
for (var i = 0; i < HiddenAbilities.Count && i < 255; i++)
{
if (HiddenAbilities[i] == ability.Name)
2025-03-02 16:19:57 +00:00
{
2024-07-20 11:51:52 +00:00
return new AbilityIndex
{
IsHidden = true,
2024-08-23 07:24:00 +00:00
Index = (byte)i,
2024-07-20 11:51:52 +00:00
};
2025-03-02 16:19:57 +00:00
}
2024-07-20 11:51:52 +00:00
}
return null;
}
/// <inheritdoc />
2024-07-28 10:52:17 +00:00
public StringKey GetAbility(AbilityIndex index)
2024-07-20 11:51:52 +00:00
{
var array = index.IsHidden ? HiddenAbilities : Abilities;
if (index.Index >= array.Count)
2024-07-28 10:52:17 +00:00
throw new OutOfRangeException("Ability", index.Index, array.Count);
2024-07-20 11:51:52 +00:00
return array[index.Index];
}
/// <inheritdoc />
2025-03-02 16:19:57 +00:00
public StringKey GetRandomAbility(IRandom rand) => Abilities[rand.GetInt(Abilities.Count)];
2024-07-20 11:51:52 +00:00
/// <inheritdoc />
2025-03-02 16:19:57 +00:00
public StringKey GetRandomHiddenAbility(IRandom rand) => HiddenAbilities[rand.GetInt(HiddenAbilities.Count)];
2024-07-20 11:51:52 +00:00
/// <inheritdoc />
2025-03-02 16:19:57 +00:00
public bool HasFlag(string key) => Flags.Contains(key);
2024-07-20 11:51:52 +00:00
}