Crashes
Common problems that may cause crashes in-game.
Dueling Inventory ChangesEdit
Using either RemoveMe or RemoveItem on an object in inventory immediately after adding the object will cause random crashes. To avoid this, delay the removal by several frames with a counter.
There is mounting evidence -- but no hard proof yet -- that multiple, frequent inventory changes may cause crashes if they happen too close together. For example, if you have multiple mods that rely heavily on adding and removing tokens from the player or nearby actors, you may encounter random crashes when one of these mods removes a token in the same frame that another mod adds a token. In theory, the chances of this happening would increase as the frame rate decreases.
There has been some suggestion that this problem might actually be related to another bug: Adding Multiple Items with the Same Script.
Deleted ReferencesEdit
If you delete any vanilla (Oblivion.esm) refs and another mod loads after yours that does anything with those refs that you deleted, the player will very likely get a crash on exit and/or a crash when reloading with a savegame made in another cell than the one he's currently in.
The solution is to never delete any vanilla (Oblivion.esm) refs. Move them and/or set them to be Initially Disabled instead. This won't work for an object with Parent References, so be sure to remove the Parent Reference from the object.
Shoving an object out of view by -30,000 Z units (arbitrary value) will put it far enough away that the game won't render it anyway.
See Undelete References for some tips about how to deal with this. See here and here for more details.
Nested If Versus AndEdit
Don't assume that if-tests stop at the first non hit. For example,
if (myref.isactor and myref.isincombat)
could cause a crash because myref.isincombat is always checked, even if myref isn't an actor. Use a nested IF statement instead.
Existing Object Names as Variable NamesEdit
Don't use existing object names as variable names. The existing ones get priority. If you write:
ref bed set bed to ThisBedref player.moveto bed
this will probably cause a CTD because 'bed' is also a topic id and will get priority here.
Other possible mistake names: enemy, accept, contract, creatures, gift, help, inventory, positions, placeholder, tasks, themage.
Quest TargetsEdit
Deleting a quest target will crash the CS. You can get around this by setting the conditions so that it's never displayed.
Referencing Deleted ObjectsEdit
It's easy to cause a crash by using a reference to an object that was deleted, or, in some cases to a dead actor.
For example, when using GetSelf in ScriptEffectUpdate or ScriptEffectFinish blocks for area of effect scripted spells, GetSelf can point to a dead body
This will cause a crash if you try a function that requires the object to be an actor, or even null if a summoned creature has been killed in the area.
Bow Reach BugEdit
This bug is fairly well-known but still crops up on occasion. The game will CTD if a bow with Reach = 0 is equipped by anyone (player or NPC). Some of the vanilla Oblivion bows have this problem, so be sure not to replicate the error in your mod.
SetLevel Bow BugEdit
Strangely this bug is mostly unknown (and the Bow Reach doesn't have to be zero to produce a CTD). It causes almost always a CTD if the player uses SetLevel on an actor that has a bow equipped or drawn and is inside the players cell (the CTD occurs as soon as the player visits or is in the cell where the actor was forced to reequip his bow due to SetLevel).
To avoid the CTD the actor has to be moved to a never-to-be-visited-cell to do SetLevel and then move the actor back to its origin. That can be done in a single frame.
Activate SelfEdit
When you script an object
- to Activate itself
- from a block that continously runs (i.e., GameMode, MenuMode, etc.)
- and not bypass the OnActivate block, as such:
begin GameMode Activate player, 1 end begin onActivate ...
you can cause an CTD. It seems that self-activation causes the entire script to run from the top, including the GameMode block, and so will Activate itself infinitely. You can prevent this by placing the OnActivate block before the self-activation, as such:
begin onActivate ... end begin GameMode Activate player, 1 end
It is also usually unwise to self-activate an object from within its OnActivate block with the OnActivate bit true, as this almost always leads to infinite recursion and a crash.
Wrong:
begin OnActivate ... Activate player, 1 end
Right:
begin OnActivate ... Activate player, 0 end
The default on that bit is zero, but it is a good practice to explicitly specify it as a reminder to yourself.
This situation arises (for example) if you have a container with a script that does something when activated but then lets the player or NPC go ahead and open the container in the usual way. The Activate call to actually open the container does not need to recurse into your OnActivate script.
Activating a Container (including NPC)Edit
If you meet all of these conditions:
- Activate a Container, so that you run its OnActivate block, that is:
YourContainer.Activate player, 1
- from an Object Script (and maybe a Magic Effect Script, but a Quest Script, direct activation, or dialog script would be safe)
- when a scripted item is in it (even a Scriptname declaration is too much)
you will get a CTD upon activation. The easiest way around it is to place the script on another object (an Activator, etc.) and activate it instead of the container. You can also use a Quest Script to activate the container, as such:
scn YourOpenerQuest ref rContainerToOpen float fQuestDelayTime begin GameMode if (fQuestDelayTime != .01) ;to activate the container quicker set fQuestDelayTime to .01 endif rContainerToOpen.Activate player, 1 StopQuest YourOpenerQuest end
and use this whenever you want to activate a container:
scn ActivatingScript set YourOpenerQuest.rContainerToOpen to YourContainer StartQuest YourOpenQuest
MessageBox on a Terminating ScriptEdit
You will very likely get a CTD if you open a MessageBox just before a script terminates. For example, if you have some scripted condition on an item that will force the player to drop the item, don't use a MessageBox in that condition.
scn MyItemScript begin gamemode If PCVampire MessageBox "You can't use this item while you're a vampire." Player.UnEquip MyItem Player.Drop MyItem 1 EndIf end
It seems that the script terminates after the drop (because it's attached to MyItem), but the MessageBox is still active so you get a CTD.
You can avoid this particular case by using Message instead of MessageBox:
If PCVampire Message "You can't use this item while you're a vampire." Player.UnEquip MyItem Player.Drop MyItem 1 EndIf
Which doesn't cause a CTD.
Edits to Tamriel cell (-47,-7)Edit
Any change to Tamriel cell AnvilMainEntrance (-47,-7) will not cause crashes in-game, but instead will cause Oblivion to crash on exit from the main menu. There may be other cells that also do this. The presence of the CELL record is enough; even if all the refs. are removed the crash will still occur if the CELL record is still present.