FAQ: My Script Doesn't Work!

From the CreationKit Wiki
Jump to navigation Jump to search

Overview

This is a page for the community to document common pitfalls, mistakes, and best practices when working with Papyrus.

Acclimating to Papyrus can be a difficult process - this page is here to help! The goal of this page is to collect the most common stumbling blocks and hurdles we all encounter when trying to work with Papyrus scripts, especially early on.

Your contributions matter! If you've found a way around some sticking point, please add to this FAQ. Links are strongly encouraged here as are code fragments to demonstrate what you're talking about.

FAQ

General

My Script compiles, but doesn't work! How can I debug this?

When you begin working with Papyrus, you'll want to activate script logging. This feature is disabled by default - most users don't need it, and logging consumes a small amount of your PC performance in-game.

Enabling Logging is a matter of changing a few ini settings. Open (or create) your SkyrimCustom.ini file in .../My Documents/My Games/Skyrim. Add the following lines to that file. If any of these lines already exist, just make sure they are toggled to "1" instead of "0".

[Papyrus]
bEnableLogging=1
bEnableTrace=1
bLoadDebugInformation = 1

bEnableLogging toggles the entire script logging system; bEnableTrace enables Debug.Trace and related functions, and bLoadDebugInformation will load line number information so you can more easily pinpoint errors.

With these settings on, the game will create a new folder at “...\My Documents\My Games\Skyrim\Logs\Script”. (If you don’t see the Script folder, you may need to launch the game a second time) Your logs will appear inside that folder, named Papyrus.#.log with the # number going from 0 to 3. The 0 log is always the newest with older logs cycling through the increasing numbers.

The game should now be outputting some basic information, as well as any errors and trace statements to the Papyrus.0.log file while the game is running, so you should be able to keep an eye on it with your favorite text editor.

If the game detects an error in a script, it will output it in the following format:

<timestamp> <error message>
stack:
  <function 0> - "<filename>" Line <line number>
  <function 1> - "<filename>" Line <line number>
  <function 2> - "<filename>" Line <line number>
  ...

Function 0 - the one at the “top” of the stack list - is the function that caused or reported the error. Function 1 is the function that called Function 0. Function 2 called Function 1, and so on. This will help you track down what might be the cause of any issues that are reported.

But maybe you don’t see any errors. What do you do then? Well, you can take advantage of various Debug functions, for example Trace and TraceStack, to help figure out what your script is doing, and what values your various variables or properties have. For an example, take a look at the following function:

Function MyFunction(int coolValue)
  Debug.Trace("My function called! Coolvalue = " + coolValue)
  If (coolValue == 20)
        Debug.Trace("Cool value is 20! Doing some neat stuff now!")
        ; Do neat stuff!
  EndIf
EndFunction

Once you’ve added trace statements to your function, you can now look at your log to try to pin down what is going wrong. Do you never see “My function called!” in the log? Then whatever is supposed to call your function isn’t happening, so you’ll have to keep looking. Do you see that line but you don’t see “Cool value is 20!”? Then you’ll have to figure out why the value isn’t what you wanted it to be. And you’ll note that in the example, we actually trace out the value of the variable by simply “concatenating” it with the “+” operator.

Skyrim also includes console commands that can help you track down what might be the problem. If your script is attached to a quest, type in “sqv <quest>” into the console to get a list of every Papyrus script attached to the quest, and the contents of all its variables and properties. If your script is attached to a reference, target the reference with your mouse while the console is up (or use the “prid <reference id>” command) and then type in “sv” to see the same amount of information, but for the reference. (PgUp and PgDown scroll the console output!) If your script is supposed to be registered for update events, type in “dpu” to have the game dump a list of every single updating form to the Papyrus log so you can see if your script is there. Or, if you think your script might actually be stuck inside an infinite while loop, or taking a while to respond, “dps” will dump everything Papyrus is currently doing to the log for your analysis.

Object Creation

I Cannot create a new object

  • Problem: I can't create a new object.
  • Explanation: Papyrus currently does not support the instantiation of objects within script; the new keyword only works for arrays, not objects (unlike Java, for example), and constructors do not seem to work.
  • Solution: For a workaround, you could try casting a PlaceAtMe ObjectReference as your desired object. Of course your object must extend ObjectReference for this to work.

Can't cast an object as its child

  • Problem: I can't cast an object as its child. For instance, casting an ObjectReference as a TestReference when TestReference extends ObjectReference.
  • Explanation: Casting will only work if the reference casted actually has its script attached. For instance, the TestReference base object needs to have the TestReference script attached in the editor form window for it to be castable from ObjectReference to TestReference.
  • Solution: Use the editor and attach the script to the object you're actually casting. For instance, if TestReference is supposed to refer to a book, open up the book you want to cast in the editor window, goto the scripts section, and attach the TestReference script from there.

Quests

I can't get my alias to point to a reference

  • Several possibilities here:
    • The reference doesn't actually exist. Did you make sure that a PlaceAtMe command actually generated a reference? Check using Debug.Trace(theReference).
    • An alias is pointing to an object in a container. Evidently this does not work (creating a persistent reference using PlaceAtMe, and pointing the alias to the persistent reference). Solution: don't put the object in the container, or point to the container and get the object that way (not completely tested).
    • You created an alias for a quest that is already running (i.e. dirty save) - even if you are simply adding an additional alias to an already running quest, you can't get the alias to actually point to anything (despite the fact that Debug.Trace happily shows that it exists, which is horribly misleading). Solution is to make a clean save and remove the quest, then add it back.