mirror of
https://github.com/AdAstra-LD/DS-Pokemon-Rom-Editor.git
synced 2026-05-12 06:54:33 -05:00
1267 lines
55 KiB
C#
1267 lines
55 KiB
C#
using DSPRE.ROMFiles;
|
|
using Ekona.Images;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using static DSPRE.RomInfo;
|
|
using static DSPRE.ROMFiles.SpeciesFile;
|
|
using Images;
|
|
|
|
namespace DSPRE.Editors
|
|
{
|
|
public partial class TrainerEditor : UserControl
|
|
{
|
|
MainProgram _parent;
|
|
public bool trainerEditorIsReady { get; set; } = false;
|
|
public TrainerEditor()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
private List<ComboBox> partyPokemonComboboxList = new List<ComboBox>();
|
|
private List<ComboBox> partyItemsComboboxList = new List<ComboBox>();
|
|
private List<GroupBox> partyMovesGroupboxList = new List<GroupBox>();
|
|
private List<NumericUpDown> partyLevelUpdownList = new List<NumericUpDown>();
|
|
private List<ComboBox> partyGenderComboBoxList = new List<ComboBox>();
|
|
private List<ComboBox> partyAbilityComboBoxList = new List<ComboBox>();
|
|
private List<ComboBox> partyFormComboBoxList = new List<ComboBox>();
|
|
private List<NumericUpDown> partyIVUpdownList = new List<NumericUpDown>();
|
|
private List<NumericUpDown> partyBallUpdownList = new List<NumericUpDown>();
|
|
private List<GroupBox> partyGroupboxList = new List<GroupBox>();
|
|
private List<PictureBox> partyPokemonPictureBoxList = new List<PictureBox>();
|
|
private List<PictureBox> partyPokemonItemIconList = new List<PictureBox>();
|
|
|
|
private const int TRAINER_PARTY_POKEMON_GENDER_DEFAULT_INDEX = 0;
|
|
private const int TRAINER_PARTY_POKEMON_GENDER_MALE_INDEX = 1;
|
|
private const int TRAINER_PARTY_POKEMON_GENDER_FEMALE_INDEX = 2;
|
|
private const int TRAINER_PARTY_POKEMON_ABILITY_DEFAULT_INDEX = 0;
|
|
private const int TRAINER_PARTY_POKEMON_ABILITY_SLOT1_INDEX = 1;
|
|
private const int TRAINER_PARTY_POKEMON_ABILITY_SLOT2_INDEX = 2;
|
|
|
|
|
|
string[] abilityNames;
|
|
SpeciesFile[] pokemonSpecies;
|
|
|
|
private (int abi1, int abi2)[] pokemonSpeciesAbilities;
|
|
private List<(int monIdx, int moveIdx1, int moveIdx2)> duplicateMoves = new List<(int monIdx, int moveIdx1, int moveIdx2)>();
|
|
|
|
TrainerFile currentTrainerFile;
|
|
public PaletteBase trainerPal;
|
|
public ImageBase trainerTile;
|
|
public SpriteBase trainerSprite;
|
|
|
|
Dictionary<byte, (uint entryOffset, ushort musicD, ushort? musicN)> trainerClassEncounterMusicDict;
|
|
private void SetupTrainerClassEncounterMusicTable()
|
|
{
|
|
RomInfo.SetEncounterMusicTableOffsetToRAMAddress();
|
|
trainerClassEncounterMusicDict = new Dictionary<byte, (uint entryOffset, ushort musicD, ushort? musicN)>();
|
|
|
|
uint encounterMusicTableTableStartAddress = BitConverter.ToUInt32(ARM9.ReadBytes(RomInfo.encounterMusicTableOffsetToRAMAddress, 4), 0) - ARM9.address;
|
|
uint tableSizeOffset = 10;
|
|
if (gameFamily == GameFamilies.HGSS)
|
|
{
|
|
tableSizeOffset += 2;
|
|
encounterSSEQAltUpDown.Enabled = true;
|
|
}
|
|
|
|
byte tableEntriesCount = ARM9.ReadByte(RomInfo.encounterMusicTableOffsetToRAMAddress - tableSizeOffset);
|
|
using (ARM9.Reader ar = new ARM9.Reader(encounterMusicTableTableStartAddress))
|
|
{
|
|
for (int i = 0; i < tableEntriesCount; i++)
|
|
{
|
|
uint entryOffset = (uint)ar.BaseStream.Position;
|
|
byte tclass = (byte)ar.ReadUInt16();
|
|
ushort musicD = ar.ReadUInt16();
|
|
ushort? musicN = gameFamily == GameFamilies.HGSS ? ar.ReadUInt16() : (ushort?)null;
|
|
trainerClassEncounterMusicDict[tclass] = (entryOffset, musicD, musicN);
|
|
}
|
|
}
|
|
}
|
|
|
|
public void RefreshAbilities(int forPokemon)
|
|
{
|
|
DialogResult res = MessageBox.Show("You have modified a Pokemon's ability.\nDo you wish to refresh the Trainer Editor so your changes are available?", "Refresh Trainer Editor", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
|
|
if (res.Equals(DialogResult.Yes))
|
|
{
|
|
int currentIndex = trainerComboBox.SelectedIndex;
|
|
SetupTrainerEditor(_parent);
|
|
trainerComboBox.SelectedIndex = currentIndex;
|
|
}
|
|
}
|
|
|
|
public int LoadTrainerClassPic(int trClassID)
|
|
{
|
|
int paletteFileID = (trClassID * 5 + 1);
|
|
string paletteFilename = paletteFileID.ToString("D4");
|
|
trainerPal = new NCLR(gameDirs[DirNames.trainerGraphics].unpackedDir + "\\" + paletteFilename, paletteFileID, paletteFilename);
|
|
|
|
int tilesFileID = trClassID * 5;
|
|
string tilesFilename = tilesFileID.ToString("D4");
|
|
trainerTile = new NCGR(gameDirs[DirNames.trainerGraphics].unpackedDir + "\\" + tilesFilename, tilesFileID, tilesFilename);
|
|
|
|
if (gameFamily == GameFamilies.DP)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
int spriteFileID = (trClassID * 5 + 2);
|
|
string spriteFilename = spriteFileID.ToString("D4");
|
|
trainerSprite = new NCER(gameDirs[DirNames.trainerGraphics].unpackedDir + "\\" + spriteFilename, spriteFileID, spriteFilename);
|
|
|
|
return trainerSprite.Banks.Length - 1;
|
|
}
|
|
public void UpdateTrainerClassPic(PictureBox pb, int frameNumber = 0)
|
|
{
|
|
if (trainerSprite == null)
|
|
{
|
|
AppLogger.Error("Sprite is null!");
|
|
return;
|
|
}
|
|
|
|
int bank0OAMcount = trainerSprite.Banks[0].oams.Length;
|
|
int[] OAMenabled = new int[bank0OAMcount];
|
|
for (int i = 0; i < OAMenabled.Length; i++)
|
|
{
|
|
OAMenabled[i] = i;
|
|
}
|
|
|
|
frameNumber = Math.Min(trainerSprite.Banks.Length, frameNumber);
|
|
Image trSprite = trainerSprite.Get_Image(trainerTile, trainerPal, frameNumber, trainerClassPicBox.Width, trainerClassPicBox.Height, false, false, false, true, true, -1, OAMenabled);
|
|
pb.Image = trSprite;
|
|
pb.Update();
|
|
}
|
|
|
|
|
|
public void SetupTrainerEditor(MainProgram parent, bool force=false)
|
|
{
|
|
if (trainerEditorIsReady && !force) return;
|
|
|
|
trainerEditorIsReady = true;
|
|
_parent = parent;
|
|
Helpers.DisableHandlers();
|
|
|
|
//SetTrainerNameMaxLen();
|
|
SetupTrainerClassEncounterMusicTable();
|
|
/* Extract essential NARCs sub-archives*/
|
|
Helpers.statusLabelMessage("Setting up Trainer Editor...");
|
|
Update();
|
|
|
|
DSUtils.TryUnpackNarcs(new List<DirNames> {
|
|
DirNames.trainerProperties,
|
|
DirNames.trainerParty,
|
|
DirNames.trainerGraphics,
|
|
DirNames.textArchives,
|
|
DirNames.monIcons,
|
|
DirNames.personalPokeData,
|
|
DirNames.learnsets
|
|
});
|
|
|
|
int numPokemonSpecies = Directory.GetFiles(RomInfo.gameDirs[DirNames.personalPokeData].unpackedDir, "*").Count();
|
|
pokemonSpeciesAbilities = new (int abi1, int abi2)[numPokemonSpecies];
|
|
pokemonSpecies = new SpeciesFile[numPokemonSpecies];
|
|
|
|
RomInfo.SetMonIconsPalTableAddress();
|
|
RomInfo.SetAIBackportEnabled();
|
|
|
|
partyPokemonComboboxList.Clear();
|
|
partyPokemonComboboxList.Add(partyPokemon1ComboBox);
|
|
partyPokemonComboboxList.Add(partyPokemon2ComboBox);
|
|
partyPokemonComboboxList.Add(partyPokemon3ComboBox);
|
|
partyPokemonComboboxList.Add(partyPokemon4ComboBox);
|
|
partyPokemonComboboxList.Add(partyPokemon5ComboBox);
|
|
partyPokemonComboboxList.Add(partyPokemon6ComboBox);
|
|
|
|
partyItemsComboboxList.Clear();
|
|
partyItemsComboboxList.Add(partyItem1ComboBox);
|
|
partyItemsComboboxList.Add(partyItem2ComboBox);
|
|
partyItemsComboboxList.Add(partyItem3ComboBox);
|
|
partyItemsComboboxList.Add(partyItem4ComboBox);
|
|
partyItemsComboboxList.Add(partyItem5ComboBox);
|
|
partyItemsComboboxList.Add(partyItem6ComboBox);
|
|
|
|
partyLevelUpdownList.Clear();
|
|
partyLevelUpdownList.Add(partyLevel1UpDown);
|
|
partyLevelUpdownList.Add(partyLevel2UpDown);
|
|
partyLevelUpdownList.Add(partyLevel3UpDown);
|
|
partyLevelUpdownList.Add(partyLevel4UpDown);
|
|
partyLevelUpdownList.Add(partyLevel5UpDown);
|
|
partyLevelUpdownList.Add(partyLevel6UpDown);
|
|
|
|
partyGenderComboBoxList.Clear();
|
|
partyGenderComboBoxList.Add(partyGender1ComboBox);
|
|
partyGenderComboBoxList.Add(partyGender2ComboBox);
|
|
partyGenderComboBoxList.Add(partyGender3ComboBox);
|
|
partyGenderComboBoxList.Add(partyGender4ComboBox);
|
|
partyGenderComboBoxList.Add(partyGender5ComboBox);
|
|
partyGenderComboBoxList.Add(partyGender6ComboBox);
|
|
|
|
partyAbilityComboBoxList.Clear();
|
|
partyAbilityComboBoxList.Add(partyAbility1ComboBox);
|
|
partyAbilityComboBoxList.Add(partyAbility2ComboBox);
|
|
partyAbilityComboBoxList.Add(partyAbility3ComboBox);
|
|
partyAbilityComboBoxList.Add(partyAbility4ComboBox);
|
|
partyAbilityComboBoxList.Add(partyAbility5ComboBox);
|
|
partyAbilityComboBoxList.Add(partyAbility6ComboBox);
|
|
|
|
partyFormComboBoxList.Clear();
|
|
partyFormComboBoxList.Add(partyForm1ComboBox);
|
|
partyFormComboBoxList.Add(partyForm2ComboBox);
|
|
partyFormComboBoxList.Add(partyForm3ComboBox);
|
|
partyFormComboBoxList.Add(partyForm4ComboBox);
|
|
partyFormComboBoxList.Add(partyForm5ComboBox);
|
|
partyFormComboBoxList.Add(partyForm6ComboBox);
|
|
|
|
partyIVUpdownList.Clear();
|
|
partyIVUpdownList.Add(partyIV1UpDown);
|
|
partyIVUpdownList.Add(partyIV2UpDown);
|
|
partyIVUpdownList.Add(partyIV3UpDown);
|
|
partyIVUpdownList.Add(partyIV4UpDown);
|
|
partyIVUpdownList.Add(partyIV5UpDown);
|
|
partyIVUpdownList.Add(partyIV6UpDown);
|
|
|
|
partyBallUpdownList.Clear();
|
|
partyBallUpdownList.Add(partyBall1UpDown);
|
|
partyBallUpdownList.Add(partyBall2UpDown);
|
|
partyBallUpdownList.Add(partyBall3UpDown);
|
|
partyBallUpdownList.Add(partyBall4UpDown);
|
|
partyBallUpdownList.Add(partyBall5UpDown);
|
|
partyBallUpdownList.Add(partyBall6UpDown);
|
|
|
|
partyMovesGroupboxList.Clear();
|
|
partyMovesGroupboxList.Add(poke1MovesGroupBox);
|
|
partyMovesGroupboxList.Add(poke2MovesGroupBox);
|
|
partyMovesGroupboxList.Add(poke3MovesGroupBox);
|
|
partyMovesGroupboxList.Add(poke4MovesGroupBox);
|
|
partyMovesGroupboxList.Add(poke5MovesGroupBox);
|
|
partyMovesGroupboxList.Add(poke6MovesGroupBox);
|
|
|
|
partyGroupboxList.Clear();
|
|
partyGroupboxList.Add(party1GroupBox);
|
|
partyGroupboxList.Add(party2GroupBox);
|
|
partyGroupboxList.Add(party3GroupBox);
|
|
partyGroupboxList.Add(party4GroupBox);
|
|
partyGroupboxList.Add(party5GroupBox);
|
|
partyGroupboxList.Add(party6GroupBox);
|
|
|
|
partyPokemonPictureBoxList.Clear();
|
|
partyPokemonPictureBoxList.Add(partyPokemon1PictureBox);
|
|
partyPokemonPictureBoxList.Add(partyPokemon2PictureBox);
|
|
partyPokemonPictureBoxList.Add(partyPokemon3PictureBox);
|
|
partyPokemonPictureBoxList.Add(partyPokemon4PictureBox);
|
|
partyPokemonPictureBoxList.Add(partyPokemon5PictureBox);
|
|
partyPokemonPictureBoxList.Add(partyPokemon6PictureBox);
|
|
|
|
partyPokemonItemIconList.Clear();
|
|
partyPokemonItemIconList.Add(partyPokemonItemPictureBox1);
|
|
partyPokemonItemIconList.Add(partyPokemonItemPictureBox2);
|
|
partyPokemonItemIconList.Add(partyPokemonItemPictureBox3);
|
|
partyPokemonItemIconList.Add(partyPokemonItemPictureBox4);
|
|
partyPokemonItemIconList.Add(partyPokemonItemPictureBox5);
|
|
partyPokemonItemIconList.Add(partyPokemonItemPictureBox6);
|
|
|
|
int trainerCount = Directory.GetFiles(RomInfo.gameDirs[DirNames.trainerProperties].unpackedDir).Length;
|
|
trainerComboBox.Items.Clear();
|
|
trainerComboBox.Items.AddRange(Helpers.GetTrainerNames());
|
|
|
|
string[] classNames = RomInfo.GetTrainerClassNames();
|
|
trainerClassListBox.Items.Clear();
|
|
if (classNames.Length > byte.MaxValue + 1)
|
|
{
|
|
MessageBox.Show("There can't be more than 256 trainer classes! [Found " + classNames.Length + "].\nAborting.",
|
|
"Too many trainer classes", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
return;
|
|
}
|
|
for (int i = 0; i < classNames.Length; i++)
|
|
{
|
|
trainerClassListBox.Items.Add("[" + i.ToString("D3") + "]" + " " + classNames[i]);
|
|
}
|
|
|
|
for (int i = 0; i < numPokemonSpecies; i++)
|
|
{
|
|
pokemonSpecies[i] = new SpeciesFile(new FileStream(RomInfo.gameDirs[DirNames.personalPokeData].unpackedDir + "\\" + i.ToString("D4"), FileMode.Open));
|
|
}
|
|
|
|
if (gameFamily == GameFamilies.HGSS || RomInfo.AIBackportEnabled)
|
|
{
|
|
foreach (ComboBox partyGenderComboBox in partyGenderComboBoxList)
|
|
{
|
|
partyGenderComboBox.Visible = true;
|
|
partyGenderComboBox.Items.Add("Default Gender");
|
|
partyGenderComboBox.Items.Add("Male");
|
|
partyGenderComboBox.Items.Add("Female");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (ComboBox partyGenderComboBox in partyGenderComboBoxList)
|
|
{
|
|
partyGenderComboBox.Visible = false;
|
|
}
|
|
}
|
|
|
|
if (gameFamily == GameFamilies.DP)
|
|
{
|
|
foreach (ComboBox partyFormComboBox in partyFormComboBoxList)
|
|
{
|
|
partyFormComboBox.Visible = false;
|
|
}
|
|
|
|
foreach (NumericUpDown partyBallSealUpDown in partyBallUpdownList)
|
|
{
|
|
partyBallSealUpDown.Enabled = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
foreach (ComboBox partyFormComboBox in partyFormComboBoxList)
|
|
{
|
|
partyFormComboBox.Visible = true;
|
|
}
|
|
|
|
foreach (NumericUpDown partyBallSealUpDown in partyBallUpdownList)
|
|
{
|
|
partyBallSealUpDown.Enabled = true;
|
|
}
|
|
}
|
|
|
|
string[] itemNames = RomInfo.GetItemNames();
|
|
string[] pokeNames = RomInfo.GetPokemonNames();
|
|
string[] moveNames = RomInfo.GetAttackNames();
|
|
abilityNames = RomInfo.GetAbilityNames();
|
|
|
|
pokemonSpeciesAbilities = getPokemonAbilities(numPokemonSpecies);
|
|
|
|
foreach (Control c in trainerItemsGroupBox.Controls)
|
|
{
|
|
if (c is ComboBox)
|
|
{
|
|
(c as ComboBox).DataSource = new BindingSource(itemNames, string.Empty);
|
|
}
|
|
}
|
|
|
|
foreach (ComboBox CB in partyPokemonComboboxList)
|
|
{
|
|
CB.DataSource = new BindingSource(pokeNames, string.Empty);
|
|
}
|
|
|
|
foreach (ComboBox CB in partyItemsComboboxList)
|
|
{
|
|
CB.DataSource = new BindingSource(itemNames, string.Empty);
|
|
}
|
|
|
|
foreach (GroupBox movesGroup in partyMovesGroupboxList)
|
|
{
|
|
foreach (Control c in movesGroup.Controls)
|
|
{
|
|
if (c is ComboBox)
|
|
{
|
|
(c as ComboBox).DataSource = new BindingSource(moveNames, string.Empty);
|
|
}
|
|
}
|
|
}
|
|
|
|
trainerComboBox.SelectedIndex = 0;
|
|
|
|
Helpers.EnableHandlers();
|
|
trainerComboBox_SelectedIndexChanged(null, null);
|
|
Helpers.statusLabelMessage();
|
|
}
|
|
private void trainerComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
Helpers.DisableHandlers();
|
|
|
|
int currentIndex = trainerComboBox.SelectedIndex;
|
|
string suffix = "\\" + currentIndex.ToString("D4");
|
|
string[] trNames = RomInfo.GetSimpleTrainerNames();
|
|
|
|
bool error = currentIndex >= trNames.Length;
|
|
currentTrainerFile = new TrainerFile(
|
|
new TrainerProperties(
|
|
(ushort)trainerComboBox.SelectedIndex,
|
|
new FileStream(RomInfo.gameDirs[DirNames.trainerProperties].unpackedDir + suffix, FileMode.Open)
|
|
),
|
|
new FileStream(RomInfo.gameDirs[DirNames.trainerParty].unpackedDir + suffix, FileMode.Open),
|
|
error ? TrainerFile.NAME_NOT_FOUND : trNames[currentIndex]
|
|
);
|
|
RefreshTrainerPartyGUI();
|
|
RefreshTrainerPropertiesGUI();
|
|
|
|
UpdateDuplicateMovesList();
|
|
|
|
Helpers.EnableHandlers();
|
|
|
|
if (error)
|
|
{
|
|
MessageBox.Show("This Trainer File doesn't have a corresponding name.\n\n" +
|
|
"If you edited this ROM's Trainers with another tool before, don't worry.\n" +
|
|
"DSPRE will attempt to add the missing line to the Trainer Names Text Archive [" + RomInfo.trainerNamesMessageNumber + "] upon resaving.",
|
|
"Trainer name not found", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
}
|
|
|
|
public void RefreshTrainerPropertiesGUI()
|
|
{
|
|
trainerNameTextBox.Text = currentTrainerFile.name;
|
|
|
|
trainerClassListBox.SelectedIndex = currentTrainerFile.trp.trainerClass;
|
|
trainerDoubleCheckBox.Checked = currentTrainerFile.trp.doubleBattle;
|
|
trainerMovesCheckBox.Checked = currentTrainerFile.trp.chooseMoves;
|
|
trainerItemsCheckBox.Checked = currentTrainerFile.trp.chooseItems;
|
|
partyCountUpDown.Value = currentTrainerFile.trp.partyCount;
|
|
|
|
IList trainerItems = trainerItemsGroupBox.Controls;
|
|
for (int i = 0; i < trainerItems.Count; i++)
|
|
{
|
|
(trainerItems[i] as ComboBox).SelectedIndex = currentTrainerFile.trp.trainerItems[i];
|
|
}
|
|
|
|
IList trainerAI = TrainerAIGroupBox.Controls;
|
|
for (int i = 0; i < trainerAI.Count; i++)
|
|
{
|
|
(trainerAI[i] as CheckBox).Checked = currentTrainerFile.trp.AI[i];
|
|
}
|
|
}
|
|
public void RefreshTrainerPartyGUI()
|
|
{
|
|
for (int i = 0; i < TrainerFile.POKE_IN_PARTY; i++)
|
|
{
|
|
partyPokemonComboboxList[i].SelectedIndex = currentTrainerFile.party[i].pokeID ?? 0;
|
|
partyItemsComboboxList[i].SelectedIndex = currentTrainerFile.party[i].heldItem ?? 0;
|
|
partyLevelUpdownList[i].Value = Math.Max((ushort)1, currentTrainerFile.party[i].level);
|
|
partyIVUpdownList[i].Value = currentTrainerFile.party[i].difficulty;
|
|
partyBallUpdownList[i].Value = currentTrainerFile.party[i].ballSeals;
|
|
|
|
setTrainerPartyPokemonAbilities(i);
|
|
setTrainerPartyPokemonForm(i);
|
|
setTrainerPokemonGender(i);
|
|
|
|
if (currentTrainerFile.party[i].genderAndAbilityFlags.HasFlag(PartyPokemon.GenderAndAbilityFlags.ABILITY_SLOT1))
|
|
{
|
|
partyAbilityComboBoxList[i].SelectedIndex = TRAINER_PARTY_POKEMON_ABILITY_SLOT1_INDEX;
|
|
}
|
|
else if (currentTrainerFile.party[i].genderAndAbilityFlags.HasFlag(PartyPokemon.GenderAndAbilityFlags.ABILITY_SLOT2))
|
|
{
|
|
partyAbilityComboBoxList[i].SelectedIndex = TRAINER_PARTY_POKEMON_ABILITY_SLOT2_INDEX;
|
|
}
|
|
else
|
|
{
|
|
partyAbilityComboBoxList[i].SelectedIndex = TRAINER_PARTY_POKEMON_ABILITY_DEFAULT_INDEX;
|
|
}
|
|
|
|
partyFormComboBoxList[i].SelectedIndex = currentTrainerFile.party[i].formID;
|
|
|
|
if (currentTrainerFile.party[i].moves == null)
|
|
{
|
|
for (int j = 0; j < Party.MOVES_PER_POKE; j++)
|
|
{
|
|
(partyMovesGroupboxList[i].Controls[j] as ComboBox).SelectedIndex = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int j = 0; j < Party.MOVES_PER_POKE; j++)
|
|
{
|
|
(partyMovesGroupboxList[i].Controls[j] as ComboBox).SelectedIndex = currentTrainerFile.party[i].moves[j];
|
|
(partyMovesGroupboxList[i].Controls[j] as ComboBox).ForeColor = SystemColors.WindowText;
|
|
}
|
|
}
|
|
}
|
|
|
|
MarkDuplicateMoves();
|
|
|
|
}
|
|
|
|
private void ShowPartyPokemonPic(byte partyPos)
|
|
{
|
|
ComboBox cb = partyPokemonComboboxList[partyPos];
|
|
int species = cb.SelectedIndex > 0 ? cb.SelectedIndex : 0;
|
|
|
|
PictureBox pb = partyPokemonPictureBoxList[partyPos];
|
|
|
|
partyPokemonPictureBoxList[partyPos].Image = DSUtils.GetPokePic(species, pb.Width, pb.Height);
|
|
}
|
|
|
|
private void partyPokemon1ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
ShowPartyPokemonPic(0);
|
|
|
|
//event handler is called before currentTrainerFile is set, need to null check to avoid null object reference
|
|
if (currentTrainerFile != null)
|
|
{
|
|
setTrainerPartyPokemonAbilities(0);
|
|
setTrainerPartyPokemonForm(0);
|
|
setTrainerPokemonGender(0);
|
|
}
|
|
}
|
|
private void partyPokemon2ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
ShowPartyPokemonPic(1);
|
|
if (currentTrainerFile != null)
|
|
{
|
|
setTrainerPartyPokemonAbilities(1);
|
|
setTrainerPartyPokemonForm(1);
|
|
setTrainerPokemonGender(1);
|
|
}
|
|
}
|
|
|
|
private void partyPokemon3ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
ShowPartyPokemonPic(2);
|
|
if (currentTrainerFile != null)
|
|
{
|
|
setTrainerPartyPokemonAbilities(2);
|
|
setTrainerPartyPokemonForm(2);
|
|
setTrainerPokemonGender(2);
|
|
}
|
|
}
|
|
|
|
private void partyPokemon4ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
ShowPartyPokemonPic(3);
|
|
if (currentTrainerFile != null)
|
|
{
|
|
setTrainerPartyPokemonAbilities(3);
|
|
setTrainerPartyPokemonForm(3);
|
|
setTrainerPokemonGender(3);
|
|
}
|
|
}
|
|
|
|
private void partyPokemon5ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
ShowPartyPokemonPic(4);
|
|
if (currentTrainerFile != null)
|
|
{
|
|
setTrainerPartyPokemonAbilities(4);
|
|
setTrainerPartyPokemonForm(4);
|
|
setTrainerPokemonGender(4);
|
|
}
|
|
}
|
|
|
|
private void partyPokemon6ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
ShowPartyPokemonPic(5);
|
|
if (currentTrainerFile != null)
|
|
{
|
|
setTrainerPartyPokemonAbilities(5);
|
|
setTrainerPartyPokemonForm(5);
|
|
setTrainerPokemonGender(5);
|
|
}
|
|
}
|
|
|
|
private void showTrainerEditorItemPic(byte partyPos)
|
|
{
|
|
ComboBox cb = partyItemsComboboxList[partyPos];
|
|
partyPokemonItemIconList[partyPos].Visible = cb.SelectedIndex > 0;
|
|
}
|
|
|
|
private void partyItem1ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
showTrainerEditorItemPic(0);
|
|
}
|
|
|
|
private void partyItem2ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
showTrainerEditorItemPic(1);
|
|
}
|
|
|
|
private void partyItem3ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
showTrainerEditorItemPic(2);
|
|
}
|
|
|
|
private void partyItem4ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
showTrainerEditorItemPic(3);
|
|
}
|
|
|
|
private void partyItem5ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
showTrainerEditorItemPic(4);
|
|
}
|
|
|
|
private void partyItem6ComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
showTrainerEditorItemPic(5);
|
|
}
|
|
|
|
private void DVExplainButton_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
DVCalc DVCalcForm = new DVCalc(currentTrainerFile);
|
|
DVCalcForm.ShowDialog();
|
|
|
|
currentTrainerFile = DVCalcForm.trainerFile;
|
|
Helpers.DisableHandlers();
|
|
RefreshTrainerPartyGUI();
|
|
Helpers.EnableHandlers();
|
|
|
|
}
|
|
|
|
private void partyCountUpDown_ValueChanged(object sender, EventArgs e)
|
|
{
|
|
for (int i = 0; i < TrainerFile.POKE_IN_PARTY; i++)
|
|
{
|
|
partyGroupboxList[i].Enabled = (partyCountUpDown.Value > i);
|
|
partyPokemonPictureBoxList[i].Visible = partyGroupboxList[i].Enabled;
|
|
}
|
|
for (int i = Math.Min(currentTrainerFile.trp.partyCount, (int)partyCountUpDown.Value); i < TrainerFile.POKE_IN_PARTY; i++)
|
|
{
|
|
currentTrainerFile.party[i] = new PartyPokemon(currentTrainerFile.trp.chooseItems, currentTrainerFile.trp.chooseMoves);
|
|
}
|
|
}
|
|
|
|
private void trainerMovesCheckBox_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
for (int i = 0; i < TrainerFile.POKE_IN_PARTY; i++)
|
|
{
|
|
for (int j = 0; j < Party.MOVES_PER_POKE; j++)
|
|
{
|
|
(partyMovesGroupboxList[i].Controls[j] as ComboBox).Enabled = trainerMovesCheckBox.Checked;
|
|
}
|
|
if (trainerMovesCheckBox.Checked && i < currentTrainerFile.trp.partyCount && Helpers.HandlersEnabled)
|
|
{
|
|
Helpers.BackUpDisableHandler();
|
|
Helpers.DisableHandlers();
|
|
LearnsetData learnset = new LearnsetData((int)currentTrainerFile.party[i].pokeID);
|
|
int level = currentTrainerFile.party[i].level;
|
|
currentTrainerFile.party[i].moves = learnset.GetLearnsetAtLevel(level);
|
|
Debug.Print("Changing the moves of Pokemon " + i.ToString() + " which is Pokemon " + currentTrainerFile.party[i].pokeID);
|
|
Debug.Print("The new moves will be: " + string.Join(", ", currentTrainerFile.party[i].moves));
|
|
for (int j = 0; j < Party.MOVES_PER_POKE; j++)
|
|
{
|
|
(partyMovesGroupboxList[i].Controls[j] as ComboBox).SelectedIndex = currentTrainerFile.party[i].moves[j];
|
|
Debug.Print("Move for dropdwon " + j.ToString() + " is " + currentTrainerFile.party[i].moves[j].ToString());
|
|
}
|
|
Helpers.RestoreDisableHandler();
|
|
}
|
|
else
|
|
{
|
|
//currentTrainerFile.party[i].moves = null;
|
|
}
|
|
}
|
|
RefreshTrainerPartyGUI();
|
|
}
|
|
private void trainerItemsCheckBox_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
for (int i = 0; i < TrainerFile.POKE_IN_PARTY; i++)
|
|
{
|
|
partyItemsComboboxList[i].Enabled = trainerItemsCheckBox.Checked;
|
|
}
|
|
}
|
|
|
|
private void partyMoveComboBox_DropDown(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
((ComboBox)sender).ForeColor = SystemColors.WindowText;
|
|
}
|
|
|
|
private void partyMoveComboBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (Helpers.HandlersDisabled)
|
|
{
|
|
return;
|
|
}
|
|
|
|
MarkDuplicateMoves();
|
|
|
|
}
|
|
|
|
private void MarkDuplicateMoves()
|
|
{
|
|
foreach (var cbGroup in partyMovesGroupboxList)
|
|
{
|
|
foreach (var cb in cbGroup.Controls)
|
|
{
|
|
((ComboBox)cb).ForeColor = SystemColors.WindowText;
|
|
}
|
|
}
|
|
|
|
UpdateDuplicateMovesList();
|
|
|
|
foreach (var duplicate in duplicateMoves)
|
|
{
|
|
((ComboBox)partyMovesGroupboxList[duplicate.monIdx].Controls[duplicate.moveIdx1]).ForeColor = Color.Red;
|
|
((ComboBox)partyMovesGroupboxList[duplicate.monIdx].Controls[duplicate.moveIdx2]).ForeColor = Color.Red;
|
|
}
|
|
}
|
|
|
|
private void UpdateDuplicateMovesList()
|
|
{
|
|
duplicateMoves.Clear();
|
|
|
|
for (int pokemonIndex = 0; pokemonIndex < partyMovesGroupboxList.Count; pokemonIndex++)
|
|
{
|
|
for (int i = 0; i < Party.MOVES_PER_POKE - 1; i++)
|
|
{
|
|
for (int j = i + 1; j < Party.MOVES_PER_POKE; j++)
|
|
{
|
|
ComboBox cb1 = (ComboBox)partyMovesGroupboxList[pokemonIndex].Controls[i];
|
|
ComboBox cb2 = (ComboBox)partyMovesGroupboxList[pokemonIndex].Controls[j];
|
|
if (cb1.SelectedIndex != 0 && cb1.SelectedIndex == cb2.SelectedIndex)
|
|
{
|
|
duplicateMoves.Add((pokemonIndex, i, j));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void trainerSaveCurrentButton_Click(object sender, EventArgs e)
|
|
{
|
|
currentTrainerFile.trp.partyCount = (byte)partyCountUpDown.Value;
|
|
currentTrainerFile.trp.chooseMoves = trainerMovesCheckBox.Checked;
|
|
currentTrainerFile.trp.chooseItems = trainerItemsCheckBox.Checked;
|
|
currentTrainerFile.trp.doubleBattle = trainerDoubleCheckBox.Checked;
|
|
|
|
IList trainerItems = trainerItemsGroupBox.Controls;
|
|
for (int i = 0; i < trainerItems.Count; i++)
|
|
{
|
|
currentTrainerFile.trp.trainerItems[i] = (ushort)(trainerItems[i] as ComboBox).SelectedIndex;
|
|
}
|
|
|
|
IList trainerAI = TrainerAIGroupBox.Controls;
|
|
for (int i = 0; i < trainerAI.Count; i++)
|
|
{
|
|
currentTrainerFile.trp.AI[i] = (trainerAI[i] as CheckBox).Checked;
|
|
}
|
|
|
|
for (int i = 0; i < TrainerFile.POKE_IN_PARTY; i++)
|
|
{
|
|
currentTrainerFile.party[i].moves = trainerMovesCheckBox.Checked ? new ushort[4] : null;
|
|
}
|
|
|
|
|
|
for (int i = 0; i < partyCountUpDown.Value; i++)
|
|
{
|
|
currentTrainerFile.party[i].pokeID = (ushort)partyPokemonComboboxList[i].SelectedIndex;
|
|
currentTrainerFile.party[i].formID = (ushort)partyFormComboBoxList[i].SelectedIndex;
|
|
currentTrainerFile.party[i].level = (ushort)partyLevelUpdownList[i].Value;
|
|
|
|
if (trainerMovesCheckBox.Checked)
|
|
{
|
|
IList movesList = partyMovesGroupboxList[i].Controls;
|
|
for (int j = 0; j < Party.MOVES_PER_POKE; j++)
|
|
{
|
|
currentTrainerFile.party[i].moves[j] = (ushort)(movesList[j] as ComboBox).SelectedIndex;
|
|
}
|
|
}
|
|
|
|
if (trainerItemsCheckBox.Checked)
|
|
{
|
|
currentTrainerFile.party[i].heldItem = (ushort)partyItemsComboboxList[i].SelectedIndex;
|
|
}
|
|
|
|
currentTrainerFile.party[i].difficulty = (byte)partyIVUpdownList[i].Value;
|
|
|
|
if (hasMoreThanOneGender((int)currentTrainerFile.party[i].pokeID, pokemonSpecies) && (gameFamily == GameFamilies.HGSS || RomInfo.AIBackportEnabled))
|
|
{
|
|
switch (partyGenderComboBoxList[i].SelectedIndex)
|
|
{
|
|
case TRAINER_PARTY_POKEMON_GENDER_DEFAULT_INDEX:
|
|
currentTrainerFile.party[i].genderAndAbilityFlags = PartyPokemon.GenderAndAbilityFlags.NO_FLAGS;
|
|
break;
|
|
case TRAINER_PARTY_POKEMON_GENDER_MALE_INDEX:
|
|
currentTrainerFile.party[i].genderAndAbilityFlags = PartyPokemon.GenderAndAbilityFlags.FORCE_MALE;
|
|
break;
|
|
case TRAINER_PARTY_POKEMON_GENDER_FEMALE_INDEX:
|
|
currentTrainerFile.party[i].genderAndAbilityFlags = PartyPokemon.GenderAndAbilityFlags.FORCE_FEMALE;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
currentTrainerFile.party[i].genderAndAbilityFlags = PartyPokemon.GenderAndAbilityFlags.NO_FLAGS;
|
|
|
|
if (partyAbilityComboBoxList[i].SelectedIndex == TRAINER_PARTY_POKEMON_ABILITY_SLOT1_INDEX)
|
|
{
|
|
currentTrainerFile.party[i].genderAndAbilityFlags |= PartyPokemon.GenderAndAbilityFlags.ABILITY_SLOT1;
|
|
}
|
|
else if (partyAbilityComboBoxList[i].SelectedIndex == TRAINER_PARTY_POKEMON_ABILITY_SLOT2_INDEX)
|
|
{
|
|
currentTrainerFile.party[i].genderAndAbilityFlags |= PartyPokemon.GenderAndAbilityFlags.ABILITY_SLOT2;
|
|
}
|
|
|
|
currentTrainerFile.party[i].ballSeals = (ushort)partyBallUpdownList[i].Value;
|
|
}
|
|
|
|
if (duplicateMoves.Count != 0)
|
|
{
|
|
StringBuilder sb = new StringBuilder();
|
|
sb.Append("Duplicate moves have been found:\n");
|
|
|
|
foreach (var duplicate in duplicateMoves)
|
|
{
|
|
string move = partyMovesGroupboxList[duplicate.monIdx].Controls[duplicate.moveIdx1].Text;
|
|
sb.Append($"- {partyPokemonComboboxList[duplicate.monIdx].Text} has duplicate move \"{move}\"\n");
|
|
}
|
|
sb.Append("This will cause issues in game.");
|
|
|
|
MessageBox.Show(sb.ToString(), "Duplicate Moves", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
|
|
/*Write to File*/
|
|
string indexStr = "\\" + trainerComboBox.SelectedIndex.ToString("D4");
|
|
File.WriteAllBytes(RomInfo.gameDirs[DirNames.trainerProperties].unpackedDir + indexStr, currentTrainerFile.trp.ToByteArray());
|
|
File.WriteAllBytes(RomInfo.gameDirs[DirNames.trainerParty].unpackedDir + indexStr, currentTrainerFile.party.ToByteArray());
|
|
|
|
UpdateCurrentTrainerName(newName: trainerNameTextBox.Text);
|
|
UpdateCurrentTrainerShownName();
|
|
|
|
if (trainerNameTextBox.Text.Length > RomInfo.trainerNameMaxLen)
|
|
{ //Subtract 1 to account for special end character.
|
|
//Expose a smaller limit to the user
|
|
if (RomInfo.trainerNameLenOffset >= 0)
|
|
{
|
|
MessageBox.Show($"Trainer File saved successfully. However:\nYou attempted to save a Trainer whose name exceeds {RomInfo.trainerNameMaxLen} characters.\nThis may lead to issues in game." +
|
|
(PatchToolboxDialog.flag_TrainerNamesExpanded ? "\n\nIt's recommended that you use a shorter name." : "\n\nRefer to the Patch Toolbox to extend Trainer names."),
|
|
"Saved successfully, but...", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show($"Trainer File saved successfully. However:\nThe Trainer name length could not be safely determined for this ROM.\n" +
|
|
$"You attempted to save a Trainer whose name exceeds {RomInfo.trainerNameMaxLen} characters.\nThis will most likely lead to issues in game.",
|
|
"Saved successfully, but...", MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show("Trainer saved successfully!", "Saved successfully", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
}
|
|
|
|
private void UpdateCurrentTrainerShownName()
|
|
{
|
|
string trClass = GetTrainerClassNameFromListbox(trainerClassListBox.SelectedItem);
|
|
|
|
string editedTrainer = "[" + currentTrainerFile.trp.trainerID.ToString("D2") + "] " + trClass + " " + currentTrainerFile.name;
|
|
|
|
Helpers.DisableHandlers();
|
|
trainerComboBox.Items[trainerComboBox.SelectedIndex] = editedTrainer;
|
|
Helpers.EnableHandlers();
|
|
|
|
if (EditorPanels.eventEditor.eventEditorIsReady)
|
|
{
|
|
EditorPanels.eventEditor.owTrainerComboBox.Items[trainerComboBox.SelectedIndex] = editedTrainer;
|
|
}
|
|
}
|
|
|
|
private string GetTrainerClassNameFromListbox(object selectedItem)
|
|
{
|
|
string lbname = selectedItem.ToString();
|
|
return lbname.Substring(lbname.IndexOf(" ") + 1);
|
|
}
|
|
|
|
private void UpdateCurrentTrainerName(string newName)
|
|
{
|
|
currentTrainerFile.name = newName;
|
|
TextArchive trainerNames = new TextArchive(RomInfo.trainerNamesMessageNumber);
|
|
if (currentTrainerFile.trp.trainerID < trainerNames.messages.Count)
|
|
{
|
|
trainerNames.messages[currentTrainerFile.trp.trainerID] = newName;
|
|
}
|
|
else
|
|
{
|
|
trainerNames.messages.Add(newName);
|
|
}
|
|
trainerNames.SaveToFileDefaultDir(RomInfo.trainerNamesMessageNumber, showSuccessMessage: false);
|
|
}
|
|
private void UpdateCurrentTrainerClassName(string newName)
|
|
{
|
|
TextArchive trainerClassNames = new TextArchive(RomInfo.trainerClassMessageNumber);
|
|
trainerClassNames.messages[trainerClassListBox.SelectedIndex] = newName;
|
|
trainerClassNames.SaveToFileDefaultDir(RomInfo.trainerClassMessageNumber, showSuccessMessage: false);
|
|
}
|
|
|
|
private void trainerClassListBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
int selection = trainerClassListBox.SelectedIndex;
|
|
if (selection < 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
try
|
|
{
|
|
int maxFrames = LoadTrainerClassPic(selection);
|
|
UpdateTrainerClassPic(trainerClassPicBox);
|
|
|
|
trClassFramePreviewUpDown.Maximum = maxFrames;
|
|
trainerClassFrameMaxLabel.Text = "/" + maxFrames;
|
|
}
|
|
catch
|
|
{
|
|
trClassFramePreviewUpDown.Maximum = 0;
|
|
}
|
|
|
|
trainerClassNameTextbox.Text = GetTrainerClassNameFromListbox(trainerClassListBox.SelectedItem);
|
|
|
|
if (trainerClassEncounterMusicDict.TryGetValue((byte)selection, out (uint entryOffset, ushort musicD, ushort? musicN) output))
|
|
{
|
|
encounterSSEQMainUpDown.Enabled = eyeContactMusicLabel.Enabled = true;
|
|
encounterSSEQMainUpDown.Value = output.musicD;
|
|
}
|
|
else
|
|
{
|
|
encounterSSEQMainUpDown.Enabled = eyeContactMusicLabel.Enabled = false;
|
|
encounterSSEQMainUpDown.Value = 0;
|
|
}
|
|
|
|
eyeContactMusicAltLabel.Enabled = encounterSSEQAltUpDown.Enabled = (encounterSSEQMainUpDown.Enabled && gameFamily == GameFamilies.HGSS);
|
|
encounterSSEQAltUpDown.Value = output.musicN != null ? (ushort)output.musicN : 0;
|
|
currentTrainerFile.trp.trainerClass = (byte)selection;
|
|
}
|
|
|
|
private void addTrainerButton_Click(object sender, EventArgs e)
|
|
{
|
|
/* Add new trainer file to 2 folders */
|
|
string suffix = "\\" + trainerComboBox.Items.Count.ToString("D4");
|
|
|
|
string trainerPropertiesPath = gameDirs[DirNames.trainerProperties].unpackedDir + suffix;
|
|
string partyFilePath = gameDirs[DirNames.trainerParty].unpackedDir + suffix;
|
|
|
|
File.WriteAllBytes(trainerPropertiesPath, new TrainerProperties((ushort)trainerComboBox.Items.Count).ToByteArray());
|
|
File.WriteAllBytes(partyFilePath, new PartyPokemon().ToByteArray());
|
|
|
|
TextArchive trainerClasses = new TextArchive(RomInfo.trainerClassMessageNumber);
|
|
TextArchive trainerNames = new TextArchive(RomInfo.trainerNamesMessageNumber);
|
|
|
|
/* Update ComboBox and select new file */
|
|
trainerComboBox.Items.Add(trainerClasses.messages[0]);
|
|
trainerNames.messages.Add("");
|
|
trainerNames.SaveToFileDefaultDir(RomInfo.trainerNamesMessageNumber, showSuccessMessage: false);
|
|
|
|
trainerComboBox.SelectedIndex = trainerComboBox.Items.Count - 1;
|
|
UpdateCurrentTrainerShownName();
|
|
}
|
|
|
|
private void exportTrainerButton_Click(object sender, EventArgs e)
|
|
{
|
|
currentTrainerFile.SaveToFileExplorePath("G4 Trainer File " + trainerComboBox.SelectedItem);
|
|
}
|
|
|
|
private void importTrainerButton_Click(object sender, EventArgs e)
|
|
{
|
|
OpenFileDialog of = new OpenFileDialog
|
|
{
|
|
Filter = "Gen IV Trainer File (*.trf)|*.trf"
|
|
};
|
|
if (of.ShowDialog(this) != DialogResult.OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Update trainer on disk */
|
|
using (DSUtils.EasyReader reader = new DSUtils.EasyReader(of.FileName))
|
|
{
|
|
string trName = reader.ReadString();
|
|
|
|
byte datSize = reader.ReadByte();
|
|
byte[] trDat = reader.ReadBytes(datSize);
|
|
|
|
byte partySize = reader.ReadByte();
|
|
byte[] pDat = reader.ReadBytes(partySize);
|
|
|
|
string pathData = RomInfo.gameDirs[DirNames.trainerProperties].unpackedDir + "\\" + trainerComboBox.SelectedIndex.ToString("D4");
|
|
string pathParty = RomInfo.gameDirs[DirNames.trainerParty].unpackedDir + "\\" + trainerComboBox.SelectedIndex.ToString("D4");
|
|
File.WriteAllBytes(pathData, trDat);
|
|
File.WriteAllBytes(pathParty, pDat);
|
|
|
|
UpdateCurrentTrainerName(trName);
|
|
}
|
|
|
|
/* Refresh controls and re-read file */
|
|
trainerComboBox_SelectedIndexChanged(null, null);
|
|
UpdateCurrentTrainerShownName();
|
|
|
|
/* Display success message */
|
|
MessageBox.Show("Trainer File imported successfully!", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
private void exportPropertiesButton_Click(object sender, EventArgs e)
|
|
{
|
|
currentTrainerFile.trp.SaveToFileExplorePath("G4 Trainer Properties " + trainerComboBox.SelectedItem);
|
|
}
|
|
|
|
private void replacePropertiesButton_Click(object sender, EventArgs e)
|
|
{
|
|
OpenFileDialog of = new OpenFileDialog
|
|
{
|
|
Filter = "Gen IV Trainer Properties (*.trp)|*.trp"
|
|
};
|
|
if (of.ShowDialog(this) != DialogResult.OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Update trp object in memory */
|
|
currentTrainerFile.trp = new TrainerProperties((ushort)trainerComboBox.SelectedIndex, new FileStream(of.FileName, FileMode.Open));
|
|
RefreshTrainerPropertiesGUI();
|
|
|
|
/* Display success message */
|
|
MessageBox.Show("Trainer Properties imported successfully!\nRemember to save the current Trainer File.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
private void exportPartyButton_Click(object sender, EventArgs e)
|
|
{
|
|
currentTrainerFile.party.exportCondensedData = true;
|
|
currentTrainerFile.party.SaveToFileExplorePath("G4 Party Data " + trainerComboBox.SelectedItem);
|
|
currentTrainerFile.party.exportCondensedData = false;
|
|
}
|
|
|
|
private void importReplacePartyButton_Click(object sender, EventArgs e)
|
|
{
|
|
OpenFileDialog of = new OpenFileDialog
|
|
{
|
|
Filter = "Gen IV Party File (*.pdat)|*.pdat"
|
|
};
|
|
if (of.ShowDialog(this) != DialogResult.OK)
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* Update trp object in memory */
|
|
currentTrainerFile.party = new Party(readFirstByte: true, TrainerFile.POKE_IN_PARTY, new FileStream(of.FileName, FileMode.Open), currentTrainerFile.trp);
|
|
RefreshTrainerPropertiesGUI();
|
|
RefreshTrainerPartyGUI();
|
|
|
|
/* Display success message */
|
|
MessageBox.Show("Trainer Party imported successfully!\nRemember to save the current Trainer File.", "", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
private void saveTrainerClassButton_Click(object sender, EventArgs e)
|
|
{
|
|
Helpers.DisableHandlers();
|
|
|
|
int selectedTrClass = trainerClassListBox.SelectedIndex;
|
|
|
|
byte b_selectedTrClass = (byte)selectedTrClass;
|
|
ushort eyeMusicID = (ushort)encounterSSEQMainUpDown.Value;
|
|
ushort altEyeMusicID = (ushort)encounterSSEQAltUpDown.Value;
|
|
|
|
if (trainerClassEncounterMusicDict.TryGetValue(b_selectedTrClass, out var dictEntry))
|
|
{
|
|
ARM9.WriteBytes(BitConverter.GetBytes(eyeMusicID), dictEntry.entryOffset + 2);
|
|
|
|
if (gameFamily.Equals(GameFamilies.HGSS))
|
|
{
|
|
ARM9.WriteBytes(BitConverter.GetBytes(altEyeMusicID), dictEntry.entryOffset + 4);
|
|
}
|
|
|
|
trainerClassEncounterMusicDict[b_selectedTrClass] = (dictEntry.entryOffset, eyeMusicID, altEyeMusicID);
|
|
}
|
|
|
|
string newName = trainerClassNameTextbox.Text;
|
|
UpdateCurrentTrainerClassName(newName);
|
|
trainerClassListBox.Items[selectedTrClass] = "[" + selectedTrClass.ToString("D3") + "]" + " " + newName;
|
|
|
|
if (currentTrainerFile.trp.trainerClass == trainerClassListBox.SelectedIndex)
|
|
{
|
|
UpdateCurrentTrainerShownName();
|
|
}
|
|
Helpers.EnableHandlers();
|
|
|
|
if (gameFamily.Equals(GameFamilies.HGSS) && EditorPanels.tableEditor.battleTableEditorIsReady && EditorPanels.tableEditor.conditionnalMusicTableEditorIsReady)
|
|
{
|
|
EditorPanels.tableEditor.pbEffectsTrainerCombobox.Items[selectedTrClass] = trainerClassListBox.Items[selectedTrClass];
|
|
for (int i = 0; i < EditorPanels.tableEditor.vsTrainerEffectsList.Count; i++)
|
|
{
|
|
if (EditorPanels.tableEditor.vsTrainerEffectsList[i].trainerClass == selectedTrClass)
|
|
{
|
|
EditorPanels.tableEditor.pbEffectsVsTrainerListbox.Items[i] = EditorPanels.tableEditor.pbEffectsTrainerCombobox.Items[selectedTrClass] + " uses Combo #" + EditorPanels.tableEditor.vsTrainerEffectsList[i].comboID;
|
|
}
|
|
}
|
|
}
|
|
MessageBox.Show("Trainer Class settings saved.", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
|
|
private void trClassFramePreviewUpDown_ValueChanged(object sender, EventArgs e)
|
|
{
|
|
UpdateTrainerClassPic(trainerClassPicBox);
|
|
}
|
|
|
|
private (int abi1, int abi2)[] getPokemonAbilities(int numPokemonSpecies)
|
|
{
|
|
var pokemonSpeciesAbilities = new (int abi1, int abi2)[numPokemonSpecies];
|
|
|
|
for (int i = 0; i < numPokemonSpecies; i++)
|
|
{
|
|
pokemonSpeciesAbilities[i] = (pokemonSpecies[i].Ability1, pokemonSpecies[i].Ability2);
|
|
}
|
|
|
|
return pokemonSpeciesAbilities;
|
|
}
|
|
|
|
private (string ability1, string ability2) getPokemonAbilityNames(int pokemonID)
|
|
{
|
|
return (abilityNames[pokemonSpeciesAbilities[pokemonID].abi1],
|
|
abilityNames[pokemonSpeciesAbilities[pokemonID].abi2]);
|
|
}
|
|
|
|
private void setTrainerPartyPokemonAbilities(int partyPokemonPosition)
|
|
{
|
|
(string ability1, string ability2) = getPokemonAbilityNames(partyPokemonComboboxList[partyPokemonPosition].SelectedIndex);
|
|
string noFlags = "No Flag";
|
|
|
|
partyAbilityComboBoxList[partyPokemonPosition].Items.Clear();
|
|
|
|
// In DPPt just show ability 1 and do not allow editing
|
|
if (RomInfo.gameFamily != GameFamilies.HGSS && !RomInfo.AIBackportEnabled)
|
|
{
|
|
partyAbilityComboBoxList[partyPokemonPosition].Items.Add(ability1);
|
|
partyAbilityComboBoxList[partyPokemonPosition].Enabled = false;
|
|
return;
|
|
}
|
|
|
|
// In HGSS allow editing of ability flags
|
|
partyAbilityComboBoxList[partyPokemonPosition].Items.Add(noFlags);
|
|
partyAbilityComboBoxList[partyPokemonPosition].Items.Add(ability1);
|
|
|
|
string stringAbi2 = ability2;
|
|
if (ability2.Equals(ability1))
|
|
{
|
|
stringAbi2 += " (2nd Slot)";
|
|
}
|
|
else if (ability2.Equals(" -"))
|
|
{
|
|
stringAbi2 = ability1 += " (2nd Slot)";
|
|
}
|
|
partyAbilityComboBoxList[partyPokemonPosition].Items.Add(stringAbi2);
|
|
|
|
|
|
}
|
|
|
|
private void setTrainerPokemonGender(int partyPokemonPosition)
|
|
{
|
|
int currentPokemonGenderRatio = pokemonSpecies[partyPokemonComboboxList[partyPokemonPosition].SelectedIndex].GenderRatioMaleToFemale;
|
|
PartyPokemon.GenderAndAbilityFlags currentPokemonGenderAndAbilityFlags = currentTrainerFile.party[partyPokemonPosition].genderAndAbilityFlags;
|
|
|
|
if (gameFamily == GameFamilies.HGSS || RomInfo.AIBackportEnabled)
|
|
{
|
|
switch (currentPokemonGenderRatio)
|
|
{
|
|
case GENDER_RATIO_MALE:
|
|
partyGenderComboBoxList[partyPokemonPosition].SelectedIndex = TRAINER_PARTY_POKEMON_GENDER_MALE_INDEX;
|
|
partyGenderComboBoxList[partyPokemonPosition].Enabled = false;
|
|
break;
|
|
case GENDER_RATIO_FEMALE:
|
|
partyGenderComboBoxList[partyPokemonPosition].SelectedIndex = TRAINER_PARTY_POKEMON_GENDER_FEMALE_INDEX;
|
|
partyGenderComboBoxList[partyPokemonPosition].Enabled = false;
|
|
break;
|
|
case GENDER_RATIO_GENDERLESS:
|
|
partyGenderComboBoxList[partyPokemonPosition].SelectedIndex = TRAINER_PARTY_POKEMON_GENDER_DEFAULT_INDEX;
|
|
partyGenderComboBoxList[partyPokemonPosition].Enabled = false;
|
|
break;
|
|
default:
|
|
partyGenderComboBoxList[partyPokemonPosition].Enabled = true;
|
|
|
|
if (currentPokemonGenderAndAbilityFlags.HasFlag(PartyPokemon.GenderAndAbilityFlags.FORCE_MALE))
|
|
partyGenderComboBoxList[partyPokemonPosition].SelectedIndex = TRAINER_PARTY_POKEMON_GENDER_MALE_INDEX;
|
|
else if (currentPokemonGenderAndAbilityFlags.HasFlag(PartyPokemon.GenderAndAbilityFlags.FORCE_FEMALE))
|
|
partyGenderComboBoxList[partyPokemonPosition].SelectedIndex = TRAINER_PARTY_POKEMON_GENDER_FEMALE_INDEX;
|
|
else
|
|
partyGenderComboBoxList[partyPokemonPosition].SelectedIndex = TRAINER_PARTY_POKEMON_GENDER_DEFAULT_INDEX;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private List<string> getPokemonFormNames(int pokemonID)
|
|
{
|
|
List<string> pokemonFormNames = new List<string>();
|
|
|
|
switch (pokemonID)
|
|
{
|
|
case PICHU_ID_NUM:
|
|
if (RomInfo.gameFamily == GameFamilies.HGSS)
|
|
{
|
|
pokemonFormNames.Add("Non-Spiky-Eared");
|
|
pokemonFormNames.Add("Spiky-Eared");
|
|
}
|
|
else
|
|
{
|
|
pokemonFormNames.Add("No Alt Form");
|
|
}
|
|
break;
|
|
case UNOWN_ID_NUM:
|
|
for (char c = 'A'; c <= 'Z'; c++)
|
|
pokemonFormNames.Add(c + " Form");
|
|
|
|
pokemonFormNames.Add("! Form");
|
|
pokemonFormNames.Add("? Form");
|
|
break;
|
|
case CASTFORM_ID_NUM:
|
|
pokemonFormNames.Add("Normal Form");
|
|
pokemonFormNames.Add("Sunny Form");
|
|
pokemonFormNames.Add("Rainy Form");
|
|
pokemonFormNames.Add("Snowy Form");
|
|
break;
|
|
case DEOXYS_ID_NUM:
|
|
pokemonFormNames.Add("Normal Form");
|
|
pokemonFormNames.Add("Attack Form");
|
|
pokemonFormNames.Add("Defense Form");
|
|
pokemonFormNames.Add("Speed Form");
|
|
break;
|
|
case BURMY_ID_NUM:
|
|
case WORMADAM_ID_NUM:
|
|
pokemonFormNames.Add("Plant Cloak");
|
|
pokemonFormNames.Add("Sand Cloak");
|
|
pokemonFormNames.Add("Trash Cloak");
|
|
break;
|
|
case SHELLOS_ID_NUM:
|
|
case GASTRODON_ID_NUM:
|
|
pokemonFormNames.Add("West sea");
|
|
pokemonFormNames.Add("East sea");
|
|
break;
|
|
case ROTOM_ID_NUM:
|
|
pokemonFormNames.Add("Rotom");
|
|
pokemonFormNames.Add("Heat Rotom");
|
|
pokemonFormNames.Add("Wash Rotom");
|
|
pokemonFormNames.Add("Frost Rotom");
|
|
pokemonFormNames.Add("Fan Rotom");
|
|
pokemonFormNames.Add("Mow Rotom");
|
|
break;
|
|
case SHAYMIN_ID_NUM:
|
|
pokemonFormNames.Add("Land Form");
|
|
pokemonFormNames.Add("Sky Form");
|
|
break;
|
|
default:
|
|
pokemonFormNames.Add("No Alt Form");
|
|
break;
|
|
}
|
|
return pokemonFormNames;
|
|
|
|
}
|
|
|
|
private void setTrainerPartyPokemonForm(int partyPokemonPosition)
|
|
{
|
|
if (gameFamily != GameFamilies.DP)
|
|
{
|
|
partyFormComboBoxList[partyPokemonPosition].Items.Clear();
|
|
List<string> currentPokemonFormName = getPokemonFormNames(partyPokemonComboboxList[partyPokemonPosition].SelectedIndex);
|
|
foreach (string formName in currentPokemonFormName)
|
|
partyFormComboBoxList[partyPokemonPosition].Items.Add(formName);
|
|
|
|
partyFormComboBoxList[partyPokemonPosition].Enabled = currentPokemonFormName.Count > 1;
|
|
partyFormComboBoxList[partyPokemonPosition].SelectedIndex = 0;
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
}
|