@ eXistenZe : Yes, send me your .hws. I'll check it.
Update to 0.26 !
What's new :
- You can fully edit the game scripts. Also, you now have access to the World Map's script except for the japanese version which I have troubles with. The syntax ressembles to the C syntax with some significiant differencies (see below),
- Added an option for displaying texts in a nicer way (without the opcode symbols) in previews.
- Added a button in the text editing window to automatically compute the size of the dialog box. It's not 100% reliable but it's still fairly accurate.
About the game script, here is what I added in the "Help" window :
The game script handles scripted events, enemy AIs and other related stuffs.
The script is presented with a kind of C-like syntax. There are several differences though.
[General]
The language accepts only one instruction per line.
Lines are not terminated by any punctuation character.
For flow control statements, the braces are mandatory.
You can't use braces out of a flow control statement.
There is no such thing as real values. Everything is done using integers (sometimes signed).
Once you have modified a function's script, you must parse it to check eventual errors.
[Flow Control]
The different keywords for controlling the script's flow are described here.
if : usual If/Then statement with an optional Else. The syntax is
if ( CONDITION ) {
CODE
}
or
if ( CONDITION ) {
CODE_A
} else {
CODE_B
}
Note that the opening braces must be on the same line as the keywords "if" and "else".
ifnot : opposite control of if. It works similarly though. The syntax is
ifnot ( CONDITION ) {
CODE
}
while : usual While statement. You can use the keyword "break" to leave the control but there is no such thing as a "continue" instruction. The syntax is
while ( CONDITION ) {
CODE
}
do/while : usual Do/While statement. You can also use the keyword "break" to leave the control. The syntax is
do {
CODE
} while ( CONDITION )
switch : a Switch statement with consecutive cases only. The first case's value is specified in the control, as well as the maximal amount of cases. The syntax is
switch NB ( VALUE ) from FIRST {
case +INC:
CODE_A
case +INC ; +INC:
CODE_B
default:
CODE_C
}
where
NB is the maximal amount of cases,
VALUE is the control expression,
FIRST is the "+0" case,
INC are numbers strictly lower than NB.
Note that, like in C, you have to use the keyword "break" if you want only one branch to be run and that the "default" case is optional.
The semicolon allows to make several values lead to the same code branch.
switchex : a more usual Switch statement. The exact amount of cases (default case excluded) must be provided in the control. The syntax is
switchex NB ( VALUE ) {
case X:
CODE_A
case Y ; Z:
CODE_B
default:
CODE_C
}
NB being the amount of cases and X, Y and Z representing numbers. The keywords "break", "default" and the semicolon have the same purpose than for the "switch" statement.
loop : rerun the whole function. It works as an alternative to a last "RETURN" instruction and can only be used out of any other control block.
[Variables]
You can not declare variables. There is a limited amount of them, some being globals shared accross different field scripts, some being locals initialized to 0 when the script code is loaded.
For what I know,
- local variables are the ones named "VAR_A" "VAR_B" followed by 2 numbers. The second number works as an array operator,
- usual globals variables are the ones named "VAR_D",
- global variables that are saved in a memory card save are the ones named "VAR_C",
- "MV" and "SV" variables are special globals that are also shared by the game's mechanics (such as the battle code or the deplacement code).
- There are also Getters to retrieve values from the other game's mechanics that can't be directly modified (such as the player's gils amount).
In order to manipulate variables, you must use the instruction "SET" followed by a series of operations over the variables. Some of those operations are still unknown.
Besides the usual operations, you have "^" that marks the binary XOR operation and "#" that is an unary operator counting the amount of active bits.
The brackets are more of a structure's field accesser than a real array operator. They will be displayed differently in a next version.
Note that the minus operator can't be read as an unary operator yet. Only positive integers can be used in variable manipulation codes.
WARNING : at the moment, the operation priorities are not respected. By default, the operations will be executed from right to left. It is advised to write all the parentheses.
Variable manipulation codes can also be used in most of instructions's arguments.
You can change quiet a lot of things now. The content of the chests, the game dialogs, mini-game mechanics, etc... The scripting language may be a bit ascetic :/ I guess I would have had way more work if I wanted to make it more flexible.
Here is an example I made (a patch for the Disc 1 of the US version - just start a new game once patched) :
download patch exampleIt took me some time, though. It's still tedious. But way way less than editing the thing with an hexadecimal tool ^^
There is a limitation I'm willing to remove for the next version : you are limited for using only preloaded datas. You can't use a model if it is not present (hidden or not) in the original game in the field you want to use it. That also goes for model animations or fields (you can't jump from any field to any other field) or for battles.
In fact, I already passed by this limitation in the "hidden dialogs" patch I made. I need to work just a little bit more to automate the process. I guess I'll make available the choice of which datas are preloaded in a field (and a battle -> you'll finally be able to change an enemy's model).
Ah yes, something I forgot to mention in the help : the array of variables (the second number in "VAR_A10_
10" for example) is of size 256 for variables of type A, B and SV and is 65536 for C, D and MV. I also forgot to throw an error if you enter something higher... You'll end up with an array re-ajusted between 0 and 255 without being noticed of that.
Also, here is a list of the fighter structure fields I know (If you see "SV_FunctionEnemy[38]", for instance, that refers to the enemy's current MP). They appear only as raw number in the program :
[32] : Enable back presence flag
[33] : Disable presence flag
[35] : max HP
[36] : current HP
[37] : max MP
[38] : current MP
[39] : max ATB
[40] : current ATB (Only player characters maybe)
[41] : level
[42] : status immune (Heat - Gradual Petrify)
[43] : status immune (Petrify - Protect)
[44] : auto status (Heat - Gradual Petrify)
[45] : auto status (Petrify - Protect)
[46] : current status (Heat - Gradual Petrify)
[47] : current status (Petrify - Protect)
[48] : elemental immune
[49] : elemental absorb
[50] : elemental half
[51] : elemental weakness
[54] : shadow flag?
[55] : model size
[59] : Disable model flag
[60] : Enable back model flag
[65] : line position (not to confuse with "row position" ; that's the ordering of the fighters from 0 to 3)
[73] : magic power
[74] : defence
[75] : evade
[76] : magic defence
[77] : magic evade
[78] : marthym order flag (change its value to cast Marthym !)
You can totally modify them in battle script (the game does that for turning Ozma's darkness absorbtion into a weakness, for instance).
By the way, the reason why I display integer values as a base 64 numbers (among other display modes) is that most of enemy AIs use this base for the setup of their spell (how them casting is randomized is quiet complicated ^^). It has importance for the values in the AI setup.
I would be surprised if there isn't any bug, but not with the most common opcodes and stuff.
If you find one or if you have any question, please tell me.
I would like to thank yaz0r, a french fellow who works on a script dumper and who helped me for this (if you have convenient names for some functions, it's thanks to him for instance ^^).