Why is my ability not ending when removed from player?

Post » Tue Jun 19, 2012 2:57 pm

I have this spell that adds an ability spell that repeatedly casts detect life. The idea is so that I can toggle detect life, and so that it gets updated (when I was using detect life normally it would do the detect life thing, but then if I moved it wouldnt detect the new npcs I met, it would just have the ones who were initially in range glowing). The spell and ability work, except that when I remove the ability it doesn't stop, it continues to recast the detect life spell.

If I toggle it on the 'Detect Life Starting' message shows, but when I toggle it off, no message shows, and the detect life effects continue. Then when I toggle it again (back on) it shows the starting message, and then the ending message right after it, and the effect continues being on. Also, randomly when I kill stuff it sometimes seems to turn off, and at some other times and I dont understand why.

I'm pretty sure my detect life spell works fine, I'm pretty sure the toggle spell works fine, I think the issue must have to do with abilities and/or the updating. Also i have the detectUpdateInt set to 2 seconds and the duration of the detect life spell is set to 3 seconds. If anyone can shed some light on this for me I would appreciate it.

Scriptname DetectLifeSpellScript extends activemagiceffectSPELL PROPERTY DetectLifeSpell AUTOINT PROPERTY detectUpdateInt AUTOACTOR targetEVENT OnEffectStart(ACTOR akTarget, ACTOR akCaster)    debug.Notification("Detect Life Starting")    target = akCaster    DetectLifeSpell.Cast(target)    RegisterForSingleUpdate(detectUpdateInt)ENDEVENTEVENT OnUpdate()    Utility.Wait(0.1)    DetectLifeSpell.Cast(target)    RegisterForSingleUpdate(detectUpdateInt)ENDEVENTEVENT OnEffectFinish(ACTOR akTarget, ACTOR akCaster)    target.DispelSpell(DetectLifeSpell)    debug.Notification("Detect Life Ending")ENDEVENT
User avatar
sally coker
 
Posts: 3349
Joined: Wed Jul 26, 2006 7:51 pm

Post » Tue Jun 19, 2012 2:00 pm

You need a boolean to tell the OnUpdate to stop registering. As long as it's registered for updates, it will continue indefinitely.


Scriptname DetectLifeSpellScript extends activemagiceffectBool UpdatesOnSPELL PROPERTY DetectLifeSpell AUTOINT PROPERTY detectUpdateInt AUTOACTOR targetEVENT OnEffectStart(ACTOR akTarget, ACTOR akCaster)	debug.Notification("Detect Life Starting")	target = akCaster	DetectLifeSpell.Cast(target)	UpdatesOn = True	RegisterForSingleUpdate(detectUpdateInt)ENDEVENTEVENT OnUpdate()    Utility.Wait(0.1)    DetectLifeSpell.Cast(target)	if UpdatesOn	   RegisterForSingleUpdate(detectUpdateInt)	endifENDEVENTEVENT OnEffectFinish(ACTOR akTarget, ACTOR akCaster)	UpdatesOn = False	Utility.Wait(detectUpdateInt + 0.5) ; wait til updates have stopped, THEN	target.DispelSpell(DetectLifeSpell)	debug.Notification("Detect Life Ending")ENDEVENT
User avatar
Ymani Hood
 
Posts: 3514
Joined: Fri Oct 26, 2007 3:22 am

Post » Tue Jun 19, 2012 1:46 pm

Hm.. The CK Wiki says that it should automatically be unregistered when the magic effect is removed.

Edit: Actually I tried it with a boolean to stop the updates, and the updates would stop, but the OnEffectFinish event still wasn't firing.
User avatar
Nadia Nad
 
Posts: 3391
Joined: Thu Aug 31, 2006 3:17 pm

Post » Wed Jun 20, 2012 3:06 am

Okay, after removing the updating part completely, my problem seems to have more to do with the fact that the OnEffectFinish event isn't firing when I remove the ability. Yet I have another ability that I add and remove, and its OnEffectFinish event does fire when it is removed.
User avatar
Sarah Unwin
 
Posts: 3413
Joined: Tue Aug 01, 2006 10:31 pm

Post » Tue Jun 19, 2012 4:56 pm

Hm.. The CK Wiki says that it should automatically be unregistered when the magic effect is removed.

Edit: Actually I tried it with a boolean to stop the updates, and the updates would stop, but the OnEffectFinish event still wasn't firing.

Did you add a wait in there like the above, to make sure it waits all the way through an update cycle before dispelling? And OnEffectFinish didn't fire at all? You never got the "Detect Life Ending" notification?

Are you using the "Script" archetype for the spell? Try that. And be sure to check the duration you're sending it in the spell. If it's "Fire and forget" it should have a fixed duration, unless you set it up to have increased duration with a perk.

