Jump to content

Proper use of cycles in Papyrus


KatArus

Recommended Posts

I've modified the vanilla script (along with all other necessary changes) to make Transmute spell into a channeling one. Spell channels and effect properly kicks in after 1 second of channeling. How do I properly put if-endif part in a cycle? Here's the executing part of the script:

 

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
objectReference caster = akCaster
if caster.getItemCount(Ore01) >= 1
; favor the less valuable ore first
Utility.Wait(1.0)
caster.removeItem(Ore01, 1, TRUE)
caster.addItem(Ore02, 1, FALSE)
advanceSkill("alteration",skillAdvancement)
elseif caster.getItemCount(Ore02) >= 1
; if none of that, look for the silver ore to upgrade
Utility.Wait(1.0)
caster.removeItem(Ore02, 1, TRUE)
caster.addItem(Ore03, 1, FALSE)
advanceSkill("alteration",skillAdvancement)
else
; caster must have had no valid ore
FailureSFX.play(caster)
failureMSG.show()
endif
endEVENT


Thanks.

Link to comment
Share on other sites

Does it compile? Does it run properly? If so, it should be fine.

 

That said, I've never liked doing Else with ElseIf. I'd re-do it to be as follows.

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    objectReference caster = akCaster
    if caster.getItemCount(Ore01) >= 1 || caster.GetItemCount(Ore02) >= 1
        if caster.getItemCount(Ore01) >= 1
            ; favor the less valuable ore first
            Utility.Wait(1.0)
            caster.removeItem(Ore01, 1, TRUE)
            caster.addItem(Ore02, 1, FALSE)
            advanceSkill("alteration",skillAdvancement)
        elseif caster.getItemCount(Ore02) >= 1
            ; if none of that, look for the silver ore to upgrade
            Utility.Wait(1.0)
            caster.removeItem(Ore02, 1, TRUE)
            caster.addItem(Ore03, 1, FALSE)
            advanceSkill("alteration",skillAdvancement)
        EndIf
    else
        ; caster must have had no valid ore
        FailureSFX.play(caster)
        failureMSG.show()
    endif
endEVENT

FYI - When you said 'cycle' the first thing that I thought about was going through an array or formlist and doing something to each entry. But that is not what is happening here.

Link to comment
Share on other sites

Maybe I was not clear enough. I want to make if-endif part to repeat itself indefinitely while the spell is being channeled, right now it runs only once, there is no cycle code in it yet.

 

It's actually Bethesda's vanilla script used for that spell, I just added a 1 sec delay, switched ore priority and remade the spell itself into a channeling one.

Link to comment
Share on other sites

When you say channeling, what do you mean? Concentration where the spell lasts while it is being cast rather than say fire and forget?

 

Only thing I can think of is to wrap it with a While statement, but you'd need to be able to determine that the spell is still being cast for it to work. And I cannot think of how you would best accomplish that. Maybe you could add a magic effect that is applied with the spell and use a check for that magic effect in the while statement.

Link to comment
Share on other sites

How are you detecting the end of the spell? That will determine what you need to do. You said "channeling" so does that mean the spell isn't still being cast after the 1 second? You'll either need a while loop or use OnUpdate events but it depends on whether the spell is being cast continuously.

Link to comment
Share on other sites

When you say channeling, what do you mean? Concentration where the spell lasts while it is being cast rather than say fire and forget?

 

Only thing I can think of is to wrap it with a While statement, but you'd need to be able to determine that the spell is still being cast for it to work. And I cannot think of how you would best accomplish that. Maybe you could add a magic effect that is applied with the spell and use a check for that magic effect in the while statement.

That's the point. Concentration spell that repeats scripted effect once per second while conditions are met. How to make a proper 'while' out of ActiveMagicEffect, RegisterForUpdate and OnUpdate or smth.

Link to comment
Share on other sites

If the spell is going to be cast as a concentration spell then you'll want to use OnUpdate. This is also one of the few times you'll use RegisterForUpdate (instead of RegisterForSingleUpdate) since the magic effect itself will automatically unregister when the player stops casting the spell. I haven't compiled or tested but here's how I would approach it. I also added an explicit UnregisterForUpdate as a failsafe but strictly speaking that isn't needed. The declaration for caster is moved outside of the start event so it's also visible to each update event.

ObjectReference caster

Event OnEffectStart(Actor akTarget, Actor akCaster)
    caster = akCaster
    if caster.getItemCount(Ore01) >= 1 || caster.getItemCount(Ore02) >= 1
        ; player has some ore so start the updates
        RegisterForUpdate(1.0)
    else
        ; caster must have had no valid ore
        FailureSFX.play(caster)
        failureMSG.show()
    endif
EndEvent

Event OnUpdate()
    if caster.getItemCount(Ore01) >= 1
        ; favor the less valuable ore first
        caster.removeItem(Ore01, 1, TRUE)
        caster.addItem(Ore02, 1, FALSE)
        advanceSkill("alteration",skillAdvancement)
    elseif caster.getItemCount(Ore02) >= 1
        ; if none of that, look for the silver ore to upgrade
        caster.removeItem(Ore02, 1, TRUE)
        caster.addItem(Ore03, 1, FALSE)
        advanceSkill("alteration",skillAdvancement)
    else 
        ; caster must have had no valid ore left
        UnregisterForUpdate()
        FailureSFX.play(caster)
        failureMSG.show()
    endif
EndEvent
Link to comment
Share on other sites

Event OnUpdate()  

I've tried fiddling with While, IsCasting, making triggers to start and stop when player casts specific spell, stops casting, gets and loses an effect both as caster and a target and a lot of other stuff to no avail. Bleh. Reminds me of the time when I wanted to make item degradation rate being dependent of player's Repair skill in FNV and ended up making 25 tier perk that changed it's tier level in real time based on player's current Repair skill AV because there was no more healthy and elegant solution. Guess I'll try this your way tomorrow. Thank you.

Link to comment
Share on other sites

Not the way I wanted it to function, but it works and I don't want to invest even more time in this mess of an engine on top of 5-6 hours that I already did.

 

I did resort to RegisterForUpdate(1.0) and Event OnUpdate() as triggers plus UnregisterForUpdate() and caster.InterruptCast() as breakers and everything seems to be fine.

 

Thank you, cdcooley and IsharaMeradin.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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