Debug Dumps
Overview[edit | edit source]
There are various functions in NVSE that allow you to dump debugging information from any game to a text file. This is highly useful when attempting to solve third party bug reports, as all the information you need may be provided by the user simply uploading you a text file, created by running a script which could be triggered by clicking an MCM button, or by console adding some object or spell, etc.
This article describes a template of useful features you may want to include in a debug dump script.
Start[edit | edit source]
scn CreateDebugDump
int LastEcho
int iTotalMods
int iIndex
array_var UT
array_var aQuests
array_Var aObjects
array_var entry
string_var file_name
string_var svkey
string_var FO_dir
ref rQuest
ref rObject
Begin Function { }
A User Defined Function is a convenient way to run the script, although it could just as easily be on object OnAdd or spell ScriptEffectStart. Above is the variable declaration for the proceeding examples.
File naming[edit | edit source]
let file_name := "MyModName-Debug-Dump-"
let UT := GetUserTime
foreach entry <- (Ar_List "Year", "Month", "Day", "Hour", "Minute", "Second")
let svkey := entry["value"]
if eval svkey == "Hour"
let file_name += "-"
endif
let file_name += "-" + $UT[svkey]
loop
let file_name += ".txt"
con_SCOF $file_name
Print "Starting debug dump to file: " + file_name
A String Variable and the GetUserTime function can be used to create a unique and recognizable file name for your dump, based on your mod name and the real life time it is created. The Con_SCOF command writes all console output to the specified file, which will be found in the main game directory of the user. The Print command outputs text to the console, and supports many convenient features. (See also the string variables tutorial)
The debug dump file name will look like: "MyModName-Debug-Dump-YEAR-MONTH-DAY--HOUR-MINUTE-SECOND.txt"
Versions[edit | edit source]
; * Versions
Print "My Mod Version: " + $MyModMainQuest.version
Print "My Mod's Master Version: " + $MyMasterMainQuest.version
Print "NVSE Version: " + $(GetNVSEVersion) + "." + $(GetNVSERevision) + "." + $(GetNVSEBeta)
Print "NX (An NVSE plugin) Version: " + $(NX_GetVersion)
It is helpful to reliably know what version of your mod, and any requirements it might have that the user has installed. The ToString($) command converts anything to a string for printing. Notice Print allows direct printing of quest variables and function returns (eg: $(GetNVSEVersion), the added brackets allow clear distinction of functions).
Load Order[edit | edit source]
; * Load Order
Print "Load Order:"
let iTotalMods := GetNumLoadedMods
let iIndex := 0
while iIndex < iTotalMods
Print (NumToHex iIndex, 2) + " (" + $iIndex + "): " + (GetNthModName iIndex)
let iIndex += 1
loop
Print " * End Load Order *"
By using GetNthModName you can find out for certain what a user's load order is. This prints all loaded mods with their index in both hexadecimal and decimal. (See also: GetNumLoadedMods, While, NumToHex)
Quest Statuses[edit | edit source]
; * Quest statuses
let aQuests := Ar_List MyQuest1, MyQuest2, MyQuest3 ... MyQuest20
let LastEcho := SetConsoleEcho 1
foreach entry <- aQuests
let rQuest := entry["value"]
Print "Quest: " + $rQuest
con_SQV rQuest
Print " * * * * * "
loop
SetConsoleEcho LastEcho
The Con_SQV command human readably prints the name and value of all variables attached to a quest (except array_var and string_var, which you get the ID number, not contents), and it's current running status, stage and priority. You need to use SetConsoleEcho before calling it, however.
Above, we create an array with Ar_List and put all the quests we want to dump in it. You can specify up to 20 entries in one Ar_List call, see the arrays tutorial if you want more than 20 entries. Then we print the name of the quest '$rQuest' and do Con_SQV for each one.
Object Script Variables[edit | edit source]
; * Object Variable Statuses
let aObjects := Ar_List SunnyREF, MyActorREF, MyDoorREF, PlayerREF...
let LastEcho := SetConsoleEcho 1
foreach entry <- aObjects
let rObject := *entry ; '*' is shorthand for entry["value"]
Print "Variables for " + $rObject
Con_ShowVars rObject
Print " * * * * * "
loop
SetConsoleEcho LastEcho
The function, Con_ShowVars is similar to Con_SQV for quests; it prints the name and value of all variables in object scripts attached to the reference (including those on their inventory items). It also requires console echo to be toggled on.
Actor Inventory[edit | edit source]
; * Player inventory
Print "Player Inventory: "
let LastEcho := SetConsoleEcho 1
PlayerREF.Con_Inv
SetConsoleEcho LastEcho
Print " * End Inventory *"
The Con_Inv command is equivalent to typing Inv into the game console to print the contents of an inventory. This command also requires console echo to be toggled on. (You can just toggle it on once at start, if you need it multiple times)
Array dumping[edit | edit source]
Ar_Dump SomeQuest.SomeArray
If you have some arrays you want to read, you can use Ar_Dump, or call some UDF that does a more bespoke version.
Player Actor Values[edit | edit source]
; * Player Actor Values
Print "Player Actor Values: "
let iChoice := 0
while iChoice < 73
Print $iChoice + " (" + (ActorValueToStringC iChoice) + "): " + $(PlayerREF.GetAV iChoice)
let iChoice += 1
loop
Print " * End Actor Values *"
To use this convenient code, you need to use the Script Compiler Override to allow you to reference Actor Values by their int codes. It prints the code number, the language localized name, and value for all the player's actor values.
Player NX variables[edit | edit source]
; Player NX variables
Print "Player NX variables: "
foreach entry <- (Ar_List (PlayerREF.NX_GetEVFlAr ""), (PlayerREF.NX_GetEVFoAr ""), (PlayerREF.NX_GetEVStAr ""))
Ar_Dump entry["value"]
loop
Print " * End Player NX variables *"
If you are using the NX NVSE plugin, you can dump the name and value of every NX variable stored on the player like this. Replacing the "" empty strings with your mod prefix allows you to only dump relevant ones.
Misc[edit | edit source]
; * Misc
Print "GameDaysPassed: " + $GameDaysPassed
Print "Hardcore mode: " + $(PlayerREF.IsHardcore)
Print "Player Level: " + $(PlayerREF.GetLevel)
You can print anything else that might be useful.
End[edit | edit source]
; * End
Print "*** All done! ***"
let FO_dir := GetFalloutDirectory
MessageBoxEx "My Mod completed a debug dump, please upload the file '%z' to me, which is in your FNV main directory ('%z')" file_name, FO_dir
Sv_Destruct file_name, svkey, FO_dir
End
Finally, you can use MessageBoxEx (which sadly requires String Formatting unlike Print) to notify the user with your instructions, and tell them what the dump file is called and where they can find it, by using GetFalloutDirectory to return thier FNV main directory. You then need to Sv_Destruct the local string variables or they can cause save game bloat.