using System; namespace PKHeX.Core; /// /// Logic for calculating the characteristic behavior of Pokémon. /// public static class EntityCharacteristic { /// /// Gets the characteristic index from the input parameters. /// /// Index of the highest IV. /// Value of the highest IV. /// Characteristic index. public static int GetCharacteristic(int maxStatIndex, int maxStatValue) => (maxStatIndex * 5) + (maxStatValue % 5); /// /// Gets the characteristic index of the given IVs in Little Endian format. /// /// Encryption Constant. /// Lumped IVs in Little Endian format. /// Characteristic index. public static int GetCharacteristic(uint ec, uint iv32) { int index = (int)(ec % 6); // Get individual IVs from the lumped value. // The IVs are stored in the following order: HP, Atk, Def, Spe, SpA, SpD // Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen. int maxStatIndex = index; var maxStatValue = 0u; do { var value = iv32 >> (index * 5) & 0x1F; if (value > maxStatValue) { maxStatIndex = index; maxStatValue = value; } if (index != 5) index++; else index = 0; } while (maxStatIndex != index); return GetCharacteristic(maxStatIndex, (int)maxStatValue); } /// /// Gets the characteristic index of the given unpacked IVs. /// /// Encryption Constant. /// Unpacked IVs. /// Characteristic index. public static int GetCharacteristic(uint ec, Span ivs) { int index = (int)(ec % 6); // Get individual IVs from the lumped value. // The IVs are stored in the following order: HP, Atk, Def, Spe, SpA, SpD // Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen. int maxStatIndex = index; var maxStatValue = 0; do { var value = ivs[index]; if (value > maxStatValue) { maxStatIndex = index; maxStatValue = value; } if (index != 5) index++; else index = 0; } while (maxStatIndex != index); return GetCharacteristic(maxStatIndex, maxStatValue); } /// /// Gets the characteristic index of the given IVs in Big Endian format. /// /// Encryption Constant. /// Lumped IVs in Big Endian format. /// Characteristic index. public static int GetCharacteristicInvertFields(uint ec, uint iv32) { int index = (int)(ec % 6); // Get individual IVs from the lumped value. // The IVs are stored in the following order: SpD, SpA, Spe, Def, Atk, HP // Check all IVs, get the highest IV and its index. If there are multiple highest IVs, the first index checked is chosen. int maxStatIndex = index; var maxStatValue = 0u; do { // IVs are stored in reverse order, get the bits from the end of the IV value var value = iv32 >> (27 - (index * 5)) & 0x1F; if (value > maxStatValue) { maxStatIndex = index; maxStatValue = value; } if (index != 5) index++; else index = 0; } while (maxStatIndex != index); return GetCharacteristic(maxStatIndex, (int)maxStatValue); } }