using System; using System.Collections.Generic; using PkmnLibSharp.Library; using PkmnLibSharp.Library.Items; using PkmnLibSharp.Library.Moves; using Random = PkmnLibSharp.Utilities.Random; namespace PkmnLibSharp.Battling { public abstract class BasePokemonBuilder where TPokemon : Pokemon where TLearnedMove :LearnedMove { private static readonly Random _defaultRandom = new Random(); protected readonly BattleLibrary Library; public string Species { get; } public string Forme { get; private set; } = "default"; public string Nickname { get; private set; } = ""; public string Ability { get; private set; } = ""; public string Nature { get; private set; } = ""; public Gender Gender { get; private set; } = (Gender) (-1); public uint Identifier { get; private set; } = 0; public byte Level { get; } public StatisticSet IVs; public StatisticSet EVs; public bool? IsForceShiny { get; private set; } public string? HeldItem { get; private set; } public List<(string moveName, MoveLearnMethod learnMethod)> LearnedMoves { get; } = new List<(string moveName, MoveLearnMethod learnMethod)>(); public BasePokemonBuilder(BattleLibrary library, string species, byte level) { Library = library; Species = species; Level = level; } public BasePokemonBuilder WithForme(string forme) { Forme = forme; return this; } public BasePokemonBuilder WithGender(Gender gender) { Gender = gender; return this; } public BasePokemonBuilder ForceShiny(bool value) { IsForceShiny = value; return this; } public BasePokemonBuilder WithHeldItem(string heldItem) { HeldItem = heldItem; return this; } public BasePokemonBuilder WithNickname(string nickname) { Nickname = nickname; return this; } public BasePokemonBuilder WithNature(string nature) { Nature = nature; return this; } public BasePokemonBuilder WithIVs(StatisticSet ivs) { IVs = ivs; return this; } public BasePokemonBuilder WithEVs(StatisticSet evs) { EVs = evs; return this; } public BasePokemonBuilder LearnMove(string moveName, MoveLearnMethod moveLearnMethod) { if (LearnedMoves.Count > Library.StaticLibrary.Settings.MaximalMoves) { throw new Exception("Too many moves for Pokemon."); } LearnedMoves.Add((moveName, moveLearnMethod)); return this; } protected byte Coloring; protected uint Experience; protected uint Uid; protected int AbilityIndex; protected bool HiddenAbility; protected virtual void PopulateUninitialized(Species species, Forme forme, Random random) { Experience = Library.StaticLibrary.GrowthRateLibrary.CalculateExperience(species.GrowthRate, Level); Uid = random.GetUnsigned(0, uint.MaxValue); if (Gender == (Gender) (-1)) { Gender = species.GetRandomGender(random); } Coloring = 0; if (IsForceShiny.HasValue) { Coloring = (byte) (IsForceShiny.Value ? 1 : 0); } else if (random.Get(Library.StaticLibrary.Settings.ShinyRate) == 0) { Coloring = 1; } AbilityIndex = 0; HiddenAbility = false; if (string.IsNullOrEmpty(Ability)) { AbilityIndex = forme!.GetRandomAbility(random); } else { AbilityIndex = forme!.Abilities.IndexOf(Ability); if (AbilityIndex == -1) { AbilityIndex = forme.HiddenAbilities.IndexOf(Ability); if (AbilityIndex == -1) { throw new Exception( $"Invalid ability '{Ability}' for Pokemon '{species.Name}' and forme '{forme.Name}'."); } HiddenAbility = true; } } } protected abstract TPokemon Finalize(Species species, Forme forme, Item? heldItem, IReadOnlyCollection moves, Nature nature); protected abstract TLearnedMove CreateLearnedMove(MoveData move, byte maxUses, MoveLearnMethod learnMethod); public TPokemon Build(Random? random = null) { if (!Library.StaticLibrary.SpeciesLibrary.TryGet(Species, out var species)) { throw new Exception($"Species '{Species}' was not found."); } if (!species!.TryGetForme(Forme, out var forme)) { throw new Exception($"Forme '{Forme}' was not found on species '{Species}'"); } if (random == null) { random = _defaultRandom; } Item? heldItem = null; if (HeldItem != null) { if (!Library.StaticLibrary.ItemLibrary.TryGet(HeldItem, out heldItem)) { throw new Exception($"Item '{HeldItem}' was not found."); } } var moves = new LearnedMove[Library.StaticLibrary.Settings.MaximalMoves]; for (var i = 0; i < LearnedMoves.Count; i++) { if (!Library.StaticLibrary.MoveLibrary.TryGet(LearnedMoves[i].moveName, out var move)) { throw new Exception($"Move '{LearnedMoves[i].moveName}' was not found."); } moves[i] = CreateLearnedMove(move!, move!.BaseUsages, LearnedMoves[i].learnMethod); } if (string.IsNullOrEmpty(Nature)) { Nature = Library.StaticLibrary.NatureLibrary.GetRandomNatureName(random); } var nature = Library.StaticLibrary.NatureLibrary.GetNature(Nature); if (Gender == (Gender) (-1)) { Gender = species.GetRandomGender(random); } PopulateUninitialized(species, forme!, random); return Finalize(species, forme!, heldItem, moves, nature); } } }