using System; using System.Collections.Generic; using System.Linq; using Creaturelib.Generated; using Pkmnlib.Generated; using PkmnLibSharp.Utilities; using EvolutionData = PkmnLibSharp.Library.Evolution.EvolutionData; using Random = PkmnLibSharp.Utilities.Random; namespace PkmnLibSharp.Library { public class Species : PointerWrapper { public Species(ushort id, string name, Forme defaultForme, float genderRatio, string growthRate, byte captureRate, byte baseHappiness, IReadOnlyCollection eggGroups, IReadOnlyCollection tags) { var ptr = IntPtr.Zero; var tagsConverted = tags.Select(x => x.ToPtr()).ToArray(); var eggGroupsConverted = eggGroups.Select(x => x.ToPtr()).ToArray(); var eggGroupsPtr = eggGroupsConverted.ArrayPtr(); var tagsPtr = tagsConverted.ArrayPtr(); PokemonSpecies.Construct(ref ptr, id, name.ToPtr(), defaultForme.Ptr, genderRatio, growthRate.ToPtr(), captureRate, baseHappiness, eggGroupsPtr, (ulong) eggGroups.Count, tagsPtr, (ulong) tags.Count).Assert(); _formeCache.Add("default", defaultForme); Initialize(ptr); } public ushort Id => CreatureSpecies.GetId(Ptr); public float GenderRate => CreatureSpecies.GetGenderRate(Ptr); public byte CaptureRate => CreatureSpecies.GetCaptureRate(Ptr); public string Name => _name ??= CreatureSpecies.GetName(Ptr).PtrString()!; public string GrowthRate => _growthRate ??= CreatureSpecies.GetGrowthRate(Ptr).PtrString()!; public string[] EggGroups { get { if (_eggGroups != null) return _eggGroups; var count = Pkmnlib.Generated.PokemonSpecies.GetEggGroupCount(Ptr); _eggGroups = new string[count]; for (ulong i = 0; i < count; i++) { _eggGroups[i] = PokemonSpecies.GetEggGroup(Ptr, i).PtrString()!; } return _eggGroups; } } public ReadOnlyNativePtrArray Formes { get { if (_formes != null) return _formes; var startPtr = CreatureSpecies.GetVariants(Ptr); var size = CreatureSpecies.GetVariantsCount(Ptr); _formes = new ReadOnlyNativePtrArray(startPtr, (int) size, Constructor.GenericType.Forme); return _formes; } } public ReadOnlyNativePtrArray Evolutions { get { if (_evolutions != null) return _evolutions; var ptr = IntPtr.Zero; PokemonSpecies.GetEvolutions(Ptr, ref ptr); var length = PokemonSpecies.GetEvolutionCount(Ptr); _evolutions = new ReadOnlyNativePtrArray(ptr, (int) length, Constructor.GenericType.EvolutionData); return _evolutions; } } public bool HasForme(string s) { return CreatureSpecies.HasVariant(Ptr, s.ToPtr()) == MarshalHelper.True; } public bool TryGetForme(string s, out Forme? forme) { if (_formeCache.TryGetValue(s, out forme)) return true; var ptr = IntPtr.Zero; if (CreatureSpecies.TryGetVariant(Ptr, s.ToPtr(), ref ptr) == MarshalHelper.True) { if (TryResolvePointer(ptr, out forme)) { _formeCache.Add(s, forme!); return true; } forme = Constructor.Active.ConstructForme(ptr)!; _formeCache.Add(s, forme); return true; } return false; } public Forme GetForme(string s) { if (_formeCache.TryGetValue(s, out var forme)) return forme; var ptr = IntPtr.Zero; CreatureSpecies.GetVariant(ref ptr, Ptr, s.ToPtr()).Assert(); if (TryResolvePointer(ptr, out Forme? f)) { _formeCache.Add(s, f!); return f!; } forme = Constructor.Active.ConstructForme(ptr)!; _formeCache.Add(s, forme); return forme; } public void SetForme(string s, Forme forme) { _formeCache.Add(s, forme); CreatureSpecies.SetVariant(Ptr, s.ToPtr(), forme.Ptr).Assert(); } public Gender GetRandomGender(Random random) { return (Gender) CreatureSpecies.GetRandomGender(Ptr, random.Ptr); } public void AddEvolution(EvolutionData evolutionData) { Pkmnlib.Generated.PokemonSpecies.AddEvolution(Ptr, evolutionData.Ptr); } public bool HasFlag(string flag) { return CreatureSpecies.HasFlag(Ptr, flag.ToPtr()) == 1; } private string? _name; private string? _growthRate; private readonly Dictionary _formeCache = new Dictionary(StringComparer.InvariantCultureIgnoreCase); private ReadOnlyNativePtrArray? _evolutions; private ReadOnlyNativePtrArray? _formes; private string[]? _eggGroups; public override string ToString() { return $"(#{Ptr}) -> Species: {Name}"; } protected internal override void MarkAsDeleted() { base.MarkAsDeleted(); foreach (var forme in _formeCache) { forme.Value.MarkAsDeleted(); } } protected override void DeletePtr() { PokemonSpecies.Destruct(Ptr); } } }