Jump to content

Doing something after all the events have fired


Recommended Posts

ScriptName MyFirstScript extends Quest

Actor Property PlayerRef Auto
FormList Property ArmorList Auto

int ArmorCount
Form[] ArmorForms

Event OnInit()
    ArmorForms = New Form[20]
    ArmorCount = 0

    RegisterForRemoteEvent(PlayerRef, "OnItemUnequipped")
    PlayerRef.UnequipAll()    
    UnregisterForRemoteEvent(PlayerRef, "OnItemUnequipped")

EndEvent

Event Actor.OnItemUnequipped(Actor akSender, Form akBaseObject, ObjectReference akReference)
    
    if akBaseObject as Armor
		ArmorForms[ArmorCount] = akBaseObject
		ArmorCount += 1
	Else
		RETURN
	endif

EndEvent

So I'm trying my hand at this scripting thing, and I've got a question I can't seem to find an answer anywhere.

As it is right now, this script fires several events because of one PlayerRef.UnequipAll().

Is there any way to call a function or do whatever only after all the Events have fired so I can do something with everything the Events collect?

Link to comment
Share on other sites

  • 1 month later...

So I'm trying my hand at this scripting thing, and I've got a question I can't seem to find an answer anywhere.

As it is right now, this script fires several events because of one PlayerRef.UnequipAll().

Is there any way to call a function or do whatever only after all the Events have fired so I can do something with everything the Events collect?

If you don't mind using F4SE, you could do this much more easily by looping through all the equipment slots with GetWornItem() to see if an armor is equipped there, and then doing UnEquipItemSlot() on each slot where an item is equipped. GetWornItem() returns a struct that holds the base object and other information about the worn item, so you could collect your ArmorForms using that. Like so:

Event OnInit()
    ArmorForms = New Form[0]
    
    Int slot = 0
    While slot < 30
        Actor:WornItem wornItem = PlayerRef.GetWornItem(slot)
        If (wornItem) && (wornItem.Item as Armor)
            ArmorForms.Add(wornItem.Item)
            PlayerRef.UnEquipItemSlot(slot)
        EndIf
        slot += 1
    EndWhile
EndEvent

I also changed your ArmorForms[] so it starts out as a zero-length array and grows as each form is added. This is slightly less efficient than preallocating a fixed array, but has the advantage that ArmorForms.Length gives you the number of forms so you don't need to track it separately.

Edited by Guest
Link to comment
Share on other sites

Quick observation

 

>if akBaseObject as Armor ; this tries to cast will generate debug log errors

 

should be

 

>if akBaseObject IS Armor ; this is a logical test will not generate errors

Link to comment
Share on other sites

With that sort of structure, the easiest thing is probably just to let a very short timer expiration handle it:

ScriptName MyFirstScript extends Quest

Actor Property PlayerRef Auto
FormList Property ArmorList Auto

Form[] ArmorForms

Event OnInit()
	ArmorForms = New Form[0]
	RegisterForRemoteEvent(PlayerRef, "OnItemUnequipped")
	PlayerRef.UnequipAll()
	UnregisterForRemoteEvent(PlayerRef, "OnItemUnequipped")
EndEvent

Event Actor.OnItemUnequipped(Actor akSender, Form akBaseObject, ObjectReference akReference)
	if (akBaseObject is Armor)
		ArmorForms[ArmorCount] = akBaseObject
		StartTimer(0.1)
	else
		RETURN
	endif
EndEvent

Event OnTimer(int aiTimerID)
	; nothing has restarted the timer in the last 0.1 seconds, so unequips are probably finished
	
	int i = ArmorForms.Length
	while (i >= 0)
		; do something with ArmorForms[i]
		i -= 1
	endwhile
	
	ArmorForms.Clear()
EndEvent
I do this sort of thing in a few places when I'm waiting for repeated events to stop, e.g. in the event handler for RegisterForAnimationEvent(PlayerRef, "WeaponFire"), so I can wait until a burst from something like a Gatling Laser is finished before I try running some longer code.
Link to comment
Share on other sites

Quick observation

 

>if akBaseObject as Armor ; this tries to cast will generate debug log errors

 

should be

 

>if akBaseObject IS Armor ; this is a logical test will not generate errors

No, the code will work as intended and will not generate script log errors. akBaseObject as Armor will simply return None if the cast fails, which means if akBaseObject as Armor will evaluate to false since a None object auto-casts to boolean false.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...