Causes of CTDs

From the Fallout3 GECK Wiki
Jump to navigation Jump to search

Crashes to desktop (CTDs) can be difficult to track down, this page describes methods of debugging, and potential causes and workarounds.

Much of the information on this page should be viewed as just worthwhile lines of investigation when debugging, sourced from personal experiences, not as proven causes.

Debugging[edit | edit source]

The console command SCOF can be used in game, or via a script with Con_SCOF to write all console output to a text file in the fallout game directory. This is very useful as it allows you to trace output to the point of CTD back in Windows.

; within game console, type:
scof "mydebuglog.txt"

Infinite loops[edit | edit source]

The most common cause of CTDs is probably infinite loops, caused when a loop condition never becomes false. With NVSE, it is good practise to replace all usage of Label with Foreach or While. Where possible, putting condition modifiers at the beginning of the loop is recommended, to avoid them potentially being skipped by conditional usage of Continue or Goto. Indentation of any loop block is highly recommended.

Looping quest stages may also be potentially non-terminating.

Invalid references[edit | edit source]

Some functions may cause a CTD if run on an invalid reference, such as a ref variable which is empty, contains a base form, or is non-persistent and non-loaded. This may be avoided by checking the variable contents with a condition, such as IsReference, IsFormValid, TypeOf, GetType.

ref MyRef
if IsReference MyRef
  ; safe to proceed, MyRef is valid reference
endif

To catch empty ref variables, you can do just:

if MyRef

But, this will not catch base forms if you need a reference.

Some functions are not instant to effect[edit | edit source]

Some functions, particularly those that modify the 3D world, do not necessarily take effect instantly, they can potentially take several (an unpredictable number) of frames to complete. This can result in the invalid reference situation described above. For example:

set FirstRef to PlayerREF.PlaceAtMe Something
SecondRef.MoveTo FirstRef
FirstRef.Disable
FirstRef.MarkForDelete

Note also that RemoveMe and Dispel are not instant, and a script may run for several frames after its parent object/spell was removed, with unpredictable behavior. To protect against this, you can use:

int Completed

Begin GameMode
    if Completed
        return
    endif

    ; * do something
    set Completed to 1
    RemoveMe
End

BuildRef might not return what you expect[edit | edit source]

The BuildRef function allows you to reference assets of an external mod without making that mod a master to your own plugin. However, it can potentially return an invalid or unexpected reference, and crash the game if you do not bother to check for this. See the BuildRef function article for full details.

Unexpected returns during immediate game start up[edit | edit source]

It has been observed on a few occasions where scripts running in early game startup, or sometimes just on their first scan return <NULL> for an actor. With all the DLC's booting up, I've experienced such failures up to 10 seconds after gamestart, things like a female player returning zero for GetIsSex Female.

Invalid string formatting[edit | edit source]

Using invalid format specifiers or mismatched number of arguments to format may crash the game (and at best the script), for example:

DebugPrint "GunScript %n: Shooting %2.0 bullets" rActor iBullets
; you meant "%2.0f" but missed the f

If using NVSE, it is safer to use string concatanation and the ToString function where possible, instead of formatting. See String Variable for more information.

Invalid And/Or syntax for conditions[edit | edit source]

Invalid And/Or syntax will still compile, but will crash the script and possibly the game when it runs, for example:

if A==B && D < 1 && && W >= 7
               ; above ; 

EDIT (09/01/15): This comes from my personal experience. Sometimes absurd wrong syntax compile (so never fully trust 100% the compiler or PU). But mainly, some of them don't CTD in game and silently break the script execution, making the debug pretty hard.

Here an example, a mistake I did more than once because of copy/paste:

if (something) || (something else) || (some other thing) ||

(I left an extra || at the end) - This line was compiling, but it wasn't CTD in game, it was interrupting the rest of the script from that line to the end. I use vanilla + 4Gb + NVSE + PU, so it's not like NVAC preventing CTD or whatever. Also I noticed how some script mistakes CTD in FO3, while don't CTD in NV but they interrupt the script execution. And not because of FOSE / NVSE, I'm talking about vanilla script.

NPC outfit scripts that modify inventory[edit | edit source]

If you get an object script attached to an outfit worn by an NPC to add or remove any item from that NPC, it can cause a CTD. It's not an immediate CTD, you get funny colors & sounds, it's CTD on Drugs, and for other items sometimes just game freezes. Exactly the same script works fine on the Player though. I found this in doing damaged armor swapping- the only way to get it to work was have the token cast a scripted effect, with the effect script allowing adding or removing of items without crashing.

Removing an object whilst its script is in progress[edit | edit source]

If you have an object whose script calls a User Defined Function, and that UDF removes the object this will cause a CTD. This may be because the calling script for the UDF has been destroyed with its parent object, so its execution can not continue following the UDF call. It is better to use RemoveMe within the object's script, based on a return value for the function.

Nested function calls[edit | edit source]

If using the Script Compiler Override, it is possible to nest multiple function calls on a single line, rather than use intermediary variables. Sometimes this causes a CTD, which is avoidable by using multiple lines.

Single line And/Or conditions[edit | edit source]

Using And/Or (&& / ||) to evaluate too many conditions on a single line has been noted to cause a CTD when testing multiple UDFs or NVSE string comparisons. Separating the condition into multiple lines, or changing to a single UDF call, which itself checks all the conditions on single lines works around this.

Note also that the GECK does not short circuit and/or conditions when they become proven, all conditions on the line are always evaluated.

Animations[edit | edit source]

(ADDED 09/01/15) This is not about scripting, but still a cause of CTD, I would say it's common among users. When a .kf (animation file) calls a movement on a bone which is not present in the skeleton, this usually leads to a CTD. However you don't need to have a body /armor rigged on that bone, to avoid it, only have the right skeleton. This is the reason why in many mods the modders want you to install a compatibility skeleton, because it has all the possible bones used among different mods.

Animations - Textdatas[edit | edit source]

Curious to notice how an empty (wrong) textdata could lead to a GECK CTD when it's previewed on the render window, but it will be ignored in game and will work fine.

Worldspace Navmeshes[edit | edit source]

Having uncaught errors in a navmesh that is in an exterior location can cause CTD on load of any save. This effect can be delayed by up to nearly a minute in some cases. It is also possible for this to happen if you manipulated an error free navmesh and forgot to finalize it.

This may be due to bad navmesh info and can sometimes be fixed by deleting the navmesh infos for your exteriors in FO3Edit and letting GECK re generate them. It is unknown if this creates other issues but it has been observed to resolve CTD on load without creating any additional GECK errors and does not require physically recreating your actual navmesh.