Debug Scripts

Revision as of 08:17, 13 November 2006 by imported>AdiBeiElderScrolls

The debug process with CS is quite time consuming and the provided tools are not really satisfying.

So here are some hints, how to debug scripts in case you have unexpected results

Script Processing

First of all, you should take a look at the Script Processing article, to get a basic understanding, how the different script types are working.

Remember, that only quest scripts are considered to run constantly in a defined schedule.

Object scripts may run every frame, but they also may not execute for quite a while, if player is not near. Even there are cases, where AI packages prevent script running. This is true for Follow-Packages if they check on conditions related to script variables in the same object and these conditions are satisfied.

To find out, if your script is executed, simply put a code like the following into your script and control it afterwards ingame

; use long, if you want to watch the frames 
; for a longer time period
short FramesRun

Begin GameMode
Set FramesRun To FramesRun + 1

... your code

End

Control variable content

There are different ways, to control the current content of your variables.

The most convenient and reliable way is using the Console Functions, especially prid and tst or sv. You always will get the real current content.

So, first activate or focus the object, you want to examine (talk to your NPC, open the book ...) then open the console. You now will see in the upper part of the screen the formID of your object. If not, point to the object with your mouse.

The prid command will change to any object given, so if you want to examine your NPC script and your NPC has shown a formID of 0b002089 you simply enter:

prid 0b002089

If you have not too much variables in the script, than you can use the ShowVars/sv command to show the content of all variables. Simply type

sv

If you use many variables, you may only see the last ones, that have been declared.

To get a special variable content, use the Show/tst command. So if you want to control how much times the script has executed until now, if you have set a FrameRuns variable, you just type:

show FrameRuns

If that variable is not getting bigger and bigger everytime you leave the console and enter it again, you may just have the case, that some AI package is preventing your script from running.

Take care, if you use Message or MessageBox functions inside of your script!

The delay of the Message function will cause, that the displayed values are not the current ones. Moreover, the first time every message is executed in the script, it will be delayed. Every further execution (next frame) leads to messages running at the top of screen to fast to follow. To make sure, that you can watch all messages for every frame, use some dialog function like ShowEnchantment at the end of the code block to examine.

But always keep in mind, that the values shown in the message, are NOT the current values.

MessageBox behaves in another way. If you want to have different message boxes, that pop up to show some variable content, you may end up with having only the last defined message box shown and all other ignored. Don't ask me why, but it seems to work this way

At least MessageBox gives you the current values in the script.

Find bugs not reported by CS or Oblivion

CS usually gives you some hints, when you save a script. But this is not reliable at all. It only reports errors, where you try to access objects, that definitely do not exist.

You still can make syntax errors, that are not discovered or use functions, that work as a return statement.

Ingame you won't get a message about a problem, except that your script seems not to do, what it should do. But if the interpreter for the script finds some errors, it just will cancel script execution at the point, where the error is found.

It took me a whole day to find out, why my script was not executed. And the reason was, that I mixed the commands GetCurrentAIPackage and GetIsCurrentPackage.

So the statement

If ( GetCurrentAIPackage "00MyPackage1" )
   Set PackageLoaded To 1
ElseIf ( GetCurrentAIPackage "00MyPackage2" )
   Set PackageLoaded To 2
...

caused the interpreter to leave the script, whenever it reached this code block. If you wonder about the "00MyPackage", the apostrophes are recommended, whenever your EditorIDs start with a number. I used two zeros to have my objects always listed at the top

And it was right, because what I meant to do was the following

If ( GetIsCurrentPackage "00MyPackage1" )
   Set PackageLoaded To 1
ElseIf ( GetIsCurrentPackage "00MyPackage2" )
   Set PackageLoaded To 2
...

But the script saved without any problems and ingame I didn't get a message, that something went wrong.

In this cases, it is recommended to use the Message function. Put a message after each code block to see, where the script stops execution, just like

If WhatEverCondition1
  ... your code
EndIf
Message "WhatEverCondition1 executed"
If WhatEverCondition2
  ... your code
EndIf
Message "WhatEverCondition2 executed"

--AdiBeiElderScrolls 07:58, 13 November 2006 (EST)