Difference between revisions of "Crashes"
imported>Dev akm (→MessageBox on a Terminating Script: attached to MyItem) |
imported>Dev akm |
||
Line 93: | Line 93: | ||
If PCVampire | If PCVampire | ||
MessageBox "You can't use this item while you're a vampire." | MessageBox "You can't use this item while you're a vampire." | ||
Player.UnEquip | Player.UnEquip MyItem | ||
Player.Drop | Player.Drop MyItem 1 | ||
EndIf | EndIf | ||
end | end | ||
Line 104: | Line 104: | ||
If PCVampire | If PCVampire | ||
Message "You can't use this item while you're a vampire." | Message "You can't use this item while you're a vampire." | ||
Player.UnEquip | Player.UnEquip MyItem | ||
Player.Drop | Player.Drop MyItem 1 | ||
EndIf | EndIf | ||
Revision as of 20:28, 9 October 2007
Troubleshooting Crashes (CTDs)
Common problems that may cause crashes.
Nested If Versus And
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 Names
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 Targets
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 Objects
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 Bug
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.
Activate Self
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 onActive ... end begin GameMode Activate player, 1 end
Activating a Container (including NPC)
If you meet all of these conditions:
- Activate a Container, so that you run it's OnActivate block, that is:
YourContainer.Activate player, 1
- from an Object Script (and maybe a Magic Effect Script, but a Quest Script or direct activation 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 Script
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.