mirror of
https://github.com/AdAstra-LD/DS-Pokemon-Rom-Editor.git
synced 2026-05-12 15:04:55 -05:00
539 lines
17 KiB
C#
539 lines
17 KiB
C#
using DSPRE.Resources;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Drawing;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using MessageBox = System.Windows.Forms.MessageBox;
|
|
|
|
namespace DSPRE {
|
|
public partial class LearnsetEditor : Form {
|
|
|
|
private PokemonEditor _parent;
|
|
private readonly string[] fileNames;
|
|
private readonly string[] pokenames;
|
|
private readonly string[] moveNames;
|
|
|
|
private bool editMode = false;
|
|
public bool dirty = false;
|
|
private int currentLoadedId = 0;
|
|
private LearnsetData currentLoadedFile = null;
|
|
|
|
private readonly string formName = "Learnset Editor";
|
|
|
|
private readonly string[] editButtonNames = new string[] {
|
|
"Edit",
|
|
"Confirm"
|
|
};
|
|
|
|
private readonly string[] deleteButtonNames = new string[] {
|
|
"Delete",
|
|
"Discard"
|
|
};
|
|
|
|
|
|
public LearnsetEditor(string[] moveNames, Control parent, PokemonEditor pokeEditor) {
|
|
|
|
InitializeComponent();
|
|
this.FormBorderStyle = FormBorderStyle.None;
|
|
this.Size = parent.Size;
|
|
this.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
|
|
|
|
Helpers.DisableHandlers();
|
|
|
|
this._parent = pokeEditor;
|
|
this.moveNames = moveNames;
|
|
this.pokenames = RomInfo.GetPokemonNames();
|
|
this.fileNames = GetFileNames();
|
|
|
|
InitDataRanges();
|
|
|
|
/* ---------------- */
|
|
|
|
descriptorLabel.Text = "";
|
|
statusLabel.Text = "";
|
|
|
|
ChangeLoadedFile(1);
|
|
|
|
Helpers.EnableHandlers();
|
|
}
|
|
|
|
private void InitDataRanges()
|
|
{
|
|
moveInputComboBox.DataSource = moveNames;
|
|
pokemonNameInputComboBox.DataSource = fileNames;
|
|
monNumberNumericUpDown.Minimum = 0;
|
|
monNumberNumericUpDown.Maximum = RomInfo.GetLearnsetFilesCount() - 1;
|
|
|
|
pokemonNameInputComboBox.SelectedIndex = 1;
|
|
monNumberNumericUpDown.Value = 1;
|
|
levelNumericUpDown.Value = 1;
|
|
|
|
}
|
|
|
|
private string[] GetFileNames()
|
|
{
|
|
|
|
int learnsetCount = RomInfo.GetLearnsetFilesCount();
|
|
|
|
List<string> fileNames = new List<string>(RomInfo.GetLearnsetFilesCount());
|
|
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);
|
|
}
|
|
|
|
for (int i = 0; i < learnsetCount - fileNames.Count; i++)
|
|
{
|
|
fileNames.Add($"Extra entry {fileNames.Count}");
|
|
}
|
|
|
|
return fileNames.ToArray();
|
|
}
|
|
|
|
public void ChangeLoadedFile(int learnsetID)
|
|
{
|
|
currentLoadedFile = new LearnsetData(learnsetID);
|
|
currentLoadedId = learnsetID;
|
|
|
|
monNumberNumericUpDown.Value = currentLoadedId;
|
|
pokemonNameInputComboBox.SelectedIndex = currentLoadedId;
|
|
|
|
UpdateMovesListFromFile();
|
|
UpdateEntryCountLabel();
|
|
UpdateButtonsOnMoveSelection();
|
|
UpdatePokePic();
|
|
UpdateAddEditStatus();
|
|
SetDirty(false);
|
|
}
|
|
|
|
private void UpdateMovesListFromFile()
|
|
{
|
|
movesListBox.BeginUpdate();
|
|
movesListBox.Items.Clear();
|
|
foreach (var elem in currentLoadedFile.list)
|
|
{
|
|
movesListBox.Items.Add(ElemToString(elem));
|
|
}
|
|
movesListBox.EndUpdate();
|
|
}
|
|
|
|
private void UpdateEntryCountLabel()
|
|
{
|
|
StringBuilder labelText = new StringBuilder("Entry Count: ");
|
|
labelText.Append(movesListBox.Items.Count);
|
|
|
|
if (movesListBox.Items.Count > LearnsetData.VanillaLimit)
|
|
{
|
|
labelText.Append("!");
|
|
entryCountLabel.ForeColor = Color.FromArgb(210, 120, 0);
|
|
entryCountLabel.Font = new Font(entryCountLabel.Font, FontStyle.Bold);
|
|
}
|
|
else
|
|
{
|
|
entryCountLabel.ForeColor = Color.Black;
|
|
entryCountLabel.Font = new Font(entryCountLabel.Font, FontStyle.Regular);
|
|
}
|
|
|
|
entryCountLabel.Text = labelText.ToString();
|
|
}
|
|
|
|
private void UpdatePokePic()
|
|
{
|
|
int excess = currentLoadedId - pokenames.Length;
|
|
int toLoad = currentLoadedId; // Default to the current ID
|
|
try
|
|
{
|
|
if (excess >= 0)
|
|
{
|
|
toLoad = PokeDatabase.PersonalData.personalExtraFiles[excess].iconId;
|
|
}
|
|
}
|
|
catch (IndexOutOfRangeException)
|
|
{
|
|
toLoad = 0;
|
|
}
|
|
finally
|
|
{
|
|
pokemonPictureBox.Image = DSUtils.GetPokePic(toLoad, pokemonPictureBox.Width, pokemonPictureBox.Height);
|
|
}
|
|
}
|
|
|
|
private void UpdateAddEditStatus()
|
|
{
|
|
(byte level, ushort move) newEntry = ((byte)levelNumericUpDown.Value, (ushort)moveInputComboBox.SelectedIndex);
|
|
|
|
if (currentLoadedFile == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
bool duplicate = currentLoadedFile.list.Contains(newEntry);
|
|
|
|
if (duplicate)
|
|
{
|
|
if (editMode)
|
|
{
|
|
editMoveButton.Enabled = false;
|
|
}
|
|
else
|
|
{
|
|
addMoveButton.Enabled = false;
|
|
}
|
|
statusLabel.Text = "Entry already exists!";
|
|
}
|
|
else
|
|
{
|
|
bool addable = IsValidEntry();
|
|
if (addable)
|
|
{
|
|
statusLabel.Text = "";
|
|
}
|
|
else
|
|
{
|
|
statusLabel.Text = "Invalid Move ID or Level!";
|
|
}
|
|
|
|
if (editMode)
|
|
{
|
|
editMoveButton.Enabled = addable;
|
|
}
|
|
else
|
|
{
|
|
addMoveButton.Enabled = addable;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SaveLearnsetData() {
|
|
if (currentLoadedFile == null) {
|
|
return;
|
|
}
|
|
currentLoadedFile.SaveToFileDefaultDir(currentLoadedId, false);
|
|
SetDirty(false);
|
|
}
|
|
|
|
private void SetDirty(bool status) {
|
|
if (status) {
|
|
dirty = true;
|
|
this.Text = formName + "*";
|
|
} else {
|
|
dirty = false;
|
|
this.Text = formName;
|
|
}
|
|
_parent.UpdateTabPageNames();
|
|
}
|
|
public bool CheckDiscardChanges()
|
|
{
|
|
if (!dirty) {
|
|
return true;
|
|
}
|
|
|
|
DialogResult res = MessageBox.Show(this,
|
|
"You have unsaved changes. Do you want to save them before switching Pokémon?",
|
|
"Learnset Editor - Unsaved changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
|
|
|
|
if (res == DialogResult.Yes)
|
|
{
|
|
SaveLearnsetData();
|
|
}
|
|
else if (res == DialogResult.Cancel)
|
|
{
|
|
monNumberNumericUpDown.Value = currentLoadedId;
|
|
pokemonNameInputComboBox.SelectedIndex = currentLoadedId;
|
|
return false; // Cancel the change
|
|
}
|
|
|
|
return true;
|
|
}
|
|
private string ElemToString((ushort level, ushort move) elem) {
|
|
return $"Lv. {elem.level}: {moveNames[elem.move]}";
|
|
}
|
|
private bool IsValidEntry()
|
|
{
|
|
return levelNumericUpDown.Value > 0 &&
|
|
moveInputComboBox.SelectedIndex > 0;
|
|
}
|
|
|
|
private void UpdateByEditMode()
|
|
{
|
|
int index = editMode == false ? 0 : 1;
|
|
editMoveButton.Text = editButtonNames[index];
|
|
deleteMoveButton.Text = deleteButtonNames[index];
|
|
}
|
|
|
|
private void UpdateButtonsOnMoveSelection()
|
|
{
|
|
int sel = movesListBox.SelectedIndex;
|
|
|
|
if (sel < 0)
|
|
{
|
|
editMoveButton.Enabled = false;
|
|
deleteMoveButton.Enabled = false;
|
|
moveUpButton.Enabled = false;
|
|
moveDownButton.Enabled = false;
|
|
return;
|
|
}
|
|
|
|
editMoveButton.Enabled = true;
|
|
deleteMoveButton.Enabled = true;
|
|
|
|
int moveLevel = currentLoadedFile.list[sel].level;
|
|
int previousLevel = sel > 0 ? currentLoadedFile.list[sel - 1].level : 0;
|
|
int nextLevel = sel < currentLoadedFile.list.Count - 1 ? currentLoadedFile.list[sel + 1].level : 255;
|
|
|
|
// Allow reordering only if the levels are the same
|
|
moveUpButton.Enabled = moveLevel == previousLevel;
|
|
moveDownButton.Enabled = moveLevel == nextLevel;
|
|
}
|
|
|
|
private int InsertEntrySafe(int level, int moveID)
|
|
{
|
|
if (currentLoadedFile == null || !IsValidEntry())
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
(byte level, ushort move) newEntry = ((byte)level, (ushort)moveID);
|
|
|
|
if (currentLoadedFile.list.Contains(newEntry))
|
|
{
|
|
MessageBox.Show(this, "This entry already exists!\nThis should not have happened.", "Learnset Editor - Duplicate Entry", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
AppLogger.Error("Learnset Editor: Attempted to insert a duplicate entry: " + newEntry);
|
|
return -1;
|
|
}
|
|
|
|
int index = currentLoadedFile.list.FindIndex(x => x.level > newEntry.level || (x.level == newEntry.level && x.move > newEntry.move));
|
|
|
|
if (index < 0)
|
|
{
|
|
currentLoadedFile.list.Add(newEntry);
|
|
return currentLoadedFile.list.Count - 1; // Add to the end if no larger entry is found
|
|
}
|
|
else
|
|
{
|
|
currentLoadedFile.list.Insert(index, newEntry);
|
|
return index; // Insert at the found index
|
|
}
|
|
|
|
}
|
|
|
|
private bool ShiftEntry(int index, int direction)
|
|
{
|
|
if (currentLoadedFile == null || index < 0 || index >= currentLoadedFile.list.Count)
|
|
{
|
|
return false; // Invalid index
|
|
}
|
|
|
|
int newIndex = index + direction;
|
|
if (newIndex < 0 || newIndex >= currentLoadedFile.list.Count)
|
|
{
|
|
return false; // Out of bounds
|
|
}
|
|
// Move the entry safely
|
|
SwapEntriesSafe(index, newIndex);
|
|
return true;
|
|
}
|
|
|
|
private bool SwapEntriesSafe(int indexA, int indexB)
|
|
{
|
|
if (currentLoadedFile == null || indexA < 0 || indexB < 0 || indexA >= currentLoadedFile.list.Count || indexB >= currentLoadedFile.list.Count)
|
|
{
|
|
return false; // Invalid indices
|
|
}
|
|
(byte level, ushort move) entryA = currentLoadedFile.list[indexA];
|
|
(byte level, ushort move) entryB = currentLoadedFile.list[indexB];
|
|
// Swap the entries
|
|
currentLoadedFile.list[indexA] = entryB;
|
|
currentLoadedFile.list[indexB] = entryA;
|
|
|
|
return true; // Successfully swapped
|
|
}
|
|
|
|
#region Event Handlers
|
|
private void saveDataButton_Click(object sender, EventArgs e) {
|
|
SaveLearnsetData();
|
|
}
|
|
|
|
private void pokemonNameInputComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Update();
|
|
|
|
this._parent.TrySyncIndices((ComboBox)sender);
|
|
Helpers.DisableHandlers();
|
|
if (CheckDiscardChanges())
|
|
{
|
|
ChangeLoadedFile(pokemonNameInputComboBox.SelectedIndex);
|
|
}
|
|
Helpers.EnableHandlers();
|
|
}
|
|
|
|
private void monNumberNumericUpDown_ValueChanged(object sender, EventArgs e) {
|
|
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
Update();
|
|
|
|
this._parent.TrySyncIndices((NumericUpDown)sender);
|
|
Helpers.DisableHandlers();
|
|
if (CheckDiscardChanges())
|
|
{
|
|
ChangeLoadedFile((int)monNumberNumericUpDown.Value);
|
|
}
|
|
Helpers.EnableHandlers();
|
|
}
|
|
|
|
private void moveInputComboBox_SelectedIndexChanged(object sender, EventArgs e) {
|
|
if (currentLoadedFile == null) {
|
|
return;
|
|
}
|
|
UpdateAddEditStatus();
|
|
descriptorLabel.Text = "Move ID: " + moveInputComboBox.SelectedIndex;
|
|
}
|
|
|
|
private void levelNumericUpDown_ValueChanged(object sender, EventArgs e) {
|
|
if (currentLoadedFile == null) {
|
|
return;
|
|
}
|
|
UpdateAddEditStatus();
|
|
}
|
|
|
|
private void addMoveButton_Click(object sender, EventArgs e) {
|
|
|
|
int index = InsertEntrySafe((byte)levelNumericUpDown.Value, (ushort)moveInputComboBox.SelectedIndex);
|
|
|
|
if (index < 0) {
|
|
return; // Insertion failed, likely due to invalid entry
|
|
}
|
|
|
|
UpdateMovesListFromFile();
|
|
movesListBox.SelectedIndex = index;
|
|
UpdateAddEditStatus();
|
|
SetDirty(true);
|
|
}
|
|
|
|
private void deleteMoveButton_Click(object sender, EventArgs e) {
|
|
|
|
if (currentLoadedFile == null) {
|
|
return;
|
|
}
|
|
|
|
int sel = movesListBox.SelectedIndex;
|
|
if (sel < 0) {
|
|
return;
|
|
}
|
|
|
|
if (editMode)
|
|
{
|
|
editMode = false;
|
|
movesListBox.Enabled = true;
|
|
UpdateButtonsOnMoveSelection();
|
|
}
|
|
else
|
|
{
|
|
currentLoadedFile.list.RemoveAt(sel);
|
|
movesListBox.Items.RemoveAt(sel);
|
|
|
|
int count = movesListBox.Items.Count;
|
|
if (count > 0) {
|
|
movesListBox.SelectedIndex = Math.Max(0, sel - 1);
|
|
}
|
|
|
|
UpdateEntryCountLabel();
|
|
}
|
|
|
|
UpdateByEditMode();
|
|
UpdateAddEditStatus();
|
|
SetDirty(true);
|
|
}
|
|
|
|
private void editMoveButton_Click(object sender, EventArgs e) {
|
|
int sel = movesListBox.SelectedIndex;
|
|
if (sel < 0) {
|
|
return;
|
|
}
|
|
|
|
if (editMode) {
|
|
(byte level, ushort move) newEntry = ((byte)levelNumericUpDown.Value, (ushort)moveInputComboBox.SelectedIndex);
|
|
|
|
int newSelection;
|
|
int oldLevel = currentLoadedFile.list[sel].level;
|
|
|
|
if (newEntry.level == oldLevel)
|
|
{
|
|
currentLoadedFile.list[sel] = newEntry;
|
|
movesListBox.Items[sel] = ElemToString(newEntry);
|
|
newSelection = sel;
|
|
}
|
|
else
|
|
{
|
|
currentLoadedFile.list.RemoveAt(sel);
|
|
newSelection = InsertEntrySafe(newEntry.level, newEntry.move);
|
|
UpdateMovesListFromFile();
|
|
}
|
|
|
|
UpdateEntryCountLabel();
|
|
movesListBox.SelectedIndex = newSelection;
|
|
editMode = false;
|
|
movesListBox.Enabled = true;
|
|
} else {
|
|
editMode = true;
|
|
movesListBox.Enabled = false;
|
|
moveUpButton.Enabled = false;
|
|
moveDownButton.Enabled = false;
|
|
|
|
editMoveButton.Text = editButtonNames[1];
|
|
deleteMoveButton.Text = deleteButtonNames[1];
|
|
|
|
(ushort level, ushort move) = currentLoadedFile.list[sel];
|
|
moveInputComboBox.SelectedIndex = move;
|
|
levelNumericUpDown.Value = level;
|
|
}
|
|
|
|
UpdateByEditMode();
|
|
UpdateAddEditStatus();
|
|
SetDirty(true);
|
|
}
|
|
|
|
private void movesListBox_SelectedIndexChanged(object sender, EventArgs e) {
|
|
UpdateButtonsOnMoveSelection();
|
|
}
|
|
|
|
private void moveUpButton_Click(object sender, EventArgs e)
|
|
{
|
|
int sel = movesListBox.SelectedIndex;
|
|
if (!ShiftEntry(sel, -1))
|
|
{
|
|
return;
|
|
}
|
|
UpdateMovesListFromFile();
|
|
movesListBox.SelectedIndex = sel-1;
|
|
SetDirty(true);
|
|
}
|
|
|
|
private void moveDownButton_Click(object sender, EventArgs e)
|
|
{
|
|
int sel = movesListBox.SelectedIndex;
|
|
if (!ShiftEntry(sel, 1))
|
|
{
|
|
return;
|
|
}
|
|
UpdateMovesListFromFile();
|
|
movesListBox.SelectedIndex = sel+1;
|
|
SetDirty(true);
|
|
}
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|