Jump to content

Photo

Doing something after all the events have fired


  • Please log in to reply
4 replies to this topic

#1
superfranky

superfranky

    Regular

  • Members
  • PipPip
  • 55 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?



#2
Tri0xin

Tri0xin

    Enthusiast

  • Members
  • PipPip
  • 107 posts

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 Tri0xin, 01 August 2020 - 07:25 AM.


#3
SKK50

SKK50

    Institutum delenda est

  • Premium Member
  • 4,318 posts

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 



#4
IDontEvenKnow

IDontEvenKnow

    Faithful poster

  • Premium Member
  • 1,265 posts
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.

#5
Tri0xin

Tri0xin

    Enthusiast

  • Members
  • PipPip
  • 107 posts

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.






Page loaded in: 0.934 seconds