using System; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using Creaturelib.Generated; using Pkmnlib.Generated; using PkmnLibSharp.Utilities; using Random = PkmnLibSharp.Utilities.Random; namespace PkmnLibSharp.Library { public class Forme : PointerWrapper { private ReadOnlyArray? _abilities; private ReadOnlyArray? _hiddenAbilities; private LearnableMoves? _moves; private string? _name; private ReadOnlyArray? _types; public Forme(string name, float height, float weight, uint baseExperience, byte[] types, ushort baseHealth, ushort baseAttack, ushort baseDefense, ushort baseSpecialAttack, ushort baseSpecialDefense, ushort baseSpeed, IReadOnlyCollection abilities, IReadOnlyCollection hiddenAbilities, LearnableMoves moves, IReadOnlyCollection tags) { var abilitiesConverted = abilities.Select(x => x.Ptr).ToArray(); var hiddenAbilitiesConverted = hiddenAbilities.Select(x => x.Ptr).ToArray(); var tagsConverted = tags.Select(x => x.ToPtr()).ToArray(); var ab = abilitiesConverted.ArrayPtr(); var hab = hiddenAbilitiesConverted.ArrayPtr(); var tagsPtr = tagsConverted.ArrayPtr(); var ptr = PokemonForme.Construct(name.ToPtr(), height, weight, baseExperience, types.ArrayPtr(), (ulong)types.Length, baseHealth, baseAttack, baseDefense, baseSpecialAttack, baseSpecialDefense, baseSpeed, ab, (ulong)abilities.Count, hab, (ulong)hiddenAbilities.Count, moves.Ptr, tagsPtr, (ulong)tags.Count); Initialize(ptr); } public string Name => _name ??= SpeciesVariant.GetName(Ptr).PtrString()!; public float Height => SpeciesVariant.GetHeight(Ptr); public float Weight => SpeciesVariant.GetWeight(Ptr); public float BaseExperience => SpeciesVariant.GetBaseExperience(Ptr); public ReadOnlyArray Types { get { if (_types != null) return _types; var typesCount = SpeciesVariant.GetTypeCount(Ptr); var types = new byte[typesCount]; for (ulong i = 0; i < typesCount; i++) types[i] = SpeciesVariant.GetType(Ptr, i); _types = types.ToReadOnly(); return _types; } } public uint BaseHealth => SpeciesVariant.GetStatistic(Ptr, (byte)Statistic.Health); public uint BaseAttack => SpeciesVariant.GetStatistic(Ptr, (Creaturelib.Statistic)Statistic.Attack); public uint BaseDefense => SpeciesVariant.GetStatistic(Ptr, (Creaturelib.Statistic)Statistic.Defense); public uint BaseSpecialAttack => SpeciesVariant.GetStatistic(Ptr, (Creaturelib.Statistic)Statistic.SpecialAttack); public uint BaseSpecialDefense => SpeciesVariant.GetStatistic(Ptr, (Creaturelib.Statistic)Statistic.SpecialDefense); public uint BaseSpeed => SpeciesVariant.GetStatistic(Ptr, (Creaturelib.Statistic)Statistic.Speed); public ReadOnlyArray Abilities { get { if (_abilities != null) return _abilities; var abilityCount = SpeciesVariant.GetTalentCount(Ptr); var abilities = new Ability[abilityCount]; for (byte i = 0; i < abilityCount; i++) { var s = IntPtr.Zero; SpeciesVariant.GetTalent(Ptr, MarshalHelper.False, i, ref s).Assert(); abilities[i] = Constructor.Active.ConstructAbility(s)!; } _abilities = abilities.ToReadOnly(); return _abilities; } } public ReadOnlyArray HiddenAbilities { get { if (_hiddenAbilities != null) return _hiddenAbilities; var abilityCount = SpeciesVariant.GetSecretTalentCount(Ptr); var abilities = new Ability[abilityCount]; for (byte i = 0; i < abilityCount; i++) { var s = IntPtr.Zero; SpeciesVariant.GetTalent(Ptr, MarshalHelper.True, i, ref s).Assert(); abilities[i] = Constructor.Active.ConstructAbility(s)!; } _hiddenAbilities = abilities.ToReadOnly(); return _hiddenAbilities; } } public LearnableMoves Moves { get { if (_moves != null) return _moves; var movesPtr = SpeciesVariant.GetLearnableAttacks(Ptr); if (!TryResolvePointer(movesPtr, out _moves)) _moves = Constructor.Active.ConstructLearnableMoves(movesPtr); return _moves!; } } public byte GetPkmnType(int index) { return Types[index]; } public byte GetRandomAbility(Random rand) { return SpeciesVariant.GetRandomTalent(Ptr, rand.Ptr); } public bool HasFlag(string flag) { return SpeciesVariant.HasFlag(Ptr, flag.ToPtr()) == 1; } public override string ToString() { return base.ToString() + $": {Name}"; } protected internal override void MarkAsDeleted() { base.MarkAsDeleted(); _moves?.MarkAsDeleted(); } protected override void DeletePtr() { SpeciesVariant.Destruct(Ptr); } } }