OnEffectFinish does not always fire

Post » Thu Jun 21, 2012 12:56 pm

I have a spell that's applied as a constant effect with a condition on the effect in the spell setup of IsRunning == 1. Here's the source of the effect script:

Scriptname mm_BeluaVampireSprintScript extends activemagiceffect import debugGlobalVariable Property BeluaGlobalCurrentVampireLevel AutoGlobalVariable Property BeluaSatiatedStage AutoGlobalVariable Property BeluaVampireSprintImodStrength AutoImageSpaceModifier Property mm_BeluaSprintIntroImod AutoImageSpaceModifier Property mm_BeluaSprintMainImod AutoImageSpaceModifier Property mm_BeluaSprintOutroImod AutoActor CasterFloat originalSpeedFloat previousSpeedFloat SprintMod = 0.0bool EffectFinished = falsefloat ImodStrengthfloat totalincreaseEvent OnEffectStart(Actor target, Actor akCaster)ImodStrength = BeluaVampireSprintImodStrength.GetValue() as FloatCaster = akCaster; Kill the imods from previous if still running...like berzerk scriptmm_BeluaSprintIntroImod.Remove()mm_BeluaSprintMainImod.Remove()mm_BeluaSprintOutroImod.Remove()mm_BeluaSprintIntroImod.Apply(ImodStrength)int level = BeluaGlobalCurrentVampireLevel.GetValue() as intoriginalSpeed = akCaster.GetActorValue("speedMult")previousSpeed = originalSpeedTrace("CurrentLevel: " + level)Trace("originalSpeed: " + originalSpeed)if level == 1  ; 10% Increase  SprintMod = (1.10 * originalSpeed) - previousSpeedelseif level == 2  SprintMod = (1.15 * originalSpeed) - previousSpeedElseIf level == 3  SprintMod = (1.20 * originalSpeed) - previousSpeedElseIf level == 4  SprintMod = (1.25 * originalSpeed) - previousSpeedElseIf level == 5  ; 50% Increase  SprintMod = (1.30 * originalSpeed) - previousSpeedEndIfTrace("SpeedMultUp: " + SprintMod)totalincrease = SprintMod;Utility.Wait(1.75)mm_BeluaSprintIntroImod.PopTo(mm_BeluaSprintMainImod,ImodStrength)akCaster.ModActorValue("SpeedMult", SprintMod)akCaster.ModActorValue("CarryWeight", -1)akCaster.ModActorValue("CarryWeight", 1)RegisterForSingleUpdate(2)EndEventEvent OnUpdate()int SatiationStage = BeluaSatiatedStage.GetValue() as intif(!caster.IsInInterior() && effectfinished != true)  SprintMod = SprintMod * 1.3  Trace("SpeedMultUp: " + SprintMod)   ; The hungrier the are the faster you move  if SatiationStage == 4   SprintMod = SprintMod * 1.05  elseif SatiationStage == 3   SprintMod = SprintMod * 1.10  elseif SatiationStage == 2   SprintMod = SprintMod * 1.15  elseif SatiationStage == 1   SprintMod = SprintMod * 1.20  elseif SatiationStage == 0   SprintMod = SprintMod * 1.25  EndIf  totalincrease = totalincrease + SprintMod  caster.ModActorValue("SpeedMult", SprintMod)  caster.ModActorValue("CarryWeight", -1)  caster.ModActorValue("CarryWeight", 1)EndIfEndEventEvent OnEffectFinish(Actor target, Actor akCaster)effectfinished = true;mm_BeluaSprintIntroImod.Remove()float reverse = 0 - totalincreasemm_BeluaSprintMainImod.PopTo(mm_BeluaSprintOutroImod,ImodStrength); Reverse the increaseakCaster.ModActorValue("SpeedMult", reverse )akCaster.ModActorValue("CarryWeight", -1)akCaster.ModActorValue("CarryWeight", 1)Trace("SpeedMultDown: " + reverse)EndEvent

Some users have reported that they are getting stuck at higher and higher speed multipliers. One user, who turned up the imod strength then noticed when it happens, the imagespace modifier wasn't being removed. This means the OnEffectFinish event is not always firing when the effect condition in the spell evaluates to false and removes the effect. I, however, cannot reproduce the issue on my machine. The wiki has this to say:
  • By the time this event is called, the active magic effect may have already been deleted by the game. Any native calls to this active magic effect may fail.
  • This event is also called when the owning spell is removed from the target or when its conditions become invalid.

