using DSPRE.ROMFiles; using System; using System.Collections.Generic; using System.IO; using System.Runtime.CompilerServices; using System.Runtime.Remoting.Messaging; using System.Windows.Forms; using static DSPRE.RomInfo; namespace DSPRE.Editors { public partial class LevelScriptEditor : UserControl { public bool levelScriptEditorIsReady { get; set; } = false; LevelScriptFile _levelScriptFile; MainProgram _parent; public LevelScriptEditor() { InitializeComponent(); toolTip1.SetToolTip(buttonOpenSelectedScript, "Open this script in the Script Editor.\nThis button will be disabled for real level scripts."); toolTip1.SetToolTip(buttonOpenHeaderScript, "Open the script of the Header this level script is associated to.\nWill only display the first result!"); toolTip1.SetToolTip(buttonLocate, "Open the folder containing the selected level script file."); toolTip1.SetToolTip(buttonImport, "Import a level script file.\nThis will overwrite the current level script file."); toolTip1.SetToolTip(buttonSave, "Save the current level script file.\nThis will overwrite the current level script file."); toolTip1.SetToolTip(buttonExport, "Export the current level script file.\nThis will not overwrite the current level script file."); toolTip1.SetToolTip(buttonAdd, "Add a new trigger to the current level script file.\nMake sure to fill in the required fields first."); } public void SetUpLevelScriptEditor(MainProgram parent, bool force = false) { if (levelScriptEditorIsReady && !force) { return; } levelScriptEditorIsReady = true; this._parent = parent; DSUtils.TryUnpackNarcs(new List { RomInfo.DirNames.scripts }); //12 = scripts Narc Dir populate_selectScriptFileComboBox(); } public void OpenLevelScriptEditor(MainProgram parent, int levelScriptID) { SetUpLevelScriptEditor(parent); selectScriptFileComboBox.SelectedIndex = levelScriptID; if (EditorPanels.PopoutRegistry.TryGetHost(this, out var host)) { host.Focus(); } else { EditorPanels.mainTabControl.SelectedTab = EditorPanels.levelScriptEditorTabPage; } } private void populate_selectScriptFileComboBox(int selectedIndex = 0) { selectScriptFileComboBox.Items.Clear(); int scriptCount = Filesystem.GetScriptCount(); for (int i = 0; i < scriptCount; i++) { // ScriptFile currentScriptFile = new ScriptFile(i, true, true); // selectScriptFileComboBox.Items.Add(currentScriptFile); selectScriptFileComboBox.Items.Add($"Script File {i}"); } selectScriptFileComboBox.SelectedIndex = selectedIndex; } void disableButtons(bool usurp = false) { if (!usurp && isEmptyLevelScript()) { enableButtons(); } else { buttonOpenSelectedScript.Enabled = true; buttonOpenHeaderScript.Enabled = false; listBoxTriggers.DataSource = null; textBoxScriptID.Clear(); textBoxVariableName.Clear(); textBoxVariableValue.Clear(); radioButtonVariableValue.Checked = false; radioButtonMapChange.Checked = false; radioButtonScreenReset.Checked = false; radioButtonLoadGame.Checked = false; textBoxScriptID.Enabled = false; radioButtonVariableValue.Enabled = false; radioButtonMapChange.Enabled = false; radioButtonScreenReset.Enabled = false; radioButtonLoadGame.Enabled = false; radioButtonAuto.Enabled = false; radioButtonHex.Enabled = false; radioButtonDecimal.Enabled = false; buttonImport.Enabled = false; buttonSave.Enabled = false; buttonExport.Enabled = false; checkBoxPadding.Enabled = false; buttonAdd.Enabled = false; buttonRemove.Enabled = false; buttonOpenSelectedScript.Enabled = true; } } void enableButtons() { buttonOpenHeaderScript.Enabled = true; buttonOpenSelectedScript.Enabled = false; textBoxScriptID.Enabled = true; textBoxVariableName.Enabled = true; textBoxVariableValue.Enabled = true; radioButtonVariableValue.Enabled = true; radioButtonMapChange.Enabled = true; radioButtonScreenReset.Enabled = true; radioButtonLoadGame.Enabled = true; radioButtonAuto.Enabled = true; radioButtonHex.Enabled = true; radioButtonDecimal.Enabled = true; buttonImport.Enabled = true; buttonSave.Enabled = true; buttonExport.Enabled = true; checkBoxPadding.Enabled = true; //buttonAdd.Enabled = true; //buttonRemove.Enabled = true; buttonOpenSelectedScript.Enabled = false; } void buttonAdd_logic() { buttonAdd.Enabled = false; if (radioButtonVariableValue.Checked) { if (!string.IsNullOrEmpty(textBoxScriptID.Text) && !string.IsNullOrEmpty(textBoxVariableName.Text) && !string.IsNullOrEmpty(textBoxVariableValue.Text)) { buttonAdd.Enabled = true; } } else if (radioButtonMapChange.Checked || radioButtonScreenReset.Checked || radioButtonLoadGame.Checked) { if (!string.IsNullOrEmpty(textBoxScriptID.Text)) { buttonAdd.Enabled = true; } } } private void selectScriptFileComboBox_SelectedIndexChanged(object sender, EventArgs e) { if (selectScriptFileComboBox.SelectedIndex == -1) { buttonLocate.Enabled = false; } else { buttonLocate.Enabled = true; } disableButtons(true); try { _levelScriptFile = new LevelScriptFile(selectScriptFileComboBox.SelectedIndex); listBoxTriggers.DataSource = _levelScriptFile.bufferSet; if (listBoxTriggers.Items.Count > 0) { listBoxTriggers.SelectedIndex = 0; } // Check for 318767104 enableButtons(); } catch (InvalidDataException ex) { //not a level script disableButtons(); AppLogger.Info(ex.Message); } } void listBoxTriggers_SelectedValueChanged(object sender, EventArgs e) { if (listBoxTriggers.SelectedItem == null) { buttonRemove.Enabled = false; return; } if (listBoxTriggers.SelectedItem is MapScreenLoadTrigger mapScreenLoadTrigger) { if (mapScreenLoadTrigger.triggerType == LevelScriptTrigger.LOADGAME) { radioButtonLoadGame.Checked = true; } else if (mapScreenLoadTrigger.triggerType == LevelScriptTrigger.MAPCHANGE) { radioButtonMapChange.Checked = true; } else if (mapScreenLoadTrigger.triggerType == LevelScriptTrigger.SCREENRESET) { radioButtonScreenReset.Checked = true; } } else if (listBoxTriggers.SelectedItem is VariableValueTrigger variableValueTrigger) { if (variableValueTrigger.triggerType == LevelScriptTrigger.VARIABLEVALUE) { radioButtonVariableValue.Checked = true; } } handleAutoFormat(); handleHexFormat(); handleDecimalFormat(); textBoxScriptID.Enabled = true; buttonRemove.Enabled = true; } private void buttonAdd_Click(object sender, EventArgs e) { // try { if (_levelScriptFile == null) { _levelScriptFile = new LevelScriptFile(); } int convertBase = 10; //decimal if (radioButtonHex.Checked) { convertBase = 16; //hex } if (radioButtonVariableValue.Checked) { int scriptID = Convert.ToInt16(textBoxScriptID.Text, convertBase); int variableName = Convert.ToInt16(textBoxVariableName.Text, convertBase); int variableValue = Convert.ToInt16(textBoxVariableValue.Text, convertBase); VariableValueTrigger variableValueTrigger = new VariableValueTrigger(scriptID, variableName, variableValue); _levelScriptFile.bufferSet.Add(variableValueTrigger); } else { int scriptID = Convert.ToInt16(textBoxScriptID.Text, convertBase); if (radioButtonMapChange.Checked) { MapScreenLoadTrigger mapScreenLoadTrigger = new MapScreenLoadTrigger(LevelScriptTrigger.MAPCHANGE, scriptID); _levelScriptFile.bufferSet.Add(mapScreenLoadTrigger); } else if (radioButtonScreenReset.Checked) { MapScreenLoadTrigger mapScreenLoadTrigger = new MapScreenLoadTrigger(LevelScriptTrigger.SCREENRESET, scriptID); _levelScriptFile.bufferSet.Add(mapScreenLoadTrigger); } else if (radioButtonLoadGame.Checked) { MapScreenLoadTrigger mapScreenLoadTrigger = new MapScreenLoadTrigger(LevelScriptTrigger.LOADGAME, scriptID); _levelScriptFile.bufferSet.Add(mapScreenLoadTrigger); } } textBoxScriptID.Clear(); textBoxVariableName.Clear(); textBoxVariableValue.Clear(); // } // catch (Exception exception) { // MessageBox.Show(exception.Message); // } } private void buttonRemove_Click(object sender, EventArgs e) { _levelScriptFile.bufferSet.RemoveAt(listBoxTriggers.SelectedIndex); } private void buttonOpenHeaderScript_Click(object sender, EventArgs e) { HashSet result; result = HeaderSearch.AdvancedSearch(0, (ushort)EditorPanels.headerEditor.internalNames.Count, EditorPanels.headerEditor.internalNames, (int)MapHeader.SearchableFields.LevelScriptID, (int)HeaderSearch.NumOperators.Equal, EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex.ToString()); AppLogger.Debug($"Found {result.Count} headers with script ID {EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex}"); AppLogger.Debug($"Searching for script file {EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex} in headers: {string.Join(", ", result)}"); if (result.Count == 0) { MessageBox.Show($"No headers found with level-script ID {EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex}.", "No headers found"); return; } string[] arr = new string[result.Count]; result.CopyTo(arr); for (int i = 0; i < arr.Length; i++) { arr[i] = arr[i].Remove(0, 3).Replace(MapHeader.nameSeparator, ""); } AppLogger.Debug($"Found {arr.Length} headers with script ID {EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex} in internal names: {string.Join(", ", arr)}"); ushort index = (ushort)EditorPanels.headerEditor.internalNames.IndexOf(arr[0]); MapHeader h; if (PatchToolboxDialog.flag_DynamicHeadersPatchApplied || PatchToolboxDialog.CheckFilesDynamicHeadersPatchApplied()) { h = MapHeader.LoadFromFile(RomInfo.gameDirs[DirNames.dynamicHeaders].unpackedDir + "\\" + index.ToString("D4"), index, 0); } else { h = MapHeader.LoadFromARM9(index); } EditorPanels.scriptEditor.OpenScriptEditor(this._parent, (int)h.scriptFileID); } private bool isEmptyLevelScript() { ScriptFile script = new ScriptFile((int)EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex, true, true); return script.isLevelScript; } private void buttonOpenSelectedScript_Click(object sender, EventArgs e) { EditorPanels.scriptEditor.OpenScriptEditor(this._parent, (int)EditorPanels.levelScriptEditor.selectScriptFileComboBox.SelectedIndex); } void buttonLocate_Click(object sender, EventArgs e) { if (_levelScriptFile == null) { return; } string path = Filesystem.GetScriptPath(_levelScriptFile.ID); Helpers.ExplorerSelect(path); } void buttonImport_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); if (ofd.ShowDialog() == DialogResult.OK) { try { LevelScriptFile importedFile = new LevelScriptFile(); importedFile.parse_file(ofd.FileName); _levelScriptFile.bufferSet.Clear(); foreach (LevelScriptTrigger trigger in importedFile.bufferSet) { _levelScriptFile.bufferSet.Add(trigger); } } catch (InvalidDataException ex) { MessageBox.Show(ex.Message, ex.GetType().ToString()); } } } private void buttonSave_Click(object sender, EventArgs e) { string path = Filesystem.GetScriptPath(_levelScriptFile.ID); saveFile(path); } private void buttonExport_Click(object sender, EventArgs e) { SaveFileDialog sfd = new SaveFileDialog(); try { sfd.InitialDirectory = Path.GetDirectoryName(sfd.FileName); sfd.FileName = Path.GetFileName(sfd.FileName); } catch (Exception ex) { sfd.InitialDirectory = Path.GetDirectoryName(Environment.SpecialFolder.UserProfile.ToString()); sfd.FileName = Path.GetFileName(sfd.FileName); } if (sfd.ShowDialog() == DialogResult.OK) { saveFile(sfd.FileName); } } void saveFile(string path) { try { long bytes_written = _levelScriptFile.write_file(path); if (bytes_written <= 4) { MessageBox.Show("Empty level script file was correctly saved.", "Success!"); } else { MessageBox.Show("File was correctly saved.", "Success!"); } } catch (Exception ex) { MessageBox.Show(ex.Message, ex.GetType().ToString()); } } private void handleAutoFormat() { if (!radioButtonAuto.Checked) { return; } textBoxScriptID.Clear(); textBoxVariableName.Clear(); textBoxVariableValue.Clear(); if (listBoxTriggers.SelectedItem is MapScreenLoadTrigger mapScreenLoadTrigger) { textBoxScriptID.Text = mapScreenLoadTrigger.scriptTriggered.ToString(); } else if (listBoxTriggers.SelectedItem is VariableValueTrigger variableValueTrigger) { textBoxScriptID.Text = variableValueTrigger.scriptTriggered.ToString(); textBoxVariableName.Text = "" + variableValueTrigger.variableToWatch.ToString("D"); textBoxVariableValue.Text = "" + variableValueTrigger.expectedValue.ToString("D"); } } private void handleHexFormat() { if (!radioButtonHex.Checked) { return; } textBoxScriptID.Clear(); textBoxVariableName.Clear(); textBoxVariableValue.Clear(); if (listBoxTriggers.SelectedItem is MapScreenLoadTrigger mapScreenLoadTrigger) { textBoxScriptID.Text = mapScreenLoadTrigger.scriptTriggered.ToString(); } else if (listBoxTriggers.SelectedItem is VariableValueTrigger variableValueTrigger) { textBoxScriptID.Text = variableValueTrigger.scriptTriggered.ToString(); textBoxVariableName.Text = "0x" + variableValueTrigger.variableToWatch.ToString("X"); textBoxVariableValue.Text = "0x" + variableValueTrigger.expectedValue.ToString("X"); } } private void handleDecimalFormat() { if (!radioButtonDecimal.Checked) { return; } textBoxScriptID.Clear(); textBoxVariableName.Clear(); textBoxVariableValue.Clear(); if (listBoxTriggers.SelectedItem is MapScreenLoadTrigger mapScreenLoadTrigger) { textBoxScriptID.Text = mapScreenLoadTrigger.scriptTriggered.ToString(); } else if (listBoxTriggers.SelectedItem is VariableValueTrigger variableValueTrigger) { textBoxScriptID.Text = variableValueTrigger.scriptTriggered.ToString(); textBoxVariableName.Text = "" + variableValueTrigger.variableToWatch.ToString("D"); textBoxVariableValue.Text = "" + variableValueTrigger.expectedValue.ToString("D"); } } private void radioButtonAuto_CheckedChanged(object sender, EventArgs e) { handleAutoFormat(); } private void radioButtonHex_CheckedChanged(object sender, EventArgs e) { handleHexFormat(); } private void radioButtonDecimal_CheckedChanged(object sender, EventArgs e) { handleDecimalFormat(); } private void AssignGroupBoxScriptText() { if (radioButtonVariableValue.Checked) { groupBoxScript.Text = "Keep running this Script"; } else { groupBoxScript.Text = "Run this Script"; } } private void radioButtonVariableValue_CheckedChanged(object sender, EventArgs e) { groupBoxVariable.Visible = true; groupBoxValue.Visible = true; buttonAdd_logic(); AssignGroupBoxScriptText(); } private void radioButtonMapChange_CheckedChanged(object sender, EventArgs e) { groupBoxVariable.Visible = false; groupBoxValue.Visible = false; buttonAdd_logic(); AssignGroupBoxScriptText(); } private void radioButtonScreenReset_CheckedChanged(object sender, EventArgs e) { groupBoxVariable.Visible = false; groupBoxValue.Visible = false; buttonAdd_logic(); AssignGroupBoxScriptText(); } private void radioButtonLoadGame_CheckedChanged(object sender, EventArgs e) { groupBoxVariable.Visible = false; groupBoxValue.Visible = false; buttonAdd_logic(); AssignGroupBoxScriptText(); } void textBoxScriptID_TextChanged(object sender, EventArgs e) { buttonAdd_logic(); } void textBoxVariableName_TextChanged(object sender, EventArgs e) { buttonAdd_logic(); } void textBoxVariableValue_TextChanged(object sender, EventArgs e) { buttonAdd_logic(); } } }