OnTriggerLeave unreliable? Not getting event :(

Post » Tue Mar 24, 2015 12:16 am

I can't seem to reliably receive OnTriggerLeave events. OnTriggerEnter always seems to get sent. I have no idea why this isn't working reliably.

For example, staves always seem to send an OnTriggerLeave event, but every other weapon I've tested won't. I've made the trigger large enough that the player can jump into the display case and prompt reliable trigger events but this is not an acceptable solution for me :(

http://i.imgbox.com/ux77GCm7.png. No editor objects or markers intersect it.

The trigger has this script on it:

Spoiler
Scriptname MDHDisplayCaseTriggerScript extends ObjectReference{Controls the enable state of the display case activator to allow for item retrieval}ObjectReference Property ActivatorRef Auto {The activator we must disable if there is already something in this trigger}auto STATE Waiting	EVENT onTriggerEnter(ObjectReference aktriggerRef)		ActivatorRef.Disable()		debug.notification("An object has entered this trigger")	endEVENT	EVENT OnTriggerLeave(ObjectReference aktriggerRef)		ActivatorRef.Enable()		debug.notification("An object has left this trigger")	endEVENTendSTATE 

Items get placed into the trigger from my container object which has this script on it:

Spoiler
Scriptname MDHDisplayScriptCONTAINERstaff extends ObjectReference  {Script for display cases specifically};Amethyst DeceiverBool Property Blocked = False  Auto HiddenObjectReference Property TriggerMarker Auto HiddenKeyword Property WRackTrigger AutoMessage Property MessageWarning  AutoMessage Property MessageCount  AutoKeyword Property ArmorShield  AutoKeyword Property WeapTypeDagger  AutoKeyword Property WeapTypeSword  AutoKeyword Property WeapTypeGreatSword  AutoKeyword Property WeapTypeStaff AutoKeyword Property WeapTypeWarAxe AutoKeyword Property WeapTypeMace AutoKeyword Property WeapTypeBattleAxe AutoKeyword Property WeapTypeWarhammer AutoKeyword Property WeapTypeBow AutoKeyword Property ClothingRing  AutoKeyword Property VendorItemPotion  AutoKeyword Property VendorItemPoison  AutoKeyword Property VendorItemGem  AutoKeyword Property ClothingNecklace AutoFormList Property ClawList  AutoFormList Property WhitePhial  AutoFormList Property PoisonList  AutoFormList Property UniqueJarList AutoInt Property PlacedItem = 0  Auto HiddenInt Property DisplayType = 1  Auto{1 = Weapon rack2 = Dagger case3 = Jewel display4 = Shield plaque5 = Potion/Poison6 = Dragon claw7 = COA weapon8 = Unique Jar9 = Necklace}ObjectReference ItemRefForm ItemBaseEvent OnItemAdded(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akSourceContainer)Actor PlayerRef = Game.GetPlayer()If (akSourceContainer == PlayerRef)  If (AllowedItems(akBaseItem))   If (aiItemCount == 1) && (PlacedItem == 0)        PlacedItem += aiItemCount        ItemBase = akBaseItem        ItemRef = akItemReference        RegisterForSingleUpdate(0.1)   Else        MessageCount.Show()        PlacedItem += aiItemCount        RemoveItem(akBaseItem, aiItemCount, False, PlayerRef)		;if I register for a single update in the OnItemRemoved Event it should force a recheck of the now singular item   EndIf  Else   MessageWarning.Show()   PlacedItem += aiItemCount   RemoveItem(akBaseItem, aiItemCount, False, PlayerRef)  EndIfElse  RemoveItem(akBaseItem, aiItemCount, False, akSourceContainer)EndIfEndEventEvent OnItemRemoved(Form akBaseItem, int aiItemCount, ObjectReference akItemReference, ObjectReference akDestContainer)If (akDestContainer == Game.GetPlayer())  UnregisterForUpdate()EndIfPlacedItem -= aiItemCountRegisterForSingleUpdate(0.1)			;This event only fires when the player attempts to add more than one item to the container, and when the player physically removes a displayed item.										;The latter won't have any object to "drop" but the MountCurrentItem function will still fire, is this bad?EndEventEvent OnUpdate()	MountCurrentItem(ItemBase, ItemRef)EndEventFunction MountCurrentItem(Form akBaseItem, ObjectReference akItemReference)	ObjectReference MountedItem	TriggerMarker = GetLinkedRef(WRackTrigger)		Int i = 0			If (akItemReference)				DropObject(akBaseItem)				MountedItem = akItemReference			Else				MountedItem = DropObject(akBaseItem)			EndIf			If (MountedItem != None)				Blocked = True				While(!MountedItem.Is3DLoaded()) && (i < 10)					Utility.Wait(0.1)					i += 1				EndWhile;Use MoveToNode		MountedItem.SetMotionType(Motion_Keyframed, False)			If MountedItem.HasKeyword(WeapTypeSword)				MountedItem.MoveToNode(TriggerMarker, "SwordPivot01")			endif			If MountedItem.HasKeyword(WeapTypeWarAxe)				MountedItem.MoveToNode(TriggerMarker, "WarAxePivot01")			endif			If MountedItem.HasKeyword(WeapTypeMace)				MountedItem.MoveToNode(TriggerMarker, "MacePivot01")			endif			If MountedItem.HasKeyword(WeapTypeGreatSword)				MountedItem.MoveToNode(TriggerMarker, "GreatSwordPivot01")			endif			If MountedItem.HasKeyword(WeapTypeBattleAxe)				MountedItem.MoveToNode(TriggerMarker, "BattleAxePivot01")			endif			If MountedItem.HasKeyword(WeapTypeWarhammer)				MountedItem.MoveToNode(TriggerMarker, "WarhammerPivot01")			endif			If MountedItem.HasKeyword(WeapTypeBow)				MountedItem.MoveToNode(TriggerMarker, "BowPivot01")			endif			If MountedItem.HasKeyword(WeapTypeStaff)				MountedItem.MoveToNode(TriggerMarker, "StaffPivot01")			endif			If MountedItem.HasKeyword(WeapTypeDagger)				MountedItem.MoveToNode(TriggerMarker, "DaggerPivot01")			endif				Utility.Wait(1)				Blocked = False				ItemRef = None			EndifEndFunctionBool Function AllowedItems(Form akBaseItem)If (DisplayType == 1)  Return (akBaseItem as Weapon)ElseIf (DisplayType == 2)  Return (akBaseItem.HasKeyword(WeapTypeDagger))ElseIf (DisplayType == 3)  Return ((akBaseItem.HasKeyword(ClothingRing)) || (akBaseItem.HasKeyword(VendorItemGem)))ElseIf (DisplayType == 4)  Return (akBaseItem.HasKeyword(ArmorShield))ElseIf (DisplayType == 5)  Return ((akBaseItem.HasKeyword(VendorItemPotion)) || (akBaseItem.HasKeyword(VendorItemPoison)) || (WhitePhial.HasForm(akBaseItem)) || (PoisonList.HasForm(akBaseItem)))ElseIf (DisplayType == 6)  Return (ClawList.HasForm(akBaseItem))ElseIf (DisplayType == 7)  Return ((akBaseItem.HasKeyword(WeapTypeSword)) || (akBaseItem.HasKeyword(WeapTypeGreatSword)))ElseIf (DisplayType == 8)  Return (UniqueJarList .HasForm(akBaseItem))ElseIf (DisplayType == 9)  Return (akBaseItem.HasKeyword(ClothingNecklace))EndIfEndFunction 

No idea where things are going wrong. Any suggestions/solutions/workarounds would be extremely welcome.

Halp!

User avatar
Guy Pearce
 
Posts: 3499
Joined: Sun May 20, 2007 3:08 pm

Post » Tue Mar 24, 2015 1:08 am



I have had trouble with the OnTriggerLeave event before and I don't remember if I found a fix for it. This is from the Wiki page. http://www.creationkit.com/OnTriggerLeave_-_ObjectReference
User avatar
Unstoppable Judge
 
Posts: 3337
Joined: Sat Jul 29, 2006 11:22 pm

Post » Tue Mar 24, 2015 5:48 am

Thanks, it's not a problem with the event getting sent out of order. Often the event never gets sent at all :(

EDIT: Although.... I probably should conditionalize any disabling by using http://www.creationkit.com/GetTriggerObjectCount_-_ObjectReference.

I was using that function in earlier versions of the script, perhaps I missed something.

EDIT2: Regardless, I still need those OnTriggerLeave events :/ (probably why I trimmed the superfluous condition)

User avatar
Hope Greenhaw
 
Posts: 3368
Joined: Fri Aug 17, 2007 8:44 pm

Post » Mon Mar 23, 2015 11:29 pm

There are definitely weird things happening with the OnTriggerLeave event.

Current trigger script:

Spoiler
Scriptname MDHDisplayCaseTriggerScript extends ObjectReference{Controls the enable state of the display case activator to allow for item retrieval}ObjectReference Property ActivatorRef Auto {The activator we must disable if there is already something in this trigger}auto STATE Waiting	EVENT OnTriggerLeave(ObjectReference akTriggerRef)            debug.notification("An object has left this trigger")		if GetTriggerObjectCount() == 0			ActivatorRef.Enable()			debug.notification("This trigger is now empty")			UnregisterForUpdate()		endif	endEVENT	EVENT OnTriggerEnter(ObjectReference akTriggerRef)			ActivatorRef.Disable()			debug.notification("An object has entered this trigger")	endEVENT	EVENT OnTrigger(ObjectReference akTriggerRef) 	;currently being triggered, no need for condition check			RegisterForSingleUpdate(4.0)	endEVENT	EVENT OnUpdate()									;need the condition check here in case something was removed and the OnTriggerLeave event was not sent		if GetTriggerObjectCount() == 0			ActivatorRef.Enable()			debug.notification("An update has detected an empty trigger")			UnregisterForUpdate()		endif	endEVENT		endSTATE 

The update event detects the empty trigger flawlessly.

:brokencomputer:

User avatar
Carlos Vazquez
 
Posts: 3407
Joined: Sat Aug 25, 2007 10:19 am

Post » Tue Mar 24, 2015 10:59 am


I'm not much of a scripter but could you use an OnContainerChanged event?
User avatar
Sabrina garzotto
 
Posts: 3384
Joined: Fri Dec 29, 2006 4:58 pm

Post » Tue Mar 24, 2015 7:07 am

Not really :(

The container the player interacts with immediately drops the item back into the world for positioning. To receive OnContainerChanged events....I'd either need a pretty complex quest to monitor activity, or I'd need to add scripts to every item being displayed.

......All that just to get around OnTriggerLeave events that I should be receiving anyway? As much as I hate it, I'd rather stick with the update loop - or scrap this feature entirely :confused:

EDIT: Gah, Bethesda do exactly the same thing in their vanilla display cases using WeaponRackTriggerSCRIPT (it's hidden). I cannot discern any differences of critical importance.

Here's the Beth script:

Spoiler
Scriptname WeaponRackTriggerSCRIPT extends ObjectReference Hidden import gameimport debugimport utilityKeyword Property WRackActivator Auto;The activator we must disable if there is already something in this triggerObjectReference Property ActivatorRef Auto Hidden;Reference that is currently in the triggerObjectReference Property RefCurrentlyInTrig Auto Hidden;1 = if something is in this trigger, 0 = emptyBool Property HasBeenTriggered Auto HiddenInt Property numInTrig Auto HiddenBool Property AlreadyInit Auto HiddenBool Property IgnoreArmor = FALSE AutoEVENT OnReset()	AlreadyInit = FALSE	;Trace("DARYL - " + self + " running OnReset() and AlreadyInit = " + AlreadyInit)endEVENTEVENT OnLoad()	;Trace("DARYL - " + self + " running OnLoad() and AlreadyInit = " + AlreadyInit)	if (AlreadyInit == FALSE) && (self.IsEnabled())		ActivatorRef = GetLinkedRef(WRackActivator)		if (ActivatorRef)			ActivatorRef.Enable()		endif		ActivatorRef = NONE		AlreadyInit = TRUE		;Trace("DARYL - " + self + " The Activator Ref is " + ActivatorRef)	else		;Do nothing	endif	;Trace("DARYL - " + self + " finishing OnLoad() and AlreadyInit = " + AlreadyInit)endEVENT;EVENT OnCellLoad();	;Trace("DARYL - " + self + " running OnCellLoad() and AlreadyInit = " + AlreadyInit);	if (AlreadyInit == FALSE) && (self.IsEnabled());		ActivatorRef = GetLinkedRef(WRackActivator);		AlreadyInit = TRUE;		;Trace("DARYL - " + self + " The Activator Ref is " + ActivatorRef);	else;		;Do nothing;	endif;	;Trace("DARYL - " + self + " finishing OnCellLoad() and AlreadyInit = " + AlreadyInit);endEVENTauto STATE WaitingForReference	EVENT onTriggerEnter(objectReference triggerRef)		;Trace("DARYL - " + self + " Just OnTriggerEntered by " + triggerref)				if (IgnoreArmor == TRUE) && (triggerRef.GetBaseObject() as Armor)			;Trace("DARYL - " + self + " I'm ignoring armor, and this is armor, so I'm doing nothing.")			;Do Nothing		else			;Trace("DARYL - " + self + " I'm updating as normal")			;numInTrig = (numInTrig + 1)			HasBeenTriggered = TRUE			ActivatorRef = GetLinkedRef(WRackActivator)			if ActivatorRef				ActivatorRef.Disable()			endif			ActivatorRef = NONE		endif						endEVENT	EVENT OnTriggerLeave(objectReference triggerRef)		;Trace("DARYL - " + self + " A References has EXITED, refs in this trigger now = " + numInTrig)				if (IgnoreArmor == TRUE) && (triggerRef.GetBaseObject() as Armor)			;Trace("DARYL - " + self + " I'm ignoring armor, and this is armor, so I'm doing nothing.")			;Do Nothing		else			;Trace("DARYL - " + self + " I'm updating as normal")			;numInTrig = (numInTrig - 1)		endif		if (GetTriggerObjectCount() == 0)			ActivatorRef = GetLinkedRef(WRackActivator)			HasBeenTriggered = FALSE			ActivatorRef.Enable()			ActivatorRef = NONE		endif	endEVENTendSTATE 
User avatar
Ross
 
Posts: 3384
Joined: Thu Aug 10, 2006 7:22 pm


Return to V - Skyrim