using System.Diagnostics.CodeAnalysis; using PkmnLib.Static; using PkmnLib.Static.Species; namespace PkmnLib.Dynamic.Models.Serialized; /// <summary> /// A serialized Pokémon is a representation of a Pokémon that can be easily serialized and deserialized. /// </summary> public record SerializedPokemon { /// <inheritdoc cref="SerializedPokemon"/> public SerializedPokemon() { } /// <inheritdoc cref="SerializedPokemon"/> [SetsRequiredMembers] public SerializedPokemon(IPokemon pokemon) { Species = pokemon.Species.Name; Form = pokemon.Form.Name; Level = pokemon.Level; Experience = pokemon.Experience; PersonalityValue = pokemon.PersonalityValue; Gender = pokemon.Gender; Coloring = pokemon.Coloring; HeldItem = pokemon.HeldItem?.Name; CurrentHealth = pokemon.CurrentHealth; Happiness = pokemon.Happiness; IndividualValues = new SerializedStats(pokemon.IndividualValues); EffortValues = new SerializedStats(pokemon.EffortValues); Nature = pokemon.Nature.Name; Nickname = pokemon.Nickname; Ability = pokemon.Form.GetAbility(pokemon.AbilityIndex); Moves = pokemon.Moves.Select(move => { if (move == null) return null; return new SerializedLearnedMove { MoveName = move.MoveData.Name, LearnMethod = move.LearnMethod, CurrentPp = move.CurrentPp, }; }).ToArray(); AllowedExperience = pokemon.AllowedExperience; IsEgg = pokemon.IsEgg; Status = pokemon.StatusScript.Script?.Name; } /// <inheritdoc cref="IPokemon.Species"/> public required string Species { get; set; } /// <inheritdoc cref="IPokemon.Form"/> public required string Form { get; set; } /// <inheritdoc cref="IPokemon.Level"/> public LevelInt Level { get; set; } /// <inheritdoc cref="IPokemon.Experience"/> public uint Experience { get; set; } /// <inheritdoc cref="IPokemon.PersonalityValue"/> public uint PersonalityValue { get; set; } /// <inheritdoc cref="IPokemon.Gender"/> public Gender Gender { get; set; } /// <inheritdoc cref="IPokemon.Coloring"/> public byte Coloring { get; set; } /// <inheritdoc cref="IPokemon.HeldItem"/> public string? HeldItem { get; set; } /// <inheritdoc cref="IPokemon.CurrentHealth"/> public uint CurrentHealth { get; set; } /// <inheritdoc cref="IPokemon.Happiness"/> public byte Happiness { get; set; } /// <inheritdoc cref="IPokemon.IndividualValues"/> public required SerializedStats IndividualValues { get; set; } /// <inheritdoc cref="IPokemon.EffortValues"/> public required SerializedStats EffortValues { get; set; } /// <inheritdoc cref="IPokemon.Nature"/> public required string Nature { get; set; } /// <inheritdoc cref="IPokemon.Nickname"/> public string? Nickname { get; set; } /// <summary> /// The ability of the Pokémon. Note that this is the ability name, not the ability index, as the ability index might /// change if the order of abilities changes in data. /// </summary> public required string Ability { get; set; } /// <inheritdoc cref="IPokemon.Moves"/> public required SerializedLearnedMove?[] Moves { get; set; } /// <inheritdoc cref="IPokemon.AllowedExperience"/> public bool AllowedExperience { get; set; } /// <inheritdoc cref="IPokemon.IsEgg"/> public bool IsEgg { get; set; } /// <summary> /// The status of the Pokémon. This is the name of the status script, if any exists. /// </summary> public string? Status { get; set; } } /// <summary> /// A serialized learned move is a representation of a learned move that can be easily serialized and deserialized. /// </summary> public record SerializedLearnedMove { /// <summary> /// The name of the move. /// </summary> public required string MoveName { get; set; } /// <inheritdoc cref="ILearnedMove.LearnMethod"/> public required MoveLearnMethod LearnMethod { get; set; } /// <inheritdoc cref="ILearnedMove.CurrentPp"/> public required byte CurrentPp { get; set; } } public record SerializedStats { public SerializedStats() { } public SerializedStats(ImmutableStatisticSet<byte> stats) { Hp = stats.Hp; Attack = stats.Attack; Defense = stats.Defense; SpecialAttack = stats.SpecialAttack; SpecialDefense = stats.SpecialDefense; Speed = stats.Speed; } public SerializedStats(long hp, long attack, long defense, long specialAttack, long specialDefense, long speed) { Hp = hp; Attack = attack; Defense = defense; SpecialAttack = specialAttack; SpecialDefense = specialDefense; Speed = speed; } public long Hp { get; set; } public long Attack { get; set; } public long Defense { get; set; } public long SpecialAttack { get; set; } public long SpecialDefense { get; set; } public long Speed { get; set; } public IndividualValueStatisticSet ToIndividualValueStatisticSet() { if (Hp < 0 || Attack < 0 || Defense < 0 || SpecialAttack < 0 || SpecialDefense < 0 || Speed < 0) throw new InvalidOperationException("Stats cannot be negative."); if (Hp > byte.MaxValue || Attack > byte.MaxValue || Defense > byte.MaxValue || SpecialAttack > byte.MaxValue || SpecialDefense > byte.MaxValue || Speed > byte.MaxValue) throw new InvalidOperationException("Stats cannot be higher than 255."); return new IndividualValueStatisticSet((byte)Hp, (byte)Attack, (byte)Defense, (byte)SpecialAttack, (byte)SpecialDefense, (byte)Speed); } public EffortValueStatisticSet ToEffortValueStatisticSet() { if (Hp < 0 || Attack < 0 || Defense < 0 || SpecialAttack < 0 || SpecialDefense < 0 || Speed < 0) throw new InvalidOperationException("Stats cannot be negative."); if (Hp > byte.MaxValue || Attack > byte.MaxValue || Defense > byte.MaxValue || SpecialAttack > byte.MaxValue || SpecialDefense > byte.MaxValue || Speed > byte.MaxValue) throw new InvalidOperationException("Stats cannot be higher than 255."); return new EffortValueStatisticSet((byte)Hp, (byte)Attack, (byte)Defense, (byte)SpecialAttack, (byte)SpecialDefense, (byte)Speed); } }