mirror of
https://github.com/kwsch/PKHeX
synced 2024-11-24 04:53:08 +00:00
Refactoring
Increase flexibility, use game personal data and structure to clearly define what is going on. Helps for implementing future games.
This commit is contained in:
parent
8a2e7f3f74
commit
c9d0db23ac
9 changed files with 181 additions and 90 deletions
|
@ -407,7 +407,12 @@ namespace PKHeX
|
|||
get { return CurrentHandler == 1 ? OT_Friendship : HT_Friendship; }
|
||||
set { if (CurrentHandler == 1) OT_Friendship = value; else HT_Friendship = value; }
|
||||
}
|
||||
public int[] IVs { get { return new[] { IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD }; } }
|
||||
|
||||
public int[] IVs {
|
||||
get { return new[] {IV_HP, IV_ATK, IV_DEF, IV_SPE, IV_SPA, IV_SPD}; }
|
||||
set { if (value == null || value.Length != 6) return;
|
||||
IV_HP = value[0]; IV_ATK = value[1]; IV_DEF = value[2];
|
||||
IV_SPE = value[3]; IV_SPA = value[4]; IV_SPD = value[5]; } }
|
||||
public int[] EVs { get { return new[] { EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD }; } }
|
||||
public int[] Moves { get { return new[] { Move1, Move2, Move3, Move4 }; } }
|
||||
public int PSV { get { return (int)(((PID >> 16) ^ (PID & 0xFFFF)) >> 4); } }
|
||||
|
@ -667,7 +672,7 @@ namespace PKHeX
|
|||
Geo1_Country = Country;
|
||||
Geo1_Region = Region;
|
||||
}
|
||||
private void TradeMemory(bool Bank)
|
||||
public void TradeMemory(bool Bank)
|
||||
{
|
||||
HT_Memory = 4; // Link trade to [VAR: General Location]
|
||||
HT_TextVar = Bank ? 0 : 9; // Somewhere (Bank) : Pokécenter (Trade)
|
||||
|
|
220
Misc/PKX.cs
220
Misc/PKX.cs
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using System.Drawing;
|
||||
using System.Drawing.Text;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace PKHeX
|
||||
|
@ -136,6 +137,40 @@ namespace PKHeX
|
|||
};
|
||||
#endregion
|
||||
|
||||
internal static string[][] SpeciesLang =
|
||||
{
|
||||
Util.getStringList("Species", "ja"), // none
|
||||
Util.getStringList("Species", "ja"), // 1
|
||||
Util.getStringList("Species", "en"), // 2
|
||||
Util.getStringList("Species", "fr"), // 3
|
||||
Util.getStringList("Species", "it"), // 4
|
||||
Util.getStringList("Species", "de"), // 5
|
||||
Util.getStringList("Species", "es"), // none
|
||||
Util.getStringList("Species", "es"), // 7
|
||||
Util.getStringList("Species", "ko"), // 8
|
||||
};
|
||||
|
||||
internal static string getSpeciesName(int species, int lang)
|
||||
{
|
||||
try { return SpeciesLang[lang][species]; }
|
||||
catch { return ""; }
|
||||
}
|
||||
internal static PersonalInfo[] Personal = getPersonalArray(Properties.Resources.personal);
|
||||
internal static PersonalInfo[] getPersonalArray(byte[] data)
|
||||
{
|
||||
PersonalInfo[] d = new PersonalInfo[data.Length / PersonalInfo.Size];
|
||||
int formeIndex = 723;
|
||||
for (int i = 0; i < d.Length; i++)
|
||||
{
|
||||
d[i] = new PersonalInfo(data.Skip(i*PersonalInfo.Size).Take(PersonalInfo.Size).ToArray());
|
||||
if (d[i].FormeCount <= 1) continue;
|
||||
|
||||
d[i].FormeOffset = formeIndex;
|
||||
formeIndex += d[i].FormeCount;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
// Stat Fetching
|
||||
internal static int getMovePP(int move, int ppup)
|
||||
{
|
||||
|
@ -200,14 +235,13 @@ namespace PKHeX
|
|||
}
|
||||
internal static byte getBaseFriendship(int species)
|
||||
{
|
||||
return PersonalGetter.GetPersonal(species).BaseFriendship;
|
||||
return Personal[species].BaseFriendship;
|
||||
}
|
||||
internal static int getLevel(int species, uint exp)
|
||||
{
|
||||
if (exp == 0) { return 1; }
|
||||
|
||||
PersonalParser.Personal MonData = PersonalGetter.GetPersonal(species);
|
||||
int growth = MonData.EXPGrowth;
|
||||
int growth = Personal[species].EXPGrowth;
|
||||
|
||||
// Iterate upwards to find the level above our current level
|
||||
int tl = 0; // Initial Level, immediately incremented before loop.
|
||||
|
@ -231,15 +265,11 @@ namespace PKHeX
|
|||
if ((level == 0) || (level == 1))
|
||||
return 0;
|
||||
if (level > 100) level = 100;
|
||||
|
||||
PersonalParser.Personal MonData = PersonalGetter.GetPersonal(species);
|
||||
int growth = MonData.EXPGrowth;
|
||||
|
||||
return ExpTable[level, growth];
|
||||
return ExpTable[level, Personal[species].EXPGrowth];
|
||||
}
|
||||
internal static byte[] getAbilities(int species, int formnum)
|
||||
{
|
||||
return PersonalGetter.GetPersonal(species, formnum).Abilities;
|
||||
return Personal[Personal[species].FormeIndex(species, formnum)].Abilities;
|
||||
}
|
||||
internal static int getGender(string s)
|
||||
{
|
||||
|
@ -382,13 +412,13 @@ namespace PKHeX
|
|||
int HP_EV, int ATK_EV, int DEF_EV, int SPA_EV, int SPD_EV, int SPE_EV,
|
||||
int HP_IV, int ATK_IV, int DEF_IV, int SPA_IV, int SPD_IV, int SPE_IV)
|
||||
{
|
||||
PersonalParser.Personal MonData = PersonalGetter.GetPersonal(species, form);
|
||||
int HP_B = MonData.BaseStats[0];
|
||||
int ATK_B = MonData.BaseStats[1];
|
||||
int DEF_B = MonData.BaseStats[2];
|
||||
int SPE_B = MonData.BaseStats[3];
|
||||
int SPA_B = MonData.BaseStats[4];
|
||||
int SPD_B = MonData.BaseStats[5];
|
||||
PersonalInfo p = Personal[Personal[species].FormeIndex(species, form)];
|
||||
int HP_B = p.HP;
|
||||
int ATK_B = p.ATK;
|
||||
int DEF_B = p.DEF;
|
||||
int SPE_B = p.SPE;
|
||||
int SPA_B = p.SPA;
|
||||
int SPD_B = p.SPD;
|
||||
|
||||
// Calculate Stats
|
||||
ushort[] stats = new ushort[6]; // Stats are stored as ushorts in the PKX structure. We'll cap them as such.
|
||||
|
@ -529,8 +559,7 @@ namespace PKHeX
|
|||
}
|
||||
internal static uint getRandomPID(int species, int cg)
|
||||
{
|
||||
PersonalParser.Personal MonData = PersonalGetter.GetPersonal(species);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = Personal[species].Gender;
|
||||
uint pid = Util.rnd32();
|
||||
if (gt == 255) //Genderless
|
||||
return pid;
|
||||
|
@ -800,48 +829,6 @@ namespace PKHeX
|
|||
}
|
||||
|
||||
// Personal.dat
|
||||
internal static PersonalParser PersonalGetter = new PersonalParser();
|
||||
internal class PersonalParser
|
||||
{
|
||||
internal byte[] file = Properties.Resources.personal;
|
||||
internal const int EntryLength = 0xE;
|
||||
internal struct Personal
|
||||
{
|
||||
public byte[] BaseStats;
|
||||
public byte[] Abilities;
|
||||
public byte BaseFriendship;
|
||||
public byte GenderRatio;
|
||||
public byte EXPGrowth;
|
||||
public byte AltFormCount;
|
||||
public byte FormPointer; // 721 + FormPointer + (FormID - 1) = SpeciesIndex
|
||||
}
|
||||
|
||||
internal Personal GetPersonal(int species)
|
||||
{
|
||||
Personal data = new Personal();
|
||||
byte[] MonData = new byte[EntryLength];
|
||||
data.BaseStats = new byte[6];
|
||||
data.Abilities = new byte[3];
|
||||
Array.Copy(file, species * EntryLength, MonData, 0, EntryLength);
|
||||
Array.Copy(MonData, data.BaseStats, 6);
|
||||
Array.Copy(MonData, 6, data.Abilities, 0, 3);
|
||||
data.BaseFriendship = MonData[0x9];
|
||||
data.GenderRatio = MonData[0xA];
|
||||
data.EXPGrowth = MonData[0xB];
|
||||
data.AltFormCount = MonData[0xC];
|
||||
data.FormPointer = MonData[0xD];
|
||||
return data;
|
||||
}
|
||||
internal Personal GetPersonal(int species, int formID)
|
||||
{
|
||||
Personal data = GetPersonal(species);
|
||||
if (formID <= 0 || formID > data.AltFormCount || data.AltFormCount <= 0 || data.FormPointer <= 0)
|
||||
return data;
|
||||
|
||||
// Working with an Alt Forme with a base stat change
|
||||
return GetPersonal(721 + --formID + data.FormPointer);
|
||||
}
|
||||
}
|
||||
internal static string[] getFormList(int species, string[] t, string[] f, string[] g)
|
||||
{
|
||||
|
||||
|
@ -1373,5 +1360,118 @@ namespace PKHeX
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class PersonalInfo
|
||||
{
|
||||
internal static int Size = 0x50;
|
||||
public byte HP, ATK, DEF, SPE, SPA, SPD;
|
||||
public int BST;
|
||||
public int EV_HP, EV_ATK, EV_DEF, EV_SPE, EV_SPA, EV_SPD;
|
||||
public byte[] Types = new byte[2];
|
||||
public byte CatchRate, EvoStage;
|
||||
public ushort[] Items = new ushort[3];
|
||||
public byte Gender, HatchCycles, BaseFriendship, EXPGrowth;
|
||||
public byte[] EggGroups = new byte[2];
|
||||
public byte[] Abilities = new byte[3];
|
||||
public ushort FormStats, FormeSprite, BaseEXP;
|
||||
public byte FormeCount, Color;
|
||||
public float Height, Weight;
|
||||
public bool[] TMHM;
|
||||
public bool[] Tutors;
|
||||
public bool[][] ORASTutors = new bool[4][];
|
||||
public byte EscapeRate;
|
||||
|
||||
public PersonalInfo(byte[] data)
|
||||
{
|
||||
using (BinaryReader br = new BinaryReader(new MemoryStream(data)))
|
||||
{
|
||||
HP = br.ReadByte(); ATK = br.ReadByte(); DEF = br.ReadByte();
|
||||
SPE = br.ReadByte(); SPA = br.ReadByte(); SPD = br.ReadByte();
|
||||
BST = HP + ATK + DEF + SPE + SPA + SPD;
|
||||
|
||||
Types = new[] { br.ReadByte(), br.ReadByte() };
|
||||
CatchRate = br.ReadByte();
|
||||
EvoStage = br.ReadByte();
|
||||
|
||||
ushort EVs = br.ReadUInt16();
|
||||
EV_HP = ((EVs >> 0) & 0x3);
|
||||
EV_ATK = ((EVs >> 2) & 0x3);
|
||||
EV_DEF = ((EVs >> 4) & 0x3);
|
||||
EV_SPE = ((EVs >> 6) & 0x3);
|
||||
EV_SPA = ((EVs >> 8) & 0x3);
|
||||
EV_SPD = ((EVs >> 10) & 0x3);
|
||||
|
||||
Items = new[] { br.ReadUInt16(), br.ReadUInt16(), br.ReadUInt16() };
|
||||
Gender = br.ReadByte();
|
||||
HatchCycles = br.ReadByte();
|
||||
BaseFriendship = br.ReadByte();
|
||||
|
||||
EXPGrowth = br.ReadByte();
|
||||
EggGroups = new[] { br.ReadByte(), br.ReadByte() };
|
||||
Abilities = new[] { br.ReadByte(), br.ReadByte(), br.ReadByte() };
|
||||
EscapeRate = br.ReadByte();
|
||||
FormStats = br.ReadUInt16();
|
||||
|
||||
FormeSprite = br.ReadUInt16();
|
||||
FormeCount = br.ReadByte();
|
||||
Color = br.ReadByte();
|
||||
BaseEXP = br.ReadUInt16();
|
||||
|
||||
Height = br.ReadUInt16();
|
||||
Weight = br.ReadUInt16();
|
||||
|
||||
byte[] TMHMData = br.ReadBytes(0x10);
|
||||
TMHM = new bool[8 * TMHMData.Length];
|
||||
for (int j = 0; j < TMHM.Length; j++)
|
||||
TMHM[j] = ((TMHMData[j / 8] >> (j % 8)) & 0x1) == 1; //Bitflags for TMHM
|
||||
|
||||
byte[] TutorData = br.ReadBytes(8);
|
||||
Tutors = new bool[8 * TutorData.Length];
|
||||
for (int j = 0; j < Tutors.Length; j++)
|
||||
Tutors[j] = ((TutorData[j / 8] >> (j % 8)) & 0x1) == 1; //Bitflags for Tutors
|
||||
|
||||
if (br.BaseStream.Length - br.BaseStream.Position == 0x10) // ORAS
|
||||
{
|
||||
byte[][] ORASTutorData =
|
||||
{
|
||||
br.ReadBytes(2), // 15
|
||||
br.ReadBytes(3), // 17
|
||||
br.ReadBytes(2), // 16
|
||||
br.ReadBytes(2), // 15
|
||||
};
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
ORASTutors[i] = new bool[8 * ORASTutorData[i].Length];
|
||||
for (int b = 0; b < 8 * ORASTutorData[i].Length; b++)
|
||||
ORASTutors[i][b] = ((ORASTutorData[i][b / 8] >> (b % 8)) & 0x1) == 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Data Manipulation
|
||||
public int FormeOffset;
|
||||
public int FormeIndex(int species, int forme)
|
||||
{
|
||||
return forme == 0 ? species : FormeOffset;
|
||||
}
|
||||
public int RandomGender
|
||||
{
|
||||
get
|
||||
{
|
||||
switch (Gender)
|
||||
{
|
||||
case 255: // Genderless
|
||||
return 2;
|
||||
case 254: // Female
|
||||
return 1;
|
||||
case 0: // Male
|
||||
return 0;
|
||||
default:
|
||||
return (int)Util.rnd32()%2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -52,9 +52,7 @@ namespace PKHeX
|
|||
public int g6trgend;
|
||||
private int getAbilityNumber(int species, int ability, int formnum)
|
||||
{
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(species, formnum);
|
||||
int[] spec_abilities = new int[3];
|
||||
Array.Copy(MonData.Abilities, spec_abilities, 3);
|
||||
byte[] spec_abilities = PKX.Personal[PKX.Personal[species].FormeIndex(species, formnum)].Abilities;
|
||||
int abilval = Array.IndexOf(spec_abilities, ability);
|
||||
if (abilval >= 0)
|
||||
return 1 << abilval;
|
||||
|
@ -126,8 +124,7 @@ namespace PKHeX
|
|||
}
|
||||
|
||||
// Gender Form Fateful
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(species);
|
||||
int genderratio = MonData.GenderRatio;
|
||||
int genderratio = PKX.Personal[species].Gender;
|
||||
uint PID = BitConverter.ToUInt32(pk4, 0);
|
||||
int gv = (int)(PID & 0xFF);
|
||||
int gender;
|
||||
|
|
|
@ -594,7 +594,7 @@ namespace PKHeX
|
|||
}
|
||||
#endregion
|
||||
#region Wondercard
|
||||
else if (input.Length == 0x108 && ext == ".wc6")
|
||||
else if (input.Length == 0x108 && ext == ".wc6")
|
||||
new SAV_Wondercard(input).Show();
|
||||
#endregion
|
||||
else
|
||||
|
@ -877,7 +877,7 @@ namespace PKHeX
|
|||
int[] ball_nums = { 7, 576, 13, 492, 497, 14, 495, 493, 496, 494, 11, 498, 8, 6, 12, 15, 9, 5, 499, 10, 1, 16 };
|
||||
int[] ball_vals = { 7, 25, 13, 17, 22, 14, 20, 18, 21, 19, 11, 23, 8, 6, 12, 15, 9, 5, 24, 10, 1, 16 };
|
||||
BallDataSource = Util.getVariedCBList(Util.getCBList(itemlist, new[] { 4 }, new[] { 3 }, new[] { 2 }, new[] { 1 }), itemlist, ball_nums, ball_vals);
|
||||
ItemDataSource = Util.getCBList(itemlist, (DEV_Ability.Enabled) ? null : Legal.Items_Held);
|
||||
ItemDataSource = Util.getCBList(itemlist, DEV_Ability.Enabled ? null : Legal.Items_Held);
|
||||
SpeciesDataSource = Util.getCBList(specieslist, null);
|
||||
NatureDataSource = Util.getCBList(natures, null);
|
||||
AbilityDataSource = Util.getCBList(abilitylist, null);
|
||||
|
@ -1094,8 +1094,7 @@ namespace PKHeX
|
|||
// Form Tables
|
||||
cb.DisplayMember = "Text";
|
||||
cb.ValueMember = "Value";
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(species);
|
||||
bool hasForms = !(MonData.AltFormCount == 0 && species != 664 && species != 665); // If no forms & not Scatterbug / Spewpa...
|
||||
bool hasForms = !(PKX.Personal[species].FormeCount == 1 && species != 664 && species != 665); // If no forms & not Scatterbug / Spewpa...
|
||||
cb.Enabled = cb.Visible = hasForms;
|
||||
if (l != null) l.Visible = hasForms;
|
||||
|
||||
|
@ -1191,8 +1190,7 @@ namespace PKHeX
|
|||
private void clickGender(object sender, EventArgs e)
|
||||
{
|
||||
// Get Gender Threshold
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(Util.getIndex(CB_Species));
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[Util.getIndex(CB_Species)].Gender;
|
||||
|
||||
if (gt == 255 || gt == 0 || gt == 254) // Single gender/genderless
|
||||
return;
|
||||
|
@ -1638,8 +1636,7 @@ namespace PKHeX
|
|||
|
||||
// Check for Gender Changes
|
||||
// Get Gender Threshold
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(Species);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[Species].Gender;
|
||||
int genderflag;
|
||||
|
||||
if (gt == 255) // Genderless
|
||||
|
|
Binary file not shown.
|
@ -377,8 +377,7 @@ namespace PKHeX
|
|||
{
|
||||
// Get Gender Threshold
|
||||
int species = Util.getIndex(CB_Species);
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(species);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[species].Gender;
|
||||
|
||||
if (gt == 255)
|
||||
Label_Gender.Text = gendersymbols[2];
|
||||
|
|
|
@ -86,8 +86,7 @@ namespace PKHeX
|
|||
CHK_P1.Enabled = true;
|
||||
|
||||
int index = LB_Species.SelectedIndex + 1;
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(index);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[index].Gender;
|
||||
|
||||
CHK_P2.Enabled = CHK_P4.Enabled = CHK_P6.Enabled = CHK_P8.Enabled = (gt != 254); // Not Female-Only
|
||||
CHK_P3.Enabled = CHK_P5.Enabled = CHK_P7.Enabled = CHK_P9.Enabled = (gt != 0) && (gt != 255); // Not Male-Only and Not Genderless
|
||||
|
@ -253,9 +252,7 @@ namespace PKHeX
|
|||
CHK_P1.Checked = ModifierKeys != Keys.Control;
|
||||
}
|
||||
int index = LB_Species.SelectedIndex+1;
|
||||
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(index);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[index].Gender;
|
||||
|
||||
CHK_P2.Checked = CHK_P4.Checked = (gt != 254) && ModifierKeys != Keys.Control;
|
||||
CHK_P3.Checked = CHK_P5.Checked = (gt != 0) && (gt != 255) && ModifierKeys != Keys.Control;
|
||||
|
|
|
@ -100,8 +100,7 @@ namespace PKHeX
|
|||
CHK_P1.Enabled = true;
|
||||
|
||||
int index = LB_Species.SelectedIndex + 1;
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(index);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[index].Gender;
|
||||
|
||||
CHK_P2.Enabled = CHK_P4.Enabled = CHK_P6.Enabled = CHK_P8.Enabled = (gt != 254); // Not Female-Only
|
||||
CHK_P3.Enabled = CHK_P5.Enabled = CHK_P7.Enabled = CHK_P9.Enabled = (gt != 0) && (gt != 255); // Not Male-Only and Not Genderless
|
||||
|
@ -284,8 +283,7 @@ namespace PKHeX
|
|||
CHK_F1.Checked = ModifierKeys != Keys.Control;
|
||||
}
|
||||
int index = LB_Species.SelectedIndex+1;
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(index);
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[index].Gender;
|
||||
|
||||
CHK_P2.Checked = CHK_P4.Checked = (gt != 254) && ModifierKeys != Keys.Control;
|
||||
CHK_P3.Checked = CHK_P5.Checked = (gt != 0) && (gt != 255) && ModifierKeys != Keys.Control;
|
||||
|
|
|
@ -426,8 +426,7 @@ namespace PKHeX
|
|||
|
||||
// Check for Gender Changes
|
||||
// Get Gender Threshold
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(Util.getIndex(CB_Species));
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[Util.getIndex(CB_Species)].Gender;
|
||||
|
||||
if (gt == 255) // Genderless
|
||||
genderflag = 2;
|
||||
|
@ -452,8 +451,7 @@ namespace PKHeX
|
|||
private void Label_Gender_Click(object sender, EventArgs e)
|
||||
{
|
||||
// Get Gender Threshold
|
||||
PKX.PersonalParser.Personal MonData = PKX.PersonalGetter.GetPersonal(Util.getIndex(CB_Species));
|
||||
int gt = MonData.GenderRatio;
|
||||
int gt = PKX.Personal[Util.getIndex(CB_Species)].Gender;
|
||||
|
||||
if (gt == 255 || gt == 0 || gt == 254) // Single gender/genderless
|
||||
return;
|
||||
|
|
Loading…
Reference in a new issue