Oh, and if you really want to have it work like a toggle, (Cast on, Cast off), you should have all the stuff that's in the OnEffectFinish in the OnEffectStart, and use the boolean to decide what to do with each casting, toggle on, or toggle off...put the dispel in the OnUpdate in an "else" case of the If Statement that checks if you should keep updating.
User avatar
Czar Kahchi
 
Posts: 3306
Joined: Mon Jul 30, 2007 11:56 am

Post » Wed Jun 20, 2012 1:07 am

No, see I have 2 spells, the one that code is in, which is actually an ability (it can't be equipped, it has infinite duration, and its effect automatically start as soon as it's added) and one which does the toggling and adds that spell to the player. When the toggling spell toggles the ability off it just does player.removespell.

And I only get the Detect Life Ending notification after ive re-toggled the spell back on, then it gives me the starting notification and the ending notification which should have fired earlier and the spell does use the script archetype.
User avatar
Svenja Hedrich
 
Posts: 3496
Joined: Mon Apr 23, 2007 3:18 pm

Post » Wed Jun 20, 2012 3:38 am

I guess this will be much easier to do with a while loop:

Scriptname DetectLifeSpellScript extends ActiveMagicEffectSpell Property DetectLifeSpell AutoEvent OnEffectStart(Actor akTarget, Actor akCaster)	Debug.Notification("Detect life starting.")	MagicEffect meSelfMagicEffect = Self.GetBaseObject()	While akCaster.HasMagicEffect(meSelfMagicEffect)			DetectLifeSpell.Cast(akCaster, None)				Utility.Wait(0.1)			EndWhile		Debug.Notification("Detect life ending.")	EndEvent

The meSelfMagicEffect contains the reference to the magic effect that started this script (the ability), so once it's gone (dispeled) from the target actor the while loop can no longer continue effectively ending the script as well.

NOTE: You don't need an extra "target" variable here, in case of abilities both akCaster and akTarget are always the same.
NOTE2: It's best to set the wait function to the same amount of time as the duration of the detect life spell, but keep it as short as possible to prevent "overflow" of the detect life effect when you toggle it off.
User avatar
u gone see
 
Posts: 3388
Joined: Tue Oct 02, 2007 2:53 pm

Post » Tue Jun 19, 2012 1:22 pm

Oh, and the target variable is, as Alth said, completely unnecessary. But as an Ability, with a duration of "permament", you would never get an OnEffectFinish() event, because the effect never "finishes", it's just removed.
User avatar
Spaceman
 
Posts: 3429
Joined: Wed May 23, 2007 10:09 am

Post » Wed Jun 20, 2012 4:50 am

But as an Ability, with a duration of "permament", you would never get an OnEffectFinish() event, because the effect never "finishes", it's just removed.

Actually I'm pretty sure it does trigger the OnEffectFinish() event, I have a spell that adds a "parent" ability, which in reaction on start adds another set of "child" abilities and once this parent ability is removed by the RemoveSpell function, the OnEffectFinish() inside its script removes the children as well.

EDIT: OK I must admit it seems not to always work, or at least it works under some conditions, seems like there is a need for a lot of testing.
EDIT: Seems like I was too fast in my assumptions, OnEffectFinish() indeed does always work, there is just a problem with loops inside scripts which are still present in game until they happen to end by themselves even when the original form that started this script no longer exists. In this case, for example, if you would manage to dispel the ability just as the script reaches the wait() function and recast it before it returns, you would have two scripts running at the same time (this can go to infinity or until the game crashes).

I think the solution for you, Xtynct, is:
Scriptname DetectLifeSpellScript extends activemagiceffectSPELL PROPERTY DetectLifeSpell AUTOINT PROPERTY detectUpdateInt AUTOACTOR targetMagicEffect SelfMagicEffectEVENT OnEffectStart(ACTOR akTarget, ACTOR akCaster)	debug.Notification("Detect Life Starting")	target = akCaster	SelfMagicEffect = Self.GetBaseObject()	DetectLifeSpell.Cast(target)	RegisterForSingleUpdate(detectUpdateInt)	ENDEVENTEVENT OnUpdate()	If target.HasMagicEffect(SelfMagicEffect)			DetectLifeSpell.Cast(target)		RegisterForSingleUpdate(detectUpdateInt)			EndIf	ENDEVENTEVENT OnEffectFinish(ACTOR akTarget, ACTOR akCaster)	target.DispelSpell(DetectLifeSpell)	Debug.Notification("Detect Life Ending")	ENDEVENT
User avatar
P PoLlo
 
Posts: 3408
Joined: Wed Oct 31, 2007 10:05 am

Post » Wed Jun 20, 2012 2:03 am

Thank you for the help, but my real problem was the OnEffectFinish event not firing when it should. I changed a couple settings in my magic effect and spell and for some reason it started working. And then even when I changed them back it's still working.
User avatar
CArla HOlbert
 
Posts: 3342
Joined: Wed Feb 21, 2007 11:35 pm


Return to V - Skyrim