FAQ: My Script Doesn't Work!
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.
I can't remove an item from a player
- If you are using AddItem with a negative value, that does not seem to work (even though it works in the console). Use RemoveItem instead and check for the sign with a conditional.
My script can't compile and all I'm using is an Editor ID!
Properties. You need them. Read up on them.
My mod works for me, but not for anyone else!
That sounds like a packaging problem. Consider the following:
- Did you accidentally leave out any meshes or textures? Textures might not cause an outright crash, but will definitely make things look weird (i.e. purple). Missing meshes may lead to graphical anomalities or outright crashes. Check also that the paths in your meshes are relative, not absolute (If you see "program files" or something in your textures, then something is wrong).
- Are you using a custom script that extends another custom script? There is a [1] in the .bsa packager where if the parent custom script is not actually present in a base form in the game, then it will not be listed in the file selector for the packager. The solution is to create a dummy mesh that has the parent script attached, or manually include it in the .bsa on build.
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. Simply removing the quest via console and adding it back may also work (unverified).
I can't add a property to a script fragment!
- You need to define the property through the Properties window for a script fragment before it can work in the script. To do this:
- Remove all references of the property from your script and compile. Use a blank script (;comment) if you need to.
- You may need to rename the script to get the Properties window to work.
- Click on the properties window on the lower right side (next to TIF_) to add the new property.