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