using System; using System.Collections.Immutable; using System.Linq; using System.Runtime.InteropServices; using Creatureliblibrary.Generated; using PkmnLibSharp.Utilities; using Random = PkmnLibSharp.Utilities.Random; namespace PkmnLibSharp.Library { public class Forme : PointerWrapper { private ImmutableArray _abilities; private ImmutableArray _hiddenAbilities; private LearnableMoves _moves; private string _name; private ImmutableArray _types; internal Forme(IntPtr parent) : base(parent) { } 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 ImmutableArray 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.ToImmutableArray(); return _types; } } public uint BaseHealth => SpeciesVariant.GetStatistic(Ptr, (byte) Statistic.Health); public uint BaseAttack => SpeciesVariant.GetStatistic(Ptr, (Creatureliblibrary.Statistic) Statistic.Attack); public uint BaseDefense => SpeciesVariant.GetStatistic(Ptr, (Creatureliblibrary.Statistic) Statistic.Defense); public uint BaseSpecialAttack => SpeciesVariant.GetStatistic(Ptr, (Creatureliblibrary.Statistic) Statistic.SpecialAttack); public uint BaseSpecialDefense => SpeciesVariant.GetStatistic(Ptr, (Creatureliblibrary.Statistic) Statistic.SpecialDefense); public uint BaseSpeed => SpeciesVariant.GetStatistic(Ptr, (Creatureliblibrary.Statistic) Statistic.Speed); public ImmutableArray Abilities { get { if (_abilities != null) return _abilities; var abilityCount = SpeciesVariant.GetTalentCount(Ptr); var abilities = new string[abilityCount]; for (byte i = 0; i < abilityCount; i++) { var s = IntPtr.Zero; SpeciesVariant.GetTalent(Ptr, MarshalHelper.False, i, ref s).Assert(); abilities[i] = s.PtrString(); } _abilities = abilities.ToImmutableArray(); return _abilities; } } public ImmutableArray HiddenAbilities { get { if (_hiddenAbilities != null) return _hiddenAbilities; var abilityCount = SpeciesVariant.GetSecretTalentCount(Ptr); var abilities = new string[abilityCount]; for (byte i = 0; i < abilityCount; i++) { var s = IntPtr.Zero; SpeciesVariant.GetTalent(Ptr, MarshalHelper.True, i, ref s).Assert(); abilities[i] = s.PtrString(); } _hiddenAbilities = abilities.ToImmutableArray(); return _hiddenAbilities; } } public LearnableMoves Moves { get { if (_moves != null) return _moves; var movesPtr = SpeciesVariant.GetLearnableAttacks(Ptr); if (!TryResolvePointer(movesPtr, out _moves)) _moves = new LearnableMoves(movesPtr); return _moves; } } public int GetPkmnType(int index) { return Types[index]; } public static Forme Create(string name, float height, float weight, uint baseExperience, byte[] types, ushort baseHealth, ushort baseAttack, ushort baseDefense, ushort baseSpecialAttack, ushort baseSpecialDefense, ushort baseSpeed, string[] abilities, string[] hiddenAbilities, LearnableMoves moves) { var abilitiesConverted = abilities.Select(x => x.ToPtr()).ToArray(); var hiddenAbilitiesConverted = hiddenAbilities.Select(x => x.ToPtr()).ToArray(); var ab = abilitiesConverted.ArrayPtr(); var hab = abilitiesConverted.ArrayPtr(); var ptr = SpeciesVariant.Construct(name.ToPtr(), height, weight, baseExperience, types.ArrayPtr(), (ulong) types.Length, baseHealth, baseAttack, baseDefense, baseSpecialAttack, baseSpecialDefense, baseSpeed, (IntPtr) ab, (ulong) abilities.Length, (IntPtr) hab, (ulong) hiddenAbilities.Length, moves.Ptr); var f = new Forme(ptr); foreach (var intPtr in abilitiesConverted) Marshal.FreeHGlobal(intPtr); foreach (var intPtr in hiddenAbilitiesConverted) Marshal.FreeHGlobal(intPtr); return f; } public byte GetRandomAbility(Random rand) { return SpeciesVariant.GetRandomTalent(Ptr, rand.Ptr); } protected internal override void MarkAsDeleted() { base.MarkAsDeleted(); _moves?.MarkAsDeleted(); } protected override void DeletePtr() { SpeciesVariant.Destruct(Ptr); } } }