Debug Dumps
Overview
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
scn fnCreateDebugDump int LastEcho int iTotalMods int iIndex array_var UT array_var aQuests array_var entry string_var file_name string_var svkey string_var FO_dir ref rQuest ref rItem int iChoice int iCount 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
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.
The debug dump file name will look like: "MyModName-Debug-Dump-YEAR-MONTH-DAY--HOUR-MINUTE-SECOND.txt"
Versions
; * 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
; * Load Order Print "Load Order:" let iTotalMods := GetNumLoadedMods let iIndex := 0 while iIndex < iTotalMods Print (NumToHex iIndex) + " (" + $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
; * 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.
Array dumping
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 Inventory
; * Player inventory Print "Player Inventory: " let iChoice := PlayerREF.GetNumItems while iChoice > 0 let iChoice -= 1 let rItem := PlayerREF.GetInventoryObject iChoice let iCount := PlayerREF.GetItemCount rItem Print $rItem + " (" + (GetFormIDString rItem) + ") : " + $iCount loop Print " * End Inventory *"
The above is similar to typing Player.inv into the game console, but unfortunately you can't do that from a script. It prints the name, formid and count of every item in the player's inventory. (See also: GetInventoryObject, GetNumItems)
Player Actor Values
; * 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
; 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
; * Misc Print "GameDaysPassed: " + $GameDaysPassed Print "Hardcore mode: " + $(PlayerREF.IsHardcore) Print "Player Level: " + $(PlayerREF.GetLevel)
You can print anything else that might be useful.
End
; * 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.