mirror of
https://github.com/AdAstra-LD/DS-Pokemon-Rom-Editor.git
synced 2026-10-30 13:10:33 -05:00
Major script editor update + other stuff
- Separated Script Commands and Scipt Actions (new class) - minor code refactor - fixed menu buttons - proceeded with script editor rewrite - script editor identifies errors and reports them - fixed minor issue with decimals ( buildings updown value box )
This commit is contained in:
@@ -3,196 +3,171 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace DSPRE.ROMFiles {
|
||||
public class Script {
|
||||
public class CommandContainer {
|
||||
public List<ScriptCommand> commands;
|
||||
public int manualUserID;
|
||||
public int useScript;
|
||||
|
||||
#region Constructors (2)
|
||||
public Script(int useScript = -1, List<ScriptCommand> commandList = null) {
|
||||
commands = commandList;
|
||||
public CommandContainer(int scriptNumber, int useScript = -1, List<ScriptCommand> commandList = null) {
|
||||
manualUserID = scriptNumber;
|
||||
this.useScript = useScript;
|
||||
commands = commandList;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
public class ScriptCommand {
|
||||
#region Fields (4)
|
||||
public ushort id;
|
||||
public List<byte[]> parameterList;
|
||||
public string cmdName;
|
||||
public bool isMovement;
|
||||
public List<byte[]> commandParameters;
|
||||
public string name;
|
||||
#endregion
|
||||
|
||||
#region Constructors (2)
|
||||
public ScriptCommand(ushort id, List<byte[]> parameterList, bool isMovement = false) {
|
||||
public ScriptCommand(ushort id, List<byte[]> commandParameters) {
|
||||
this.id = id;
|
||||
this.isMovement = isMovement;
|
||||
this.parameterList = parameterList;
|
||||
this.commandParameters = commandParameters;
|
||||
|
||||
Dictionary<ushort, string> commandNamesDatabase;
|
||||
if (isMovement) {
|
||||
commandNamesDatabase = PokeDatabase.ScriptEditor.movementsDictIDName;
|
||||
} else {
|
||||
commandNamesDatabase = RomInfo.scriptCommandNamesDict;
|
||||
}
|
||||
commandNamesDatabase = RomInfo.scriptCommandNamesDict;
|
||||
|
||||
try {
|
||||
cmdName = commandNamesDatabase[id];
|
||||
name = commandNamesDatabase[id];
|
||||
} catch (KeyNotFoundException) {
|
||||
cmdName = id.ToString("X4");
|
||||
name = id.ToString("X4");
|
||||
}
|
||||
|
||||
if (isMovement) {
|
||||
for (int i = 0; i < parameterList.Count; i++) {
|
||||
if (parameterList[i].Length == 1)
|
||||
this.cmdName += " " + "0x" + (parameterList[i][0]).ToString("X1");
|
||||
else if (parameterList[i].Length == 2)
|
||||
this.cmdName += " " + "0x" + (BitConverter.ToInt16(parameterList[i], 0)).ToString("X1");
|
||||
else if (parameterList[i].Length == 4)
|
||||
this.cmdName += " " + "0x" + (BitConverter.ToInt32(parameterList[i], 0)).ToString("X1");
|
||||
}
|
||||
} else {
|
||||
switch (id) {
|
||||
case 0x16: // Jump
|
||||
case 0x1A: // Call
|
||||
this.cmdName += " " + "Function_#" + (1 + BitConverter.ToInt32(parameterList[0], 0)).ToString("D");
|
||||
break;
|
||||
case 0x17: // JumpIfObjID
|
||||
case 0x18: // JumpIfBgID
|
||||
case 0x19: // JumpIfPlayerDir
|
||||
this.cmdName += " " + (BitConverter.ToInt32(parameterList[0], 0)).ToString("D") + " " + "Function_#" + (1 + (BitConverter.ToInt32(parameterList[1], 0))).ToString("D");
|
||||
break;
|
||||
case 0x1C: // CompareLastResultJump
|
||||
case 0x1D: // CompareLastResultCall
|
||||
byte opcode = parameterList[0][0];
|
||||
this.cmdName += " " + PokeDatabase.ScriptEditor.comparisonOperators[opcode] + " " + "Function_#" + (1 + (BitConverter.ToInt32(parameterList[1], 0))).ToString("D");
|
||||
break;
|
||||
case 0x5E: // ApplyMovement
|
||||
ushort flexID = BitConverter.ToUInt16(parameterList[0], 0);
|
||||
this.cmdName += OverworldFlexDecode(flexID);
|
||||
this.cmdName += " " + "Action_#" + (1 + (BitConverter.ToInt32(parameterList[1], 0))).ToString("D");
|
||||
break;
|
||||
case 0x62: // Lock
|
||||
case 0x63: // Release
|
||||
case 0x64: // AddPeople
|
||||
case 0x65: // RemoveOW
|
||||
flexID = BitConverter.ToUInt16(parameterList[0], 0);
|
||||
cmdName += OverworldFlexDecode(flexID);
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < parameterList.Count; i++) {
|
||||
if (parameterList[i].Length == 1)
|
||||
this.cmdName += " " + "0x" + (parameterList[i][0]).ToString("X1");
|
||||
else if (parameterList[i].Length == 2)
|
||||
this.cmdName += " " + "0x" + (BitConverter.ToInt16(parameterList[i], 0)).ToString("X1");
|
||||
else if (parameterList[i].Length == 4)
|
||||
this.cmdName += " " + "0x" + (BitConverter.ToInt32(parameterList[i], 0)).ToString("X1");
|
||||
}
|
||||
break;
|
||||
}
|
||||
switch (id) {
|
||||
case 0x16: // Jump
|
||||
case 0x1A: // Call
|
||||
this.name += " " + "Function_#" + (1 + BitConverter.ToInt32(commandParameters[0], 0)).ToString("D");
|
||||
break;
|
||||
case 0x17: // JumpIfObjID
|
||||
case 0x18: // JumpIfBgID
|
||||
case 0x19: // JumpIfPlayerDir
|
||||
this.name += " " + (BitConverter.ToInt32(commandParameters[0], 0)).ToString("D") + " " + "Function_#" + (1 + (BitConverter.ToInt32(commandParameters[1], 0))).ToString("D");
|
||||
break;
|
||||
case 0x1C: // CompareLastResultJump
|
||||
case 0x1D: // CompareLastResultCall
|
||||
byte opcode = commandParameters[0][0];
|
||||
this.name += " " + PokeDatabase.ScriptEditor.comparisonOperators[opcode] + " " + "Function_#" + (1 + (BitConverter.ToInt32(commandParameters[1], 0))).ToString("D");
|
||||
break;
|
||||
case 0x5E: // ApplyMovement
|
||||
ushort flexID = BitConverter.ToUInt16(commandParameters[0], 0);
|
||||
this.name += ScriptFile.OverworldFlexDecode(flexID);
|
||||
this.name += " " + "Action_#" + (1 + (BitConverter.ToInt32(commandParameters[1], 0))).ToString("D");
|
||||
break;
|
||||
case 0x62: // Lock
|
||||
case 0x63: // Release
|
||||
case 0x64: // AddPeople
|
||||
case 0x65: // RemoveOW
|
||||
flexID = BitConverter.ToUInt16(commandParameters[0], 0);
|
||||
name += ScriptFile.OverworldFlexDecode(flexID);
|
||||
break;
|
||||
default:
|
||||
for (int i = 0; i < commandParameters.Count; i++) {
|
||||
if (commandParameters[i].Length == 1)
|
||||
this.name += " " + "0x" + (commandParameters[i][0]).ToString("X1");
|
||||
else if (commandParameters[i].Length == 2)
|
||||
this.name += " " + "0x" + (BitConverter.ToInt16(commandParameters[i], 0)).ToString("X1");
|
||||
else if (commandParameters[i].Length == 4)
|
||||
this.name += " " + "0x" + (BitConverter.ToInt32(commandParameters[i], 0)).ToString("X1");
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
public ScriptCommand(string wholeLine, bool isMovement = false) {
|
||||
this.cmdName = wholeLine;
|
||||
this.isMovement = isMovement;
|
||||
this.parameterList = new List<byte[]>();
|
||||
public ScriptCommand(string wholeLine, int lineNumber) {
|
||||
name = wholeLine;
|
||||
commandParameters = new List<byte[]>();
|
||||
|
||||
string[] nameParts = wholeLine.Split(' '); // Separate command code from parameters
|
||||
/* Get command id, which is always first in the description */
|
||||
|
||||
try {
|
||||
if (isMovement) {
|
||||
id = PokeDatabase.ScriptEditor.movementsDictIDName.First(x => x.Value == nameParts[0]).Key;
|
||||
} else {
|
||||
id = RomInfo.scriptCommandNamesDict.First(x => x.Value == nameParts[0]).Key;
|
||||
}
|
||||
id = RomInfo.scriptCommandNamesDict.First(x => x.Value == nameParts[0]).Key;
|
||||
} catch (InvalidOperationException) {
|
||||
UInt16.TryParse(nameParts[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture, out this.id);
|
||||
try {
|
||||
id = UInt16.Parse(nameParts[0], NumberStyles.HexNumber, CultureInfo.InvariantCulture);
|
||||
} catch (FormatException) {
|
||||
MessageBox.Show("This Script file could not be saved." +
|
||||
Environment.NewLine + "Parser failed to interpret line " + lineNumber + ": \"" + wholeLine + "\"." +
|
||||
Environment.NewLine + "\nAre you sure it's a proper Script Command?", "Parser error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
id = UInt16.MaxValue;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read parameters from remainder of the description */
|
||||
Console.WriteLine("ID = " + id.ToString("X4"));
|
||||
if (nameParts.Length > 1) {
|
||||
if (isMovement) {
|
||||
if (nameParts[1].Length > 4) { // Cases where movement is followed by an Overworld parameter
|
||||
|
||||
int positionOfOverworldID = nameParts[1].IndexOf('#'); // Find position of #
|
||||
parameterList.Add(BitConverter.GetBytes(Int32.Parse(nameParts[1].Substring(positionOfOverworldID + 1), NumberStyles.Integer))); // Add Overworld_#
|
||||
parameterList[0] = BitConverter.GetBytes(BitConverter.ToInt32(parameterList[0], 0) - 1); // Add Overworld number
|
||||
byte[] parametersArr = RomInfo.commandParametersDict[id];
|
||||
|
||||
int paramLength = 0;
|
||||
if (parametersArr.Length == 1 && parametersArr.First() == 0) {
|
||||
paramLength = 0;
|
||||
} else {
|
||||
paramLength = parametersArr.Length;
|
||||
}
|
||||
|
||||
// TODO: Check if other cases may apply to movement parameters
|
||||
} else {
|
||||
parameterList.Add(BitConverter.GetBytes(Int16.Parse(nameParts[1].Substring(2), NumberStyles.HexNumber)));
|
||||
}
|
||||
} else {
|
||||
byte[] parametersArr = RomInfo.scriptParametersDict[id];
|
||||
for (int i = 0; i < parametersArr.Length; i++) {
|
||||
Console.WriteLine("Parameter #" + i.ToString() + ": " + nameParts[i + 1]);
|
||||
try {
|
||||
ushort comparisonOperator = PokeDatabase.ScriptEditor.comparisonOperators.First(x => x.Value == nameParts[i + 1]).Key;
|
||||
parameterList.Add(new byte[] { (byte)comparisonOperator });
|
||||
} catch { //Not a comparison
|
||||
int indexOfSpecialCharacter = nameParts[i + 1].IndexOfAny(new char[] { 'x', '#' });
|
||||
if (nameParts.Length - 1 == paramLength) {
|
||||
for (int i = 0; i < paramLength; i++) {
|
||||
Console.WriteLine("Parameter #" + i.ToString() + ": " + nameParts[i + 1]);
|
||||
try {
|
||||
ushort comparisonOperator = PokeDatabase.ScriptEditor.comparisonOperators.First(x => x.Value == nameParts[i + 1]).Key;
|
||||
commandParameters.Add(new byte[] { (byte)comparisonOperator });
|
||||
} catch { //Not a comparison
|
||||
int indexOfSpecialCharacter = nameParts[i + 1].IndexOfAny(new char[] { 'x', '#' });
|
||||
|
||||
/* If number is preceded by 0x parse it as hex, otherwise as decimal */
|
||||
NumberStyles style;
|
||||
if (nameParts[i + 1].Contains("0x"))
|
||||
style = NumberStyles.HexNumber;
|
||||
else
|
||||
style = NumberStyles.Integer;
|
||||
/* If number is preceded by 0x parse it as hex, otherwise as decimal */
|
||||
NumberStyles style;
|
||||
if (nameParts[i + 1].StartsWith("0x"))
|
||||
style = NumberStyles.HexNumber;
|
||||
else
|
||||
style = NumberStyles.Integer;
|
||||
|
||||
/* Convert strings of parameters to the correct datatypes */
|
||||
switch (parametersArr[i]) {
|
||||
case 1:
|
||||
parameterList.Add(new byte[] { Byte.Parse(nameParts[i + 1].Substring(indexOfSpecialCharacter + 1), style) });
|
||||
break;
|
||||
case 2:
|
||||
switch (nameParts[i + 1]) {
|
||||
case "Player":
|
||||
parameterList.Add(BitConverter.GetBytes((ushort)255));
|
||||
break;
|
||||
case "Following":
|
||||
parameterList.Add(BitConverter.GetBytes((ushort)253));
|
||||
break;
|
||||
case "Cam":
|
||||
parameterList.Add(BitConverter.GetBytes((ushort)241));
|
||||
break;
|
||||
default:
|
||||
parameterList.Add(BitConverter.GetBytes(Int16.Parse(nameParts[i + 1].Substring(indexOfSpecialCharacter + 1), style)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
parameterList.Add(BitConverter.GetBytes(Int32.Parse(nameParts[i + 1].Substring(indexOfSpecialCharacter + 1), style)));
|
||||
break;
|
||||
}
|
||||
/* Convert strings of parameters to the correct datatypes */
|
||||
switch (parametersArr[i]) {
|
||||
case 1:
|
||||
commandParameters.Add(new byte[] { Byte.Parse(nameParts[i + 1].Substring(indexOfSpecialCharacter + 1), style) });
|
||||
break;
|
||||
case 2:
|
||||
switch (nameParts[i + 1]) {
|
||||
case "Player":
|
||||
commandParameters.Add(BitConverter.GetBytes((ushort)255));
|
||||
break;
|
||||
case "Following":
|
||||
commandParameters.Add(BitConverter.GetBytes((ushort)253));
|
||||
break;
|
||||
case "Cam":
|
||||
commandParameters.Add(BitConverter.GetBytes((ushort)241));
|
||||
break;
|
||||
default:
|
||||
commandParameters.Add(BitConverter.GetBytes(Int16.Parse(nameParts[i + 1].Substring(indexOfSpecialCharacter + 1), style)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
commandParameters.Add(BitConverter.GetBytes(Int32.Parse(nameParts[i + 1].Substring(indexOfSpecialCharacter + 1), style)));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
MessageBox.Show("Wrong number of parameters for command " + nameParts[0] + " at line " + lineNumber + "." + Environment.NewLine +
|
||||
"Received: " + (nameParts.Length - 1) + Environment.NewLine + "Expected: " + paramLength
|
||||
+ Environment.NewLine + "\nThis Script File can not be saved.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
id = ushort.MaxValue; //ERROR VALUE
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Utilities
|
||||
private string OverworldFlexDecode(ushort flexID) {
|
||||
if (flexID > 255) {
|
||||
return " " + "0x" + flexID.ToString("X4");
|
||||
} else {
|
||||
switch (flexID) {
|
||||
case 255:
|
||||
return " " + "Player";
|
||||
case 253:
|
||||
return " " + "Following";
|
||||
case 241:
|
||||
return " " + "Cam";
|
||||
default:
|
||||
return " " + "Overworld_#" + flexID.ToString("D");
|
||||
}
|
||||
}
|
||||
}
|
||||
public override string ToString() {
|
||||
return cmdName + " (" + id.ToString("X") + ")";
|
||||
return name + " (" + id.ToString("X") + ")";
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user