diff --git a/pkNX.Structures/Util.cs b/pkNX.Structures/Util.cs index 22afa5b3..e80efecd 100644 --- a/pkNX.Structures/Util.cs +++ b/pkNX.Structures/Util.cs @@ -18,6 +18,14 @@ private static T[] GetArray(IReadOnlyList entries, Func de return data; } + public static T[] GetArray(byte[][] entries, Func del, int size) + { + var data = new T[entries.Length / size]; + for (int i = 0; i < data.Length; i++) + data[i] = del(entries[i]); + return data; + } + public static T[] GetArray(this byte[] entries, Func del, int size) { if (entries == null || entries.Length < size) diff --git a/pkNX.Structures/VsTrainer/Base/IAwakened.cs b/pkNX.Structures/VsTrainer/Base/IAwakened.cs new file mode 100644 index 00000000..3d9fbc8d --- /dev/null +++ b/pkNX.Structures/VsTrainer/Base/IAwakened.cs @@ -0,0 +1,12 @@ +namespace pkNX.Structures +{ + public interface IAwakened + { + int AV_HP { get; set; } + int AV_ATK { get; set; } + int AV_DEF { get; set; } + int AV_SPA { get; set; } + int AV_SPD { get; set; } + int AV_SPE { get; set; } + } +} \ No newline at end of file diff --git a/pkNX.Structures/VsTrainer/Base/IMoveset.cs b/pkNX.Structures/VsTrainer/Base/IMoveset.cs new file mode 100644 index 00000000..68c268f2 --- /dev/null +++ b/pkNX.Structures/VsTrainer/Base/IMoveset.cs @@ -0,0 +1,10 @@ +namespace pkNX.Structures +{ + public interface IMoveset + { + int Move1 { get; set; } + int Move2 { get; set; } + int Move3 { get; set; } + int Move4 { get; set; } + } +} \ No newline at end of file diff --git a/pkNX.Structures/VsTrainer/Base/ITrainerPoke.cs b/pkNX.Structures/VsTrainer/Base/ITrainerPoke.cs new file mode 100644 index 00000000..77238736 --- /dev/null +++ b/pkNX.Structures/VsTrainer/Base/ITrainerPoke.cs @@ -0,0 +1,27 @@ +namespace pkNX.Structures +{ + public interface IPokeData + { + int Species { get; set; } + int Level { get; set; } + int Nature { get; set; } + int Form { get; set; } + int HeldItem { get; set; } + int Gender { get; set; } + int Ability { get; set; } + + int IV_HP { get; set; } + int IV_ATK { get; set; } + int IV_DEF { get; set; } + int IV_SPA { get; set; } + int IV_SPD { get; set; } + int IV_SPE { get; set; } + + int EV_HP { get; set; } + int EV_ATK { get; set; } + int EV_DEF { get; set; } + int EV_SPA { get; set; } + int EV_SPD { get; set; } + int EV_SPE { get; set; } + } +} \ No newline at end of file diff --git a/pkNX.Structures/VsTrainer/Base/StatPKM.cs b/pkNX.Structures/VsTrainer/Base/StatPKM.cs new file mode 100644 index 00000000..74a555e2 --- /dev/null +++ b/pkNX.Structures/VsTrainer/Base/StatPKM.cs @@ -0,0 +1,146 @@ +using System; + +namespace pkNX.Structures +{ + public abstract class StatPKM : IPokeData + { + public abstract int Species { get; set; } + public abstract int Form { get; set; } + public abstract int Level { get; set; } + public abstract int Nature { get; set; } + + public abstract int HeldItem { get; set; } + public abstract int Gender { get; set; } + public abstract int Ability { get; set; } + + public abstract int IV_HP { get; set; } + public abstract int IV_ATK { get; set; } + public abstract int IV_DEF { get; set; } + public abstract int IV_SPA { get; set; } + public abstract int IV_SPD { get; set; } + public abstract int IV_SPE { get; set; } + + public abstract int EV_HP { get; set; } + public abstract int EV_ATK { get; set; } + public abstract int EV_DEF { get; set; } + public abstract int EV_SPA { get; set; } + public abstract int EV_SPD { get; set; } + public abstract int EV_SPE { get; set; } + + public virtual ushort[] GetStats(PersonalInfo p) + { + ushort[] Stats = new ushort[6]; + Stats[0] = (ushort)(((IV_HP + (2 * p.HP) + (EV_HP / 4) + 100) * Level / 100) + 10); + Stats[1] = (ushort)((((IV_ATK + (2 * p.ATK) + EV_ATK) / 4) * Level / 100) + 5); + Stats[2] = (ushort)((((IV_DEF + (2 * p.DEF) + EV_DEF) / 4) * Level / 100) + 5); + Stats[4] = (ushort)((((IV_SPA + (2 * p.SPA) + EV_SPA) / 4) * Level / 100) + 5); + Stats[5] = (ushort)((((IV_SPD + (2 * p.SPD) + EV_SPD) / 4) * Level / 100) + 5); + Stats[3] = (ushort)((((IV_SPE + (2 * p.SPE) + EV_SPE) / 4) * Level / 100) + 5); + if (p.HP == 1) + Stats[0] = 1; + + // Account for nature + int incr = (Nature / 5) + 1; + int decr = (Nature % 5) + 1; + if (incr != decr) + { + Stats[incr] *= 11; + Stats[incr] /= 10; + Stats[decr] *= 9; + Stats[decr] /= 10; + } + + return Stats; + } + + public int HiddenPowerType => 15 * (IV_HP + (2 * IV_ATK) + (4 * IV_DEF) + (8 * IV_SPE) + (16 * IV_SPA) + (32 * IV_SPD)) / 63; + + public int GetIV(int index) + { + switch (index) + { + case 0: return IV_HP; + case 1: return IV_ATK; + case 2: return IV_DEF; + case 3: return IV_SPE; + case 4: return IV_SPA; + case 5: return IV_SPD; + default: + throw new ArgumentOutOfRangeException(nameof(index)); + } + } + + public void SetIV(int index, int value) + { + switch (index) + { + case 0: IV_HP = value; break; + case 1: IV_ATK = value; break; + case 2: IV_DEF = value; break; + case 3: IV_SPE = value; break; + case 4: IV_SPA = value; break; + case 5: IV_SPD = value; break; + default: + throw new ArgumentOutOfRangeException(nameof(index)); + } + } + + public int GetEV(int index) + { + switch (index) + { + case 0: return EV_HP; + case 1: return EV_ATK; + case 2: return EV_DEF; + case 3: return EV_SPE; + case 4: return EV_SPA; + case 5: return EV_SPD; + default: + throw new ArgumentOutOfRangeException(nameof(index)); + } + } + + public void SetEV(int index, int value) + { + switch (index) + { + case 0: EV_HP = value; break; + case 1: EV_ATK = value; break; + case 2: EV_DEF = value; break; + case 3: EV_SPE = value; break; + case 4: EV_SPA = value; break; + case 5: EV_SPD = value; break; + default: + throw new ArgumentOutOfRangeException(nameof(index)); + } + } + + public void SetHPIVs(int type) + { + for (int i = 0; i < 6; i++) + { + var val = (GetIV(i) & 0x1E) + hpivs[type, i]; + SetIV(i, val); + } + } + + private static readonly int[,] hpivs = { + { 1, 1, 0, 0, 0, 0 }, // Fighting + { 0, 0, 0, 0, 0, 1 }, // Flying + { 1, 1, 0, 0, 0, 1 }, // Poison + { 1, 1, 1, 0, 0, 1 }, // Ground + { 1, 1, 0, 1, 0, 0 }, // Rock + { 1, 0, 0, 1, 0, 1 }, // Bug + { 1, 0, 1, 1, 0, 1 }, // Ghost + { 1, 1, 1, 1, 0, 1 }, // Steel + { 1, 0, 1, 0, 1, 0 }, // Fire + { 1, 0, 0, 0, 1, 1 }, // Water + { 1, 0, 1, 0, 1, 1 }, // Grass + { 1, 1, 1, 0, 1, 1 }, // Electric + { 1, 0, 1, 1, 1, 0 }, // Psychic + { 1, 0, 0, 1, 1, 1 }, // Ice + { 1, 0, 1, 1, 1, 1 }, // Dragon + { 1, 1, 1, 1, 1, 1 }, // Dark + }; + } +} \ No newline at end of file diff --git a/pkNX.Structures/VsTrainer/Base/TrainerPoke.cs b/pkNX.Structures/VsTrainer/Base/TrainerPoke.cs index d4db6091..a48ec5c5 100644 --- a/pkNX.Structures/VsTrainer/Base/TrainerPoke.cs +++ b/pkNX.Structures/VsTrainer/Base/TrainerPoke.cs @@ -1,16 +1,9 @@ namespace pkNX.Structures { - public abstract class TrainerPoke + public abstract class TrainerPoke : StatPKM, IMoveset, IAwakened { protected byte[] Data; - public abstract int Species { get; set; } - public abstract int Form { get; set; } - public abstract int Level { get; set; } - public abstract int HeldItem { get; set; } - public abstract int Nature { get; set; } - public abstract int Gender { get; set; } - public abstract int Ability { get; set; } public abstract int Friendship { get; set; } public abstract bool Shiny { get; set; } @@ -22,19 +15,6 @@ public abstract class TrainerPoke public abstract int Move4 { get; set; } public abstract uint IV32 { get; set; } - public abstract int IV_HP { get; set; } - public abstract int IV_ATK { get; set; } - public abstract int IV_DEF { get; set; } - public abstract int IV_SPE { get; set; } - public abstract int IV_SPA { get; set; } - public abstract int IV_SPD { get; set; } - - public abstract int EV_HP { get; set; } - public abstract int EV_ATK { get; set; } - public abstract int EV_DEF { get; set; } - public abstract int EV_SPA { get; set; } - public abstract int EV_SPD { get; set; } - public abstract int EV_SPE { get; set; } public abstract int AV_HP { get; set; } public abstract int AV_ATK { get; set; } diff --git a/pkNX.Structures/VsTrainer/GG/Trainer7b.cs b/pkNX.Structures/VsTrainer/GG/Trainer7b.cs index 75c1b382..febace91 100644 --- a/pkNX.Structures/VsTrainer/GG/Trainer7b.cs +++ b/pkNX.Structures/VsTrainer/GG/Trainer7b.cs @@ -6,14 +6,14 @@ public class Trainer7b : VsTrainer { public Trainer7b(byte[] tr = null, byte[] tp = null) { - Trainer = new TrainerData7b(tr); + Self = new TrainerData7b(tr); LoadTeam(tp); } private void LoadTeam(byte[] tp) { - var pokes = tp.GetArray((data, offset) => new TrainerPoke7b(offset, data), TrainerPoke7b.SIZE); - Debug.Assert(pokes.Length == Trainer.NumPokemon); + var pokes = TrainerPoke7b.ReadTeam(tp, Self); + Debug.Assert(pokes.Length == Self.NumPokemon); Team.AddRange(pokes); } } diff --git a/pkNX.Structures/VsTrainer/GG/TrainerPoke7b.cs b/pkNX.Structures/VsTrainer/GG/TrainerPoke7b.cs index 64b32bb0..b231f611 100644 --- a/pkNX.Structures/VsTrainer/GG/TrainerPoke7b.cs +++ b/pkNX.Structures/VsTrainer/GG/TrainerPoke7b.cs @@ -1,13 +1,18 @@ using System; +using System.Collections.Generic; +using System.Linq; namespace pkNX.Structures { public class TrainerPoke7b : TrainerPoke { - internal const int SIZE = 0x28; + public const int SIZE = 0x28; public override TrainerPoke Clone() => new TrainerPoke7b(Write()); public TrainerPoke7b(byte[] data = null) => Data = data ?? new byte[SIZE]; + public static TrainerPoke7b[] ReadTeam(byte[] data, TrainerData _) => data.GetArray((x, offset) => new TrainerPoke7b(offset, x), SIZE); + public static byte[] WriteTeam(IList team, TrainerData _) => team.SelectMany(z => z.Write()).ToArray(); + public TrainerPoke7b(int index, byte[] data = null) { Data = new byte[SIZE]; diff --git a/pkNX.Structures/VsTrainer/VsTrainer.cs b/pkNX.Structures/VsTrainer/VsTrainer.cs index dd429eb2..4baefa03 100644 --- a/pkNX.Structures/VsTrainer/VsTrainer.cs +++ b/pkNX.Structures/VsTrainer/VsTrainer.cs @@ -6,9 +6,9 @@ public class VsTrainer { public int ID { get; set; } public string Name { get; set; } - public TrainerData Trainer { get; set; } + public TrainerData Self { get; set; } public readonly List Team = new List(6); - public TrainerClass GetClass(IList list) => list[Trainer.Class]; + public TrainerClass GetClass(IList list) => list[Self.Class]; } }