Scriptname WispActorScript extends ActiveMagicEffect {Abilities and FX for Wisp/Glimmerwitch} ;======================================================================================; ; IMPORTS / ;=============/ import utility import form import debug ;======================================================================================; ; PROPERTIES / ;=============/ keyword property wispChild01 auto keyword property wispChild02 auto keyword property wispChild03 auto spell property Phase1ConcSpell auto {A long range concentration spell for phase #1} spell property Phase2ConcSpell auto {Shorter range spell for phase #2} actorBase property encWispShade auto VisualEffect Property WispFXAttachEffect Auto explosion property ExplosionIllusionLight01 auto Activator property AshPileObject auto {The object we use as a pile.} float property PhaseThreeHPPercent auto {At what % of HP should I spawn my dopplegangers?. DEFAULT: 0.2} ;======================================================================================; ; VARIABLES / ;=============/ ;USKP 2.0.4 - All of these are Actors, so let's just dispense with all the type casting that's going on down below. Actor selfRef ; let's refer to the witchlights as "orbs" to avoid confusion. Actor orb01 Actor orb02 Actor orb03 Actor Shade01 Actor Shade02 ;track number of living orb babies int liveLights = 3 ; have my FX been attached? bool bFX = FALSE ;======================================================================================; ; EVENTS / ;=============/ EVENT onLoad() ;trace("Wisp: Has Loaded 3D ("+selfRef+")") EVPall() endEVENT EVENT OnEffectStart(Actor Target, Actor Caster) ;trace("AbWisp Effect Start on: "+SelfRef+"") selfRef = caster ;USKP 2.0.1 - Stop this from attaching to the player. if selfRef == Game.GetPlayer() Dispel() Return EndIf if selfref.getLinkedRef() == NONE ; only attack FX at this point if I am not in an ambush link if (WispFXAttachEffect != NONE) WispFXAttachEffect.Play(selfRef, -1) bFX = TRUE Endif endif ;USKP 2.0.4 - These should be cast as Actors orb01 = selfRef.getLinkedRef(WispChild01) as Actor orb02 = selfRef.getLinkedRef(WispChild02) as Actor orb03 = selfRef.getLinkedRef(WispChild03) as Actor EVPall() if phaseThreeHPpercent > 1.0 ; if we passed a high value, the user probably meant a whole number percentage like 30% phaseThreeHPpercent = phaseThreeHPpercent/100 endif ENDEVENT EVENT onGetup(ObjectReference akFurniture) ;USKP 2.0.1 - Stop this from attaching to the player. if( selfRef == Game.GetPlayer() ) Return EndIf if akFurniture == selfRef.getLinkedRef() && bFX == FALSE ; if I was in a furniture ambush, then add my FX when I leave it WispFXAttachEffect.Play(selfRef, -1) bFX = TRUE endif endEVENT Event OnCombatStateChanged(Actor victim, int aeCombatState) if aeCombatState != 0 ; 0 means not in combat, so non-zero means we entered combat ; debug.trace("Wisp began combat with "+victim+" ("+self+")") if aeCombatState == 1 ;USKP 2.0.6 - Dead actors throw errors when asked to start combat. If orb01 && orb01.IsDead() == False orb01.startCombat(victim) Endif If orb02 && orb02.IsDead() == False orb02.startCombat(victim) Endif If orb03 && orb03.IsDead() == False orb03.startCombat(victim) Endif ; Start listening for critically low HP registerforSingleupdate(1.0) endif endif endEVENT EVENT onActivate(objectReference actronaut) ; debug.trace("Wisp Activated") if actronaut == orb01 || actronaut == orb02 || actronaut == orb03 utility.wait(0.1) ; debug.trace("Actronaut was one of my orbs") liveLights -= 1 ; debug.trace("Livelights = "+livelights) if liveLights <= 0 ; debug.trace("All child lights dead for "+selfref) ;Variable07 sets up the berserk package/combat style selfRef.setActorValue("Variable07",1) ;also "eliminate" her ability to cast spells - take all her magicka away. ;trace("WISPS: move to combat phase 2") ; Take away her magicka (she'll regen) and shuffle her spell set selfRef.damageActorValue("Magicka", -(selfRef.getActorValue("Magicka"))) selfRef.removeSpell(Phase1ConcSpell) selfRef.addSpell(Phase2ConcSpell) endif endif endEVENT EVENT onUpdate() ; Check HP for Phase 3 Combat - Last ditch doppleganger attack! if selfRef.getActorValuePercentage("health") > phaseThreeHPpercent ; HP still high, so hold off. ;utility.wait(0.5) RegisterforSingleUpdate(0.5) else ; create my dopplegangers and unregister for update If EncWispShade Shade01 = selfRef.placeAtMe(EncWispShade) as Actor Shade02 = selfRef.placeAtMe(EncWispShade) as Actor EndIf ;/ selfRef.setActorValue("Variable07",1) selfRef.damageActorValue("Magicka", -(selfRef.getActorValue("Magicka"))) selfRef.SetActorValue("Magicka", 0.0) Debug.Notification("Set variables!") /; ; Dump the orbs. If (orb01 != NONE) orb01.kill() Endif If (Orb02 != NONE) orb02.kill() Endif If (Orb03 != NONE) orb03.kill() Endif ; restore her longer-range spell If orb01 || orb02 || orb03 selfRef.addSpell(Phase1ConcSpell) EndIf endif endEVENT EVENT OnDying(Actor akKiller) ; Effects automatically finish onDeath so use this EVENT hook instead ;trace("Actor has died: "+selfref) selfRef.SetCriticalStage(selfRef.CritStage_DisintegrateStart) WispFXAttachEffect.Stop(selfRef) utility.wait(0.90) selfRef.placeatme(ExplosionIllusionLight01) selfRef.AttachAshPile(AshPileObject) ; pause a second before killing inheritors - I've seen massive damage skip over this utility.wait(0.5) If (orb01 != NONE) orb01.kill() Endif If (Orb02 != NONE) orb02.kill() Endif If (Orb03 != NONE) orb03.kill() Endif If (Shade01 != NONE) Shade01.kill() Endif If (Shade02 != NONE) Shade02.kill() Endif selfRef.SetCriticalStage(selfRef.CritStage_DisintegrateEnd) ENDEVENT FUNCTION EVPall() ;trace("Sending EVP to self and witchlight children ("+selfRef+")") ;trace("Witchlights are the Following:") ;trace("--------------------------------") ;trace(orb01) ;trace(orb02) ;trace(orb03) ;trace("--------------------------------") If (orb01 != NONE) orb01.evaluatePackage() Endif If (Orb02 != NONE) orb02.evaluatePackage() Endif If (Orb03 != NONE) orb03.evaluatePackage() Endif endFUNCTION