using DSPRE.Resources; using DSPRE.ROMFiles; using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Windows.Controls; using System.Windows.Forms; using static System.Windows.Forms.VisualStyles.VisualStyleElement.TextBox; namespace DSPRE { public partial class PersonalDataEditor : Form { private readonly string[] fileNames; private readonly string[] pokenames; private int currentLoadedId = 0; private PokemonPersonalData currentLoadedFile = null; private static bool dirty = false; private bool modifiedAbilities = false; private static readonly string formName = "Personal Data Editor"; PokemonEditor _parent; public PersonalDataEditor(string[] itemNames, string[] abilityNames, System.Windows.Forms.Control parent, PokemonEditor pokeEditor) { this.fileNames = RomInfo.GetPokemonNames().ToArray();; this._parent = pokeEditor; InitializeComponent(); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Size = parent.Size; this.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom; Helpers.DisableHandlers(); BindingList listItemNames = new BindingList(itemNames); item1InputComboBox.DataSource = new BindingSource(listItemNames, string.Empty); item2InputComboBox.DataSource = new BindingSource(listItemNames, string.Empty); BindingList listTypeNames = new BindingList(Enum.GetNames(typeof(PokemonType))); type1InputComboBox.DataSource = new BindingSource(listTypeNames, string.Empty); type2InputComboBox.DataSource = new BindingSource(listTypeNames, string.Empty); BindingList listAbilityNames = new BindingList(abilityNames); ability1InputComboBox.DataSource = new BindingSource(listAbilityNames, string.Empty); ability2InputComboBox.DataSource = new BindingSource(listAbilityNames, string.Empty); BindingList listEggGroups = new BindingList(Enum.GetNames(typeof(PokemonEggGroup))); eggGroup1InputCombobox.DataSource = new BindingSource(listEggGroups, string.Empty); eggGroup2InputCombobox.DataSource = new BindingSource(listEggGroups, string.Empty); growthCurveInputComboBox.Items.AddRange(Enum.GetNames(typeof(PokemonGrowthCurve))); dexColorInputComboBox.Items.AddRange(Enum.GetNames(typeof(PokemonDexColor))); /* ---------------- */ int count = RomInfo.GetPersonalFilesCount(); this.pokenames = RomInfo.GetPokemonNames(); List fileNames = new List(count); fileNames.AddRange(pokenames); for (int i = 0; i < PokeDatabase.PersonalData.personalExtraFiles.Length; i++) { PokeDatabase.PersonalData.PersonalExtraFiles altFormEntry = PokeDatabase.PersonalData.personalExtraFiles[i]; fileNames.Add(fileNames[altFormEntry.monId] + " - " + altFormEntry.description); } int extraEntries = fileNames.Count; for (int i = 0; i < count - extraEntries; i++) { fileNames.Add($"Extra entry {fileNames.Count}"); } this.fileNames = fileNames.ToArray(); monNumberNumericUpDown.Maximum = fileNames.Count - 1; pokemonNameInputComboBox.Items.AddRange(this.fileNames); /* ---------------- */ Helpers.EnableHandlers(); pokemonNameInputComboBox.SelectedIndex = 1; } private void setDirty(bool status) { if (status) { dirty = true; this.Text = formName + "*"; } else { dirty = false; this.Text = formName; } } private void baseHpNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseHP = (byte)baseHpNumericUpDown.Value; setDirty(true); } private void baseAtkNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseAtk = (byte)baseAtkNumericUpDown.Value; setDirty(true); } private void baseDefNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseDef = (byte)baseDefNumericUpDown.Value; setDirty(true); } private void baseSpAtkNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseSpAtk = (byte)baseSpAtkNumericUpDown.Value; setDirty(true); } private void baseSpDefNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseSpDef = (byte)baseSpDefNumericUpDown.Value; setDirty(true); } private void baseSpeedNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseSpeed = (byte)baseSpeedNumericUpDown.Value; setDirty(true); } private void evHpNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.evHP = (byte)evHpNumericUpDown.Value; setDirty(true); } private void evAtkNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.evAtk = (byte)evAtkNumericUpDown.Value; setDirty(true); } private void evDefNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.evDef = (byte)evDefNumericUpDown.Value; setDirty(true); } private void evSpAtkNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.evSpAtk = (byte)evSpAtkNumericUpDown.Value; setDirty(true); } private void evSpDefNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.evSpDef = (byte)evSpDefNumericUpDown.Value; setDirty(true); } private void evSpeedNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.evSpeed = (byte)evSpeedNumericUpDown.Value; setDirty(true); } private void type1InputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.type1 = (PokemonType)type1InputComboBox.SelectedIndex; setDirty(true); } private void type2InputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.type2 = (PokemonType)type2InputComboBox.SelectedIndex; setDirty(true); } private void growthCurveInputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.growthCurve = (PokemonGrowthCurve)growthCurveInputComboBox.SelectedIndex; setDirty(true); } private void baseExpYieldNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.givenExp = (byte)baseExpYieldNumericUpDown.Value; setDirty(true); } private void dexColorInputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.color = (PokemonDexColor)dexColorInputComboBox.SelectedIndex; setDirty(true); } private void flipFlagCheckBox_CheckedChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.flip = flipFlagCheckBox.Checked; setDirty(true); } private void escapeRateNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.escapeRate = (byte)escapeRateNumericUpDown.Value; setDirty(true); } private void catchRateNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.catchRate = (byte)catchRateNumericUpDown.Value; setDirty(true); } private void genderProbabilityNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.genderVec = (byte)genderProbabilityNumericUpDown.Value; genderLabel.Text = GetGenderText(currentLoadedFile.genderVec); setDirty(true); } private string GetGenderText(int vec) { switch (vec) { case (byte)PokemonGender.Male: case (byte)PokemonGender.Female: return $"100% {Enum.GetName(typeof(PokemonGender), vec)}"; case (byte)PokemonGender.Unknown: return "Gender Unknown"; default: { vec++; float femaleProb = 100 * ((float)vec / 256); return $"{100 - femaleProb}% Male\n\n{femaleProb}% Female"; } } } private void ability1InputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.firstAbility = (byte)ability1InputComboBox.SelectedIndex; setDirty(true); modifiedAbilities = true; } private void ability2InputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.secondAbility = (byte)ability2InputComboBox.SelectedIndex; setDirty(true); modifiedAbilities = true; } private void eggGroup1InputCombobox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.eggGroup1 = (byte)eggGroup1InputCombobox.SelectedIndex; setDirty(true); } private void eggGroup2InputCombobox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.eggGroup2 = (byte)eggGroup2InputCombobox.SelectedIndex; setDirty(true); } private void eggStepsNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.eggSteps = (byte)eggStepsNumericUpDown.Value; setDirty(true); } private void item1InputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.item1 = (ushort)item1InputComboBox.SelectedIndex; setDirty(true); } private void item2InputComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.item2 = (ushort)item2InputComboBox.SelectedIndex; setDirty(true); } private void baseFriendshipNumericUpDown_ValueChanged(object sender, EventArgs e) { if (Helpers.HandlersDisabled) { return; } currentLoadedFile.baseFriendship = (byte)baseFriendshipNumericUpDown.Value; setDirty(true); } private void addMachineButton_Click(object sender, EventArgs e) { int elemAdd = addableMachinesListBox.SelectedIndex; if (elemAdd < 0) { return; } int id = ZeroBasedIndexFromMachineName((string)addableMachinesListBox.SelectedItem); currentLoadedFile.machines.Add((byte)id); RebuildMachinesListBoxes(false, true); int count = addableMachinesListBox.Items.Count; if (count > 0) { addableMachinesListBox.SelectedIndex = Math.Min(count-1, elemAdd); } setDirty(true); } private void removeMachineButton_Click(object sender, EventArgs e) { int elemRemove = addedMachinesListBox.SelectedIndex; if (elemRemove < 0) { return; } int id = ZeroBasedIndexFromMachineName((string)addedMachinesListBox.SelectedItem); currentLoadedFile.machines.Remove((byte)id); RebuildMachinesListBoxes(true, false); int count = addedMachinesListBox.Items.Count; if (count > 0) { addedMachinesListBox.SelectedIndex = Math.Max(0, elemRemove - 1); } setDirty(true); } private void addAllMachinesButton_Click(object sender, EventArgs e) { int tot = PokemonPersonalData.tmsCount + PokemonPersonalData.hmsCount; if (currentLoadedFile.machines.Count == tot) { return; } currentLoadedFile.machines = new SortedSet(); for (byte i = 0; i < tot; i++) { currentLoadedFile.machines.Add(i); } RebuildMachinesListBoxes(); setDirty(true); } private void removeAllMachinesButton_Click(object sender, EventArgs e) { if (currentLoadedFile.machines.Count == 0) { return; } currentLoadedFile.machines.Clear(); RebuildMachinesListBoxes(); setDirty(true); } private void saveDataButton_Click(object sender, EventArgs e) { currentLoadedFile.SaveToFileDefaultDir(currentLoadedId, true); if (modifiedAbilities) { EditorPanels.MainProgram.RefreshAbilities(currentLoadedId); modifiedAbilities = false; } setDirty(false); } //------------------------------- public bool CheckDiscardChanges() { if (!dirty) { return true; } DialogResult res = MessageBox.Show("Personal Editor\nThere are unsaved changes to the current Personal data.\nDiscard and proceed?", "Personal Editor - Unsaved changes", MessageBoxButtons.YesNo, MessageBoxIcon.Question); if (res.Equals(DialogResult.Yes)) { return true; } monNumberNumericUpDown.Value = currentLoadedId; pokemonNameInputComboBox.SelectedIndex = currentLoadedId; return false; } private void pokemonNameInputComboBox_SelectedIndexChanged(object sender, EventArgs e) { Update(); if (Helpers.HandlersDisabled) { return; } this._parent.TrySyncIndices((System.Windows.Forms.ComboBox)sender); Helpers.DisableHandlers(); if (CheckDiscardChanges()) { int newNumber = pokemonNameInputComboBox.SelectedIndex; monNumberNumericUpDown.Value = newNumber; ChangeLoadedFile(newNumber); } Helpers.EnableHandlers(); } private void monNumberNumericUpDown_ValueChanged(object sender, EventArgs e) { Update(); if (Helpers.HandlersDisabled) { return; } this._parent.TrySyncIndices((NumericUpDown)sender); Helpers.DisableHandlers(); if (CheckDiscardChanges()) { int newNumber = (int)monNumberNumericUpDown.Value; pokemonNameInputComboBox.SelectedIndex = newNumber; ChangeLoadedFile(newNumber); } Helpers.EnableHandlers(); } public void ChangeLoadedFile(int toLoad) { currentLoadedId = toLoad; currentLoadedFile = new PokemonPersonalData(currentLoadedId); baseHpNumericUpDown.Value = currentLoadedFile.baseHP; baseAtkNumericUpDown.Value = currentLoadedFile.baseAtk; baseDefNumericUpDown.Value = currentLoadedFile.baseDef; baseSpeedNumericUpDown.Value = currentLoadedFile.baseSpeed; baseSpAtkNumericUpDown.Value = currentLoadedFile.baseSpAtk; baseSpDefNumericUpDown.Value = currentLoadedFile.baseSpDef; type1InputComboBox.SelectedIndex = (byte)currentLoadedFile.type1; type2InputComboBox.SelectedIndex = (byte)currentLoadedFile.type2; catchRateNumericUpDown.Value = currentLoadedFile.catchRate; baseExpYieldNumericUpDown.Value = currentLoadedFile.givenExp; evHpNumericUpDown.Value = currentLoadedFile.evHP; evAtkNumericUpDown.Value = currentLoadedFile.evAtk; evDefNumericUpDown.Value = currentLoadedFile.evDef; evSpeedNumericUpDown.Value = currentLoadedFile.evSpeed; evSpAtkNumericUpDown.Value = currentLoadedFile.evSpAtk; evSpDefNumericUpDown.Value = currentLoadedFile.evSpDef; item1InputComboBox.SelectedIndex = currentLoadedFile.item1; item2InputComboBox.SelectedIndex = currentLoadedFile.item2; genderProbabilityNumericUpDown.Value = currentLoadedFile.genderVec; eggStepsNumericUpDown.Value = currentLoadedFile.eggSteps; baseFriendshipNumericUpDown.Value = currentLoadedFile.baseFriendship; growthCurveInputComboBox.SelectedIndex = (byte)currentLoadedFile.growthCurve; eggGroup1InputCombobox.SelectedIndex = currentLoadedFile.eggGroup1; eggGroup2InputCombobox.SelectedIndex = currentLoadedFile.eggGroup2; ability1InputComboBox.SelectedIndex = currentLoadedFile.firstAbility; ability2InputComboBox.SelectedIndex = currentLoadedFile.secondAbility; escapeRateNumericUpDown.Value = currentLoadedFile.escapeRate; dexColorInputComboBox.SelectedIndex = (byte)currentLoadedFile.color; flipFlagCheckBox.Checked = currentLoadedFile.flip; genderLabel.Text = GetGenderText(currentLoadedFile.genderVec); RebuildMachinesListBoxes(); int excess = toLoad - pokenames.Length; try { if (excess >= 0) { toLoad = PokeDatabase.PersonalData.personalExtraFiles[excess].iconId; } } catch (IndexOutOfRangeException) { toLoad = 0; } finally { pokemonPictureBox.Image = DSUtils.GetPokePic(toLoad, pokemonPictureBox.Width, pokemonPictureBox.Height); } setDirty(false); } private void RebuildMachinesListBoxes(bool keepAddableSelection = true, bool keepAddedSelection = true) { addableMachinesListBox.BeginUpdate(); addedMachinesListBox.BeginUpdate(); string addableSel = null; if (keepAddableSelection) { addableSel = (string)addableMachinesListBox.SelectedItem; } string addedSel = null; if (keepAddedSelection) { addedSel = (string)addableMachinesListBox.SelectedItem; } addedMachinesListBox.Items.Clear(); addableMachinesListBox.Items.Clear(); int dataIndex = 0; byte tot = (byte)(PokemonPersonalData.tmsCount + PokemonPersonalData.hmsCount); for (byte i = 0; i < tot; i++) { string currentItem = MachineNameFromZeroBasedIndex(i); if (dataIndex < currentLoadedFile.machines.Count && currentLoadedFile.machines.Contains(i)) { addedMachinesListBox.Items.Add(currentItem); dataIndex++; } else { addableMachinesListBox.Items.Add(currentItem); } } addableMachinesListBox.EndUpdate(); addedMachinesListBox.EndUpdate(); if (keepAddableSelection) { int addableCount = addableMachinesListBox.Items.Count; if (addableCount > 0) { addableMachinesListBox.SelectedItem = addableSel; } } int addedCount = addedMachinesListBox.Items.Count; if (addedCount > 0) { addedMachinesListBox.SelectedItem = addedSel; } } private static string MachineNameFromZeroBasedIndex(int n) { //0-91 --> TMs //>=92 --> HM n += 1; int diff = n - PokemonPersonalData.tmsCount; string item = diff > 0 ? "HM " + diff : "TM " + n; return item; } private static int ZeroBasedIndexFromMachineName(string machineName) { // Split the machineName to get the prefix (TM or HM) and the number string[] parts = machineName.Split(' '); if (parts.Length == 2) { // Check if the first part is "TM" (case-insensitive) bool isTM = parts[0].Equals("TM", StringComparison.OrdinalIgnoreCase); if (isTM || parts[0].Equals("HM", StringComparison.OrdinalIgnoreCase)) { if (int.TryParse(parts[1], out int number)) { number--; // Calculate the index based on the prefix (TM or HM) int index = isTM ? number : number + PokemonPersonalData.tmsCount; return index; } } } // Return -1 to indicate an invalid input or failure to parse return -1; } } }