How does script-debug mode work?
This article documents part of an incomplete and never officially announced feature. It will probably never be completed
Ubersetzung contains a new script debugger which does much more than the old one. However it makes my head hurt, and I programmed it myself (just like the old one made James' head hurt)! I consider it a failure and plan to try again. A useful small subset of the debugger is described here.
There are three script debugging levels, Off, Regular, and Extended. Pressing F10 cycles between them. In regular mode, the currently running scripts are shown while the game continues to run. In Extended mode, the game is paused and you can investigate the state of the interpreter (there is no way to modify it).
When in script-debugging mode you will see two bars at the top of the screen, one blue and one pink. Ignore them. The blue bar shows the amount of script data loaded. It can't overflow. The pink bar shows the number of local variables used.
Using the debugger, you can both examine the state of the interpreter, which works fairly well aside from the fact that the original variable names and script line numbers aren't available, and also
You can change the currently selected script by pressing PgUp/PgDown
There are 4 viewing modes. Pressing V toggles between them.
The default one shows the command the script is currently executing. Compare this with the script source to make sense of it - see below.
The second shows the script's return value, arguments, and local variables. Press +/- to scroll if required.
The third doesn't depend on the selected script, it shows the value of all global variables. Press +/- to scroll.
The fourth shows the value of the 32 plotstrings. +/- to scroll.
The rest of extended mode (setting breakpoints and stepping through scripts) is undocumented, and somewhat buggy.
Reading the script state
Reading the script state string is difficult. Unfortunately, there are also several bugs, so if something plain doesn't make sense, it's probably the debugger's fault.
Here is an example of a the debugger's description of the state of a script from Pliptamer:
movescorefloaters:3/4 for(var0,4,11,1)do: if() then:1/2 moveonescore(4)
and here is the original script:
script, move score floaters, begin set timer(time:floater, 1, 1, @move score floaters) variable(floatref, floater count) floater count := 0 for(floatref, str:floater, str:floater limit) do, begin if(string is visible(floatref)) then, begin move one score(floatref) if(string is visible(floatref)) then(floater count += 1) end end if(floater count == 0) then, begin stop timer(time:floater) end end
What is the script doing? movescorefloaters:3/4 tells us that the current command at the base level of the script is the 3rd one, out of 4. variable does not count as a command (and is never executed), and all loops and if/then/else blocks count as single commands. So you can see that there are 4 commands at the bottom most level.
script, move score floaters, begin 1: set timer(time:floater, 1, 1, @move score floaters) variable(floatref, floater count) 2: floater count := 0 3: for(floatref, str:floater, str:floater limit) do, begin 1: if(string is visible(floatref)) then, begin 1: move one score(floatref) 2: if(string is visible(floatref)) then(floater count += 1) end end 4: if(floater count == 0) then, begin 1: stop timer(time:floater) end end
for(var0,4,11,1)do: is pretty clear: we are iterating var0 from 4 to 11, with step size 1 (the default step size, which was not explicitly given in the script). var0 means the first variable declared in the script, floatref. floater count is the second declared variable, so would be called var1. What is the current value of floatref? Pressing V, you see var0=4.
This for (strictly, do) block only has a single command, so the 1/1 is skipped. And so on. moveonescore(4), with all the arguments calculated and displayed, indicates either that the moveonescore script is currently running, if we do not have the top script on the stack selected; or if an error just caused the script debugger to open, then the error occurred while trying to run this command; otherwise (normally) this indicates that this command is about to be run (and will be run if you press S).
Here's another example:
plotscript, swap game key handler, begin if(keyval(key:BACKSPACE)>>1) then(toggle debug) if(switching) then (exit script) if(NPC is walking(cursor) || NPC is walking(satellite)) then (exit script) ...
swapgamekeyhandler:3/13 if ||(0,npciswalking(-299)
Operators like +, or, || are displayed in prefix notation: with the operator name first. Notice that the brackets don't match up. This is because the arguments to || are still being evaluated. The first argument, NPC is walking(cursor), has been calculated to be 0, and the interpreter has stopped right before, or encountered an error while calling npciswalking(-299).