PKHeX/PKHeX.Core/Saves/Substructures/PokeDex/Zukan7b.cs
Kurt 35a85670b3 Set height/weight dex values
Closes #2167
Based off sub_71001D16A0 with shortcut modifications:
* code marks new entries for evolution processing later using the low
bit (hence the << 1); in save files I can't see any bits set, but I
can't see anywhere in the code that DOESNT set this bit. Thus the
assumption of post-processing.

As noted in gameplay, a new capture doesn't set Min and Max; it only
sets it if it is above the usual sizing values.

Megas apparently don't set until seen in battle, so don't worry about
setting the other forme based indexes.
2018-11-27 22:05:36 -08:00

191 lines
No EOL
7.1 KiB
C#

using System;
namespace PKHeX.Core
{
/// <summary>
/// Beluga specific Dex manipulator, slightly modified from Gen7.
/// </summary>
public class Zukan7b : Zukan7
{
private const int SIZE_MAGIC = 4; // 0x2F120F17 magic
private const int SIZE_FLAGS = 4;
private const int SIZE_MISC = 0x80; // Misc Data (1024 bits)
private const int SIZE_CAUGHT = 0x68; // 832 bits
protected override int OFS_CAUGHT => SIZE_MAGIC + SIZE_FLAGS + SIZE_MISC;
protected override int OFS_SEEN => OFS_CAUGHT + SIZE_CAUGHT;
protected override int BitSeenSize => 0x8C; // 1120 bits
protected override int DexLangFlagByteCount => 920; // 0x398 = 817*9, top off the savedata block.
protected override int DexLangIDCount => 9; // CHT, skipping langID 6 (unused)
public Zukan7b(SaveFile sav, int dex, int langflag)
{
SAV = sav;
PokeDex = dex;
PokeDexLanguageFlags = langflag;
DexFormIndexFetcher = SaveUtil.GetDexFormIndexGG;
LoadDexList();
}
public override void SetDex(PKM pkm)
{
if (!TryGetIndex(pkm.AltForm, pkm.Species, out _))
return;
SetSizeData((PB7)pkm);
base.SetDex(pkm);
}
protected override void SetDex(int species, int bit, int form, int gender, bool shiny, int lang)
{
if (IsBuddy(species, form))
form = 0;
base.SetDex(species, bit, form, gender, shiny, lang);
}
private static bool IsBuddy(int species, int form) => (species == 25 && form == 8) || (species == 133 && form == 1);
private void SetSizeData(PB7 pkm)
{
int species = pkm.Species;
int form = pkm.AltForm;
if (!TryGetIndex(form, species, out int index))
return;
if (Math.Round(pkm.HeightAbsolute) < pkm.PersonalInfo.Height) // possible minimum height
{
int ofs = GetDexSizeOffset(0, index);
var minHeight = BitConverter.ToUInt16(SAV.Data, ofs) >> 1;
var calcHeight = PB7.GetHeightAbsolute(pkm.PersonalInfo, minHeight);
if (Math.Round(pkm.HeightAbsolute) < Math.Round(calcHeight) || BitConverter.ToUInt32(SAV.Data, ofs) == 0x007F00FE) // unset
UpdateSizeIndex(pkm, 0);
}
else if (Math.Round(pkm.HeightAbsolute) > pkm.PersonalInfo.Height) // possible maximum height
{
int ofs = GetDexSizeOffset(1, index);
var maxHeight = BitConverter.ToUInt16(SAV.Data, ofs) >> 1;
var calcHeight = PB7.GetHeightAbsolute(pkm.PersonalInfo, maxHeight);
if (Math.Round(pkm.HeightAbsolute) > Math.Round(calcHeight) || BitConverter.ToUInt32(SAV.Data, ofs) == 0x007F00FE) // unset
UpdateSizeIndex(pkm, 1);
}
if (Math.Round(pkm.WeightAbsolute) < pkm.PersonalInfo.Weight) // possible minimum weight
{
int ofs = GetDexSizeOffset(2, index);
var minWeight = BitConverter.ToUInt16(SAV.Data, ofs + 2);
var minHeight = BitConverter.ToUInt16(SAV.Data, ofs) >> 1;
var calcWeight = PB7.GetWeightAbsolute(pkm.PersonalInfo, minHeight, minWeight);
if (Math.Round(pkm.WeightAbsolute) < Math.Round(calcWeight) || BitConverter.ToUInt32(SAV.Data, ofs) == 0x007F00FE) // unset
UpdateSizeIndex(pkm, 2);
}
else if (Math.Round(pkm.WeightAbsolute) > pkm.PersonalInfo.Weight) // possible maximum weight
{
int ofs = GetDexSizeOffset(3, index);
var maxWeight = BitConverter.ToUInt16(SAV.Data, ofs + 2);
var maxHeight = BitConverter.ToUInt16(SAV.Data, ofs) >> 1;
var calcWeight = PB7.GetWeightAbsolute(pkm.PersonalInfo, maxHeight, maxWeight);
if (Math.Round(pkm.WeightAbsolute) > Math.Round(calcWeight) || BitConverter.ToUInt32(SAV.Data, ofs) == 0x007F00FE) // unset
UpdateSizeIndex(pkm, 3);
}
}
private int GetDexSizeOffset(int group, int index) => 0x3978 + (index * 6) + (group * 0x45C); // blockofs + 0xF78 + ([186*6]*n) + x*6
private void UpdateSizeIndex(PB7 pkm, int group)
{
var tree = EvolutionTree.GetEvolutionTree(pkm, 7);
int species = pkm.Species;
int form = pkm.AltForm;
// update for all species in potential lineage
var allspec = tree.GetEvolutionsAndPreEvolutions(species, form);
foreach (var s in allspec)
{
if (!TryGetIndex(form, s, out var index))
continue; // shouldn't hit this
var ofs = GetDexSizeOffset(group, index);
BitConverter.GetBytes((ushort)(pkm.HeightScalar << 1)).CopyTo(SAV.Data, ofs);
BitConverter.GetBytes((ushort)(pkm.WeightScalar)).CopyTo(SAV.Data, ofs + 2);
}
}
private static bool TryGetIndex(int form, int species, out int index)
{
index = -1;
if (form == 0 && species <= 151)
{
index = species - 1;
return true;
}
for (int i = 0; i < SizeDexInfoTable.Length; i += 3)
{
if (SizeDexInfoTable[i] != species)
continue;
if (SizeDexInfoTable[i + 1] != form)
continue;
index = SizeDexInfoTable[i + 2];
return true;
}
return false;
}
public static readonly ushort[] SizeDexInfoTable =
{
// spec, form, index
808, 0, 151,
809, 0, 152,
003, 1, 153,
006, 1, 154,
006, 2, 155,
009, 1, 156,
015, 1, 157,
018, 1, 158,
019, 1, 159,
020, 1, 160,
026, 1, 161,
027, 1, 162,
028, 1, 163,
037, 1, 164,
038, 1, 165,
050, 1, 166,
051, 1, 167,
052, 1, 168,
053, 1, 169,
065, 1, 170,
074, 1, 171,
075, 1, 172,
076, 1, 173,
080, 1, 174,
088, 1, 175,
089, 1, 176,
094, 1, 177,
103, 1, 178,
105, 1, 179,
115, 1, 180,
127, 1, 181,
130, 1, 182,
142, 1, 183,
150, 1, 184,
150, 2, 185,
};
protected override bool GetSaneFormsToIterate(int species, out int formStart, out int formEnd, int formIn)
{
switch (species)
{
case 020: // Raticate
case 105: // Marowak
formStart = 0;
formEnd = 1;
return true;
default:
int count = SaveUtil.GetDexFormCountGG(species);
formStart = formEnd = 0;
return count < formIn;
}
}
}
}