pk3DS/pk3DS.WinForms/Subforms/Gen7/PersonalEditor7.cs
2024-06-02 18:30:56 -05:00

488 lines
19 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Media;
using System.Text;
using System.Windows.Forms;
using pk3DS.Core.Structures.PersonalInfo;
using pk3DS.Core;
using pk3DS.Core.Randomizers;
namespace pk3DS.WinForms;
public partial class PersonalEditor7 : Form
{
public PersonalEditor7(byte[][] infiles)
{
InitializeComponent();
helditem_boxes = [CB_HeldItem1, CB_HeldItem2, CB_HeldItem3];
ability_boxes = [CB_Ability1, CB_Ability2, CB_Ability3];
typing_boxes = [CB_Type1, CB_Type2];
eggGroup_boxes = [CB_EggGroup1, CB_EggGroup2];
byte_boxes = [TB_BaseHP, TB_BaseATK, TB_BaseDEF, TB_BaseSPA, TB_BaseSPD, TB_BaseSPE, TB_Gender, TB_HatchCycles, TB_Friendship, TB_CatchRate, TB_CallRate,
];
ev_boxes = [TB_HPEVs, TB_ATKEVs, TB_DEFEVs, TB_SPEEVs, TB_SPAEVs, TB_SPDEVs];
rstat_boxes = [CHK_rHP, CHK_rATK, CHK_rDEF, CHK_rSPA, CHK_rSPD, CHK_rSPE];
files = infiles;
species[0] = "---";
abilities[0] = items[0] = moves[0] = "";
var altForms = Main.Config.Personal.GetFormList(species, Main.Config.MaxSpeciesID);
entryNames = Main.Config.Personal.GetPersonalEntryList(altForms, species, Main.Config.MaxSpeciesID, out baseForms, out formVal);
TMs = TMEditor7.GetTMHMList();
Setup();
CB_Species.SelectedIndex = 1;
RandSettings.GetFormSettings(this, TP_Randomizer.Controls);
}
#region Global Variables
private readonly byte[][] files;
private readonly string[] items = Main.Config.GetText(TextName.ItemNames);
private readonly string[] moves = Main.Config.GetText(TextName.MoveNames);
private readonly string[] species = Main.Config.GetText(TextName.SpeciesNames);
private readonly string[] abilities = Main.Config.GetText(TextName.AbilityNames);
//private readonly string[] forms = Main.Config.GetText(TextName.Forms);
private readonly string[] types = Main.Config.GetText(TextName.Types);
private readonly string[] entryNames;
private readonly ComboBox[] helditem_boxes;
private readonly ComboBox[] ability_boxes;
private readonly ComboBox[] typing_boxes;
private readonly ComboBox[] eggGroup_boxes;
private readonly MaskedTextBox[] byte_boxes;
private readonly MaskedTextBox[] ev_boxes;
private readonly CheckBox[] rstat_boxes;
private readonly string[] eggGroups = ["---", "Monster", "Water 1", "Bug", "Flying", "Field", "Fairy", "Grass", "Human-Like", "Water 3", "Mineral", "Amorphous", "Water 2", "Ditto", "Dragon", "Undiscovered",
];
private readonly string[] EXPGroups = ["Medium-Fast", "Erratic", "Fluctuating", "Medium-Slow", "Fast", "Slow"];
private readonly string[] colors = ["Red", "Blue", "Yellow", "Green", "Black", "Brown", "Purple", "Gray", "White", "Pink",
];
private readonly ushort[] tutormoves = [520, 519, 518, 338, 307, 308, 434, 620];
internal static readonly int[] Tutors_USUM =
[
450, 343, 162, 530, 324, 442, 402, 529, 340, 067, 441, 253, 009, 007, 008,
277, 335, 414, 492, 356, 393, 334, 387, 276, 527, 196, 401, 428, 406, 304, 231,
020, 173, 282, 235, 257, 272, 215, 366, 143, 220, 202, 409, 264, 351, 352,
380, 388, 180, 495, 270, 271, 478, 472, 283, 200, 278, 289, 446, 285,
477, 502, 432, 710, 707, 675, 673,
];
private readonly int[] baseForms, formVal;
private readonly ushort[] TMs;
private int entry = -1;
#endregion
private void Setup()
{
CLB_TM.Items.Clear();
if (TMs.Length == 0) // No ExeFS to grab TMs from.
{
for (int i = 1; i <= 100; i++)
CLB_TM.Items.Add($"TM{i:00}");
}
else // Use TM moves.
{
for (int i = 1; i <= 100; i++)
CLB_TM.Items.Add($"TM{i:00} {moves[TMs[i - 1]]}");
}
foreach (ushort m in tutormoves)
CLB_MoveTutors.Items.Add(moves[m]);
for (int i = 0; i < entryNames.Length; i++)
CB_Species.Items.Add($"{entryNames[i]} - {i:000}");
foreach (ComboBox cb in helditem_boxes)
{
cb.Items.AddRange(items);
}
CB_ZItem.Items.AddRange(items);
CB_ZBaseMove.Items.AddRange(moves);
CB_ZMove.Items.AddRange(moves);
foreach (ComboBox cb in ability_boxes)
{
cb.Items.AddRange(abilities);
}
foreach (ComboBox cb in typing_boxes)
{
cb.Items.AddRange(types);
}
foreach (ComboBox cb in eggGroup_boxes)
{
cb.Items.AddRange(eggGroups);
}
CB_Color.Items.AddRange(colors);
CB_EXPGroup.Items.AddRange(EXPGroups);
if (Main.Config.USUM)
{
foreach (var tutor in Tutors_USUM)
CLB_BeachTutors.Items.Add(moves[tutor]);
}
// toggle usum content
CHK_BeachTutors.Checked = CHK_BeachTutors.Visible =
CLB_BeachTutors.Visible = CLB_BeachTutors.Enabled = L_BeachTutors.Visible = Main.Config.USUM;
}
private void CB_Species_SelectedIndexChanged(object sender, EventArgs e)
{
if (entry > -1 && !dumping) SaveEntry();
entry = CB_Species.SelectedIndex;
ReadEntry();
}
private void ByteLimiter(object sender, EventArgs e)
{
if (sender is not MaskedTextBox mtb)
return;
_ = int.TryParse(mtb.Text, out int val);
if (Array.IndexOf(byte_boxes, mtb) > -1 && val > 255)
mtb.Text = "255";
else if (Array.IndexOf(ev_boxes, mtb) > -1 && val > 3)
mtb.Text = "3";
}
private PersonalInfo pkm;
private void ReadInfo()
{
pkm = Main.SpeciesStat[entry];
TB_BaseHP.Text = pkm.HP.ToString("000");
TB_BaseATK.Text = pkm.ATK.ToString("000");
TB_BaseDEF.Text = pkm.DEF.ToString("000");
TB_BaseSPE.Text = pkm.SPE.ToString("000");
TB_BaseSPA.Text = pkm.SPA.ToString("000");
TB_BaseSPD.Text = pkm.SPD.ToString("000");
TB_HPEVs.Text = pkm.EV_HP.ToString("0");
TB_ATKEVs.Text = pkm.EV_ATK.ToString("0");
TB_DEFEVs.Text = pkm.EV_DEF.ToString("0");
TB_SPEEVs.Text = pkm.EV_SPE.ToString("0");
TB_SPAEVs.Text = pkm.EV_SPA.ToString("0");
TB_SPDEVs.Text = pkm.EV_SPD.ToString("0");
CB_Type1.SelectedIndex = pkm.Types[0];
CB_Type2.SelectedIndex = pkm.Types[1];
TB_CatchRate.Text = pkm.CatchRate.ToString("000");
TB_Stage.Text = pkm.EvoStage.ToString("0");
CB_HeldItem1.SelectedIndex = pkm.Items[0];
CB_HeldItem2.SelectedIndex = pkm.Items[1];
CB_HeldItem3.SelectedIndex = pkm.Items[2];
TB_Gender.Text = pkm.Gender.ToString("000");
TB_HatchCycles.Text = pkm.HatchCycles.ToString("000");
TB_Friendship.Text = pkm.BaseFriendship.ToString("000");
CB_EXPGroup.SelectedIndex = pkm.EXPGrowth;
CB_EggGroup1.SelectedIndex = pkm.EggGroups[0];
CB_EggGroup2.SelectedIndex = pkm.EggGroups[1];
CB_Ability1.SelectedIndex = pkm.Abilities[0];
CB_Ability2.SelectedIndex = pkm.Abilities[1];
CB_Ability3.SelectedIndex = pkm.Abilities[2];
TB_FormeCount.Text = pkm.FormeCount.ToString("000");
TB_FormeSprite.Text = pkm.FormeSprite.ToString("000");
TB_RawColor.Text = pkm.Color.ToString("000");
CB_Color.SelectedIndex = pkm.Color & 0xF;
TB_BaseExp.Text = pkm.BaseEXP.ToString("000");
TB_BST.Text = pkm.BST.ToString("000");
TB_Height.Text = ((decimal)pkm.Height / 100).ToString("00.00");
TB_Weight.Text = ((decimal)pkm.Weight / 10).ToString("000.0");
for (int i = 0; i < CLB_TM.Items.Count; i++)
CLB_TM.SetItemChecked(i, pkm.TMHM[i]); // Bitflags for TM
for (int i = 0; i < CLB_MoveTutors.Items.Count; i++)
CLB_MoveTutors.SetItemChecked(i, pkm.TypeTutors[i]); // Bitflags for Tutors
if (Main.Config.SM || Main.Config.USUM)
{
PersonalInfoSM sm = (PersonalInfoSM)pkm;
TB_CallRate.Text = sm.EscapeRate.ToString("000");
CB_ZItem.SelectedIndex = sm.SpecialZ_Item;
CB_ZBaseMove.SelectedIndex = sm.SpecialZ_BaseMove;
CB_ZMove.SelectedIndex = sm.SpecialZ_ZMove;
CHK_Variant.Checked = sm.LocalVariant;
}
var special = pkm.SpecialTutors;
if (special.Length > 0)
{
for (int b = 0; b < CLB_BeachTutors.Items.Count; b++)
CLB_BeachTutors.SetItemChecked(b, special[0][b]);
}
}
private void ReadEntry()
{
ReadInfo();
if (dumping) return;
int s = baseForms[entry];
int f = formVal[entry];
if (entry <= Main.Config.MaxSpeciesID)
s = entry;
var rawImg = WinFormsUtil.GetSprite(s, f, 0, 0, Main.Config);
var bigImg = new Bitmap(rawImg.Width * 2, rawImg.Height * 2);
for (int x = 0; x < rawImg.Width; x++)
{
for (int y = 0; y < rawImg.Height; y++)
{
Color c = rawImg.GetPixel(x, y);
bigImg.SetPixel(2 * x, 2 * y, c);
bigImg.SetPixel((2 * x) + 1, 2 * y, c);
bigImg.SetPixel(2 * x, (2 * y) + 1, c);
bigImg.SetPixel((2 * x) + 1, (2 * y) + 1, c);
}
}
PB_MonSprite.Image = bigImg;
}
private void SavePersonal()
{
pkm.HP = Convert.ToByte(TB_BaseHP.Text);
pkm.ATK = Convert.ToByte(TB_BaseATK.Text);
pkm.DEF = Convert.ToByte(TB_BaseDEF.Text);
pkm.SPE = Convert.ToByte(TB_BaseSPE.Text);
pkm.SPA = Convert.ToByte(TB_BaseSPA.Text);
pkm.SPD = Convert.ToByte(TB_BaseSPD.Text);
pkm.EV_HP = Convert.ToByte(TB_HPEVs.Text);
pkm.EV_ATK = Convert.ToByte(TB_ATKEVs.Text);
pkm.EV_DEF = Convert.ToByte(TB_DEFEVs.Text);
pkm.EV_SPE = Convert.ToByte(TB_SPEEVs.Text);
pkm.EV_SPA = Convert.ToByte(TB_SPAEVs.Text);
pkm.EV_SPD = Convert.ToByte(TB_SPDEVs.Text);
pkm.CatchRate = Convert.ToByte(TB_CatchRate.Text);
pkm.EvoStage = Convert.ToByte(TB_Stage.Text);
pkm.Types = [CB_Type1.SelectedIndex, CB_Type2.SelectedIndex];
pkm.Items = [CB_HeldItem1.SelectedIndex, CB_HeldItem2.SelectedIndex, CB_HeldItem3.SelectedIndex];
pkm.Gender = Convert.ToByte(TB_Gender.Text);
pkm.HatchCycles = Convert.ToByte(TB_HatchCycles.Text);
pkm.BaseFriendship = Convert.ToByte(TB_Friendship.Text);
pkm.EXPGrowth = (byte)CB_EXPGroup.SelectedIndex;
pkm.EggGroups = [CB_EggGroup1.SelectedIndex, CB_EggGroup2.SelectedIndex];
pkm.Abilities = [CB_Ability1.SelectedIndex, CB_Ability2.SelectedIndex, CB_Ability3.SelectedIndex];
pkm.FormeSprite = Convert.ToUInt16(TB_FormeSprite.Text);
pkm.FormeCount = Convert.ToByte(TB_FormeCount.Text);
pkm.Color = (byte)(Convert.ToByte(CB_Color.SelectedIndex) | (Convert.ToByte(TB_RawColor.Text) & 0xF0));
pkm.BaseEXP = Convert.ToUInt16(TB_BaseExp.Text);
_ = decimal.TryParse(TB_Height.Text, out var h);
_ = decimal.TryParse(TB_Weight.Text, out var w);
pkm.Height = (int)(h * 100);
pkm.Weight = (int)(w * 10);
for (int i = 0; i < CLB_TM.Items.Count; i++)
pkm.TMHM[i] = CLB_TM.GetItemChecked(i);
for (int t = 0; t < CLB_MoveTutors.Items.Count; t++)
pkm.TypeTutors[t] = CLB_MoveTutors.GetItemChecked(t);
if (Main.Config.SM || Main.Config.USUM)
{
pkm.EscapeRate = Convert.ToByte(TB_CallRate.Text);
PersonalInfoSM sm = (PersonalInfoSM)pkm;
sm.SpecialZ_Item = CB_ZItem.SelectedIndex;
sm.SpecialZ_BaseMove = CB_ZBaseMove.SelectedIndex;
sm.SpecialZ_ZMove = CB_ZMove.SelectedIndex;
sm.LocalVariant = CHK_Variant.Checked;
}
var special = pkm.SpecialTutors;
if (special.Length > 0)
{
for (int b = 0; b < CLB_BeachTutors.Items.Count; b++)
special[0][b] = CLB_BeachTutors.GetItemChecked(b);
pkm.SpecialTutors = special;
}
}
private void SaveEntry()
{
SavePersonal();
byte[] edits = pkm.Write();
files[entry] = edits;
}
private void B_Randomize_Click(object sender, EventArgs e)
{
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Randomize all? Cannot undo.", "Double check Randomization settings in the Enhancements tab.") != DialogResult.Yes)
return;
SaveEntry();
// input settings
var rnd = new PersonalRandomizer(Main.SpeciesStat, Main.Config)
{
TypeCount = CB_Type1.Items.Count,
ModifyCatchRate = CHK_CatchRate.Checked,
ModifyEggGroup = CHK_EggGroup.Checked,
ModifyStats = CHK_Stats.Checked,
ShuffleStats = CHK_Shuffle.Checked,
StatsToRandomize = rstat_boxes.Select(g => g.Checked).ToArray(),
ModifyAbilities = CHK_Ability.Checked,
ModifyLearnsetTM = CHK_TM.Checked,
ModifyLearnsetHM = false, // no HMs in Gen 7
ModifyLearnsetTypeTutors = CHK_Tutors.Checked,
ModifyLearnsetMoveTutors = Main.Config.USUM && CHK_BeachTutors.Checked,
ModifyTypes = CHK_Type.Checked,
ModifyHeldItems = CHK_Item.Checked,
SameTypeChance = NUD_TypePercent.Value,
SameEggGroupChance = NUD_Egg.Value,
StatDeviation = NUD_StatDev.Value,
AllowWonderGuard = CHK_WGuard.Checked,
};
rnd.Execute();
Main.SpeciesStat.Select(z => z.Write()).ToArray().CopyTo(files, 0);
ReadEntry();
WinFormsUtil.Alert("Randomized all Pokémon Personal data entries according to specification!", "Press the Dump All button to view the new Personal data!");
}
private void B_ModifyAll(object sender, EventArgs e)
{
if (WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Modify all? Cannot undo.", "Double check Modification settings in the Enhancements tab.") != DialogResult.Yes) return;
for (int i = 1; i < CB_Species.Items.Count; i++)
{
CB_Species.SelectedIndex = i; // Get new Species
if (CHK_NoEV.Checked)
{
for (int z = 0; z < 6; z++)
ev_boxes[z].Text = 0.ToString();
}
if (CHK_Growth.Checked)
CB_EXPGroup.SelectedIndex = 5;
if (CHK_EXP.Checked)
TB_BaseExp.Text = ((float)NUD_EXP.Value * (Convert.ToUInt16(TB_BaseExp.Text) / 100f)).ToString("000");
if (CHK_NoTutor.Checked)
{
foreach (int tm in CLB_TM.CheckedIndices)
CLB_TM.SetItemCheckState(tm, CheckState.Unchecked);
foreach (int mt in CLB_MoveTutors.CheckedIndices)
CLB_MoveTutors.SetItemCheckState(mt, CheckState.Unchecked);
foreach (int ao in CLB_BeachTutors.CheckedIndices)
CLB_BeachTutors.SetItemCheckState(ao, CheckState.Unchecked);
}
if (CHK_FullTMCompatibility.Checked)
{
for (int t = 0; t < CLB_TM.Items.Count; t++)
CLB_TM.SetItemCheckState(t, CheckState.Checked);
}
if (CHK_FullMoveTutorCompatibility.Checked)
{
for (int m = 0; m < CLB_MoveTutors.Items.Count; m++)
CLB_MoveTutors.SetItemCheckState(m, CheckState.Checked);
}
if (CHK_FullBeachTutorCompatibility.Checked)
{
for (int m = 0; m < CLB_BeachTutors.Items.Count; m++)
CLB_BeachTutors.SetItemCheckState(m, CheckState.Checked);
}
if (CHK_QuickHatch.Checked)
TB_HatchCycles.Text = 1.ToString();
if (CHK_CallRate.Checked)
TB_CallRate.Text = ((int)NUD_CallRate.Value).ToString();
if (CHK_CatchRateMod.Checked)
TB_CatchRate.Text = ((int)NUD_CatchRateMod.Value).ToString();
}
CB_Species.SelectedIndex = 1;
WinFormsUtil.Alert("Modified all Pokémon Personal data entries according to specification!", "Press the Dump All button to view the new Personal data!");
}
private bool dumping;
private void B_Dump_Click(object sender, EventArgs e)
{
if (DialogResult.Yes != WinFormsUtil.Prompt(MessageBoxButtons.YesNo, "Dump all Personal Entries to Text File?"))
return;
var sfd = new SaveFileDialog { FileName = "Personal Entries.txt", Filter = "Text File|*.txt" };
SystemSounds.Asterisk.Play();
if (sfd.ShowDialog() != DialogResult.OK)
return;
dumping = true;
List<string> lines = [];
for (int i = 0; i < CB_Species.Items.Count; i++)
{
CB_Species.SelectedIndex = i; // Get new Species
lines.Add("======");
lines.Add($"{entry} - {CB_Species.Text} (Stage: {TB_Stage.Text})");
lines.Add("======");
lines.Add($"Base Stats: {TB_BaseHP.Text}.{TB_BaseATK.Text}.{TB_BaseDEF.Text}.{TB_BaseSPA.Text}.{TB_BaseSPD.Text}.{TB_BaseSPE.Text} (BST: {pkm.BST})");
lines.Add($"EV Yield: {TB_HPEVs.Text}.{TB_ATKEVs.Text}.{TB_DEFEVs.Text}.{TB_SPAEVs.Text}.{TB_SPDEVs.Text}.{TB_SPEEVs.Text}");
lines.Add($"Abilities: {CB_Ability1.Text} (1) | {CB_Ability2.Text} (2) | {CB_Ability3.Text} (H)");
lines.Add(string.Format(CB_Type1.SelectedIndex != CB_Type2.SelectedIndex
? "Type: {0} / {1}"
: "Type: {0}", CB_Type1.Text, CB_Type2.Text));
lines.Add($"Item 1 (50%): {CB_HeldItem1.Text}");
lines.Add($"Item 2 (5%): {CB_HeldItem2.Text}");
lines.Add($"Item 3 (1%): {CB_HeldItem3.Text}");
lines.Add($"EXP Group: {CB_EXPGroup.Text}");
lines.Add(string.Format(CB_EggGroup1.SelectedIndex != CB_EggGroup2.SelectedIndex
? "Egg Group: {0} / {1}"
: "Egg Group: {0}", CB_EggGroup1.Text, CB_EggGroup2.Text));
lines.Add($"Hatch Cycles: {TB_HatchCycles.Text}");
lines.Add($"Height: {TB_Height.Text} m, Weight: {TB_Weight.Text} kg, Color: {CB_Color.Text}");
if (CB_ZBaseMove.SelectedIndex > 0)
lines.Add($"{CB_ZBaseMove.Text} + {CB_ZItem.Text} => {CB_ZMove.Text}");
lines.Add("");
}
string path = sfd.FileName;
File.WriteAllLines(path, lines, Encoding.Unicode);
dumping = false;
}
private void CHK_Stats_CheckedChanged(object sender, EventArgs e)
{
L_StatDev.Enabled = NUD_StatDev.Enabled = CHK_Stats.Checked;
CHK_rHP.Enabled = CHK_rATK.Enabled = CHK_rDEF.Enabled = CHK_rSPA.Enabled = CHK_rSPD.Enabled = CHK_rSPE.Enabled = CHK_Stats.Checked;
}
private void CHK_Ability_CheckedChanged(object sender, EventArgs e)
{
CHK_WGuard.Enabled = CHK_Ability.Checked;
if (!CHK_WGuard.Enabled)
CHK_WGuard.Checked = false;
}
private void Form_Closing(object sender, FormClosingEventArgs e)
{
if (entry > -1) SaveEntry();
RandSettings.SetFormSettings(this, TP_Randomizer.Controls);
}
}