I'm not really sure what to make of that sentance. Can we not trust that OnEffectFinish will always be called? Does Papyrus pre-empt other script blocks from execution if it's too tasked?

-MM
User avatar
Alyna
 
Posts: 3412
Joined: Wed Aug 30, 2006 4:54 am

Post » Thu Jun 21, 2012 10:33 am

I don't think that has anything to do with your problem, since the code you have there don't include any native functions to the ActiveMagicEffect script.

No idea why the event is not being called though.
User avatar
Kyra
 
Posts: 3365
Joined: Mon Jan 29, 2007 8:24 am

Post » Thu Jun 21, 2012 8:58 am

Thanks RandomNoob. In this particular case I documented above I cannot reproduce the problem. I am able to consistently reproduce another OnEffectFinish glitch when the spell is a scripted but channelled effect. If you stop casting a channelled spell the moment it kicks in, and it's scripted, the OnEffectFinish will not fire. I haven't gotten much investigation into that one to figure out what the exact cause is.

-MM
User avatar
Emzy Baby!
 
Posts: 3416
Joined: Wed Oct 18, 2006 5:02 pm

Post » Thu Jun 21, 2012 4:41 pm

I still don't have my head wrapped around this threading business myself, but from other posts I've read...I think you might be getting multiple threads.

If you have 2 scripts trying to modify the player's speedmult simultaneously, that could lead to what you're seeing?

The OnEffectFinish probably is firing, it just isn't reverting all the changes properly because you have a second script messing up your globals and actor values.
User avatar
Doniesha World
 
Posts: 3437
Joined: Sun Jan 07, 2007 5:12 pm

Post » Thu Jun 21, 2012 5:39 pm

OnEffectFinish not always firing is a KNOWN bug going back to Oblivion. I am not saying that is the reason for your issue I am only saying it was a bug in Oblivion so it may still be in Skyrim.

Instead, you may want to try to put the work in the update, have the script test for completion of the said work and then do a dispel on self.
User avatar
Thema
 
Posts: 3461
Joined: Thu Sep 21, 2006 2:36 am

Post » Thu Jun 21, 2012 4:35 pm

OnEffectFinish is very unreliable, mostly because the game does not wait until the script is finished doing whatever it needs to do before unloading the magic effect (and all the script's properties go with it, so every single object your script references becomes NONE). I'd suspect if you were to check in the error logs, you'd see a whole bunch of "cannot call on a None object. Aborting function call" tied to your OnEffectFinish event. That means the game unloaded the reference you were trying to call your function on before the function had a chance to execute, thus when it did try to execute your function, you got an error instead.

Best not to use OnEffectFinish for anything critical to your mod's operation. It don't work too well.
User avatar
Josephine Gowing
 
Posts: 3545
Joined: Fri Jun 30, 2006 12:41 pm

Post » Thu Jun 21, 2012 2:24 pm

Magic effects are crap. You need to store your variables and work in a quest and have the effect fire a function in a quest somewhere.
User avatar
Sami Blackburn
 
Posts: 3306
Joined: Tue Jun 20, 2006 7:56 am

Post » Thu Jun 21, 2012 4:05 pm

I found one reliable method for spells with static durations is to use registerforsingleupdate and onupdate. Then in onupdate, put the stuff that goes into the oneffectfinish normally, followed by a dispel(). You can use if statements and check how much time has elapsed if you need onupdate to do other stuff too. For channeled spells, I have found that making functions in a quest script works reasonably well, then just calling those functions in your events oneffectstart and oneffectfinish. Alternatively for channeled spells, you can try using registerforsingleupdate(999999) and then never call onupdate, just use that to keep the script loaded until oneffectfinish is done and then.use unregisterforupdate at the end of oneffectfinish.

This last one worked for me in my channeled spell that creates actors that attack stuff and die if yoou stop channeling.
User avatar
Kayleigh Mcneil
 
Posts: 3352
Joined: Thu Jun 29, 2006 7:32 am

Post » Thu Jun 21, 2012 8:29 pm

Thanks all. I'm going to try and put in a lot of work to not have to rely on the oneffectfinish. At least I know now that I'm not crazy! :)
User avatar
Cathrin Hummel
 
Posts: 3399
Joined: Mon Apr 16, 2007 7:16 pm


Return to V - Skyrim