using System; using System.Collections.Generic; using PkmnLibSharp.DynamicData.Libraries; using PkmnLibSharp.StaticData; using PkmnLibSharp.Utils; namespace PkmnLibSharp.DynamicData { public class PokemonBuilder { private static readonly Random DefaultRandom = new(); private readonly Random _random; private readonly int _randomSeed; private readonly DynamicLibrary _library; private readonly string _species; private string _form = "default"; private readonly LevelInt _level; private bool? _forceShininess; private Gender? _gender; private uint? _identifier; private string? _natureName; private string? _ability; private uint? _experience; private readonly List<(string name, MoveLearnMethod method)> _moves = new(); private bool _hiddenAbility; private byte _abilityIndex; private byte _coloring; public PokemonBuilder(DynamicLibrary library, string species, LevelInt level) { _library = library; _species = species; _level = level; _randomSeed = DefaultRandom.Next(); _random = new Random(_randomSeed); } public PokemonBuilder WithForm(string form) { _form = form; return this; } public PokemonBuilder ForceShiny(bool value) { _forceShininess = value; return this; } public PokemonBuilder WithGender(Gender gender) { _gender = gender; return this; } public PokemonBuilder WithIdentifier(uint identifier) { _identifier = identifier; return this; } public PokemonBuilder WithNature(string nature) { _natureName = nature; return this; } public PokemonBuilder WithAbility(string ability) { _ability = ability; return this; } public PokemonBuilder WithExperience(uint experience) { _experience = experience; return this; } public PokemonBuilder LearnMove(string moveName, MoveLearnMethod learnMethod) { _moves.Add((moveName, learnMethod)); return this; } protected virtual Pokemon Finalize(Species species, Form form, Item? heldItem) { var pokemon = new Pokemon(_library, species, form, _hiddenAbility, _abilityIndex, _level, _identifier ?? (uint)_random.Next(), _gender!.Value, _coloring, _natureName!); if (heldItem != null) pokemon.SetHeldItem(heldItem); foreach (var move in _moves) { pokemon.LearnMove(move.name, move.method); } return pokemon; } protected virtual void PopulateUninitialized(Species species, Form form, Random random) { _experience ??= _library.StaticData.GrowthRateLibrary.CalculateExperience(species.GrowthRate, _level); _identifier ??= (uint)random.Next(); _gender ??= species.GetRandomGender((ulong)_randomSeed); if (_forceShininess.HasValue) { _coloring = _forceShininess.Value ? (byte)1 : (byte)0; } else if (random.Next((int)_library.StaticData.LibrarySettings.ShinyRate) == 0) { _coloring = 1; } if (string.IsNullOrEmpty(_ability)) { _hiddenAbility = false; _abilityIndex = (byte)_random.Next(0, form.Abilities.Count); } else { (_hiddenAbility, _abilityIndex) = GetAbilityIndex(species, form, _ability!); } if (string.IsNullOrEmpty(_natureName)) { using var nature = _library.StaticData.NatureLibrary.GetRandomNature((ulong)_randomSeed); _natureName = _library.StaticData.NatureLibrary.GetNatureName(nature); } } private static (bool, byte) GetAbilityIndex(Species species, Form form, string ability) { var i = form.Abilities.IndexOf(ability); if (i != -1) return (false, (byte)i); i = form.HiddenAbilities.IndexOf(ability); if (i == -1) { throw new Exception( $"Invalid ability '{ability}' for Pokemon '{species.Name}' and forme '{form.Name}'."); } return (true, (byte)i); } public Pokemon Build() { if (!_library.StaticData.SpeciesLibrary.TryGetValue(_species, out var species)) { throw new Exception($"Species '{_species}' was not found."); } if (!species.TryGetForm(_form, out var form)) { throw new Exception($"Forme '{_form}' was not found on species '{_species}'"); } PopulateUninitialized(species, form, _random); return Finalize(species, form, null); } } }