enderalse/source/scripts/defaultteleportability.psc

105 lines
3.3 KiB
Plaintext

scriptName defaultTeleportAbility extends activeMagicEffect
{Attempt at a generic script for NPCs to teleport to XXX markers when threatened by melee}
import game
import utility
;VFX
Activator property SummonFX Auto
;Summon parameters
activator property teleportBase auto
{Base object to search for as a teleport point}
float property fSearchRadius = 1600.0 auto
{How far near me to search for teleport points? DEFAULT = 768u}
int property iMinToTeleport = 2 auto
{Min # of hits I'll take before teleporting. DEFAULT = 2}
int property iMaxToTeleport = 4 auto
{Max # of hits I'll take before teleporting. DEFAULT = 4}
effectShader property fadeOutFX auto
effectShader property fadeInFX auto
visualEffect property TrailFX auto
;{Let's try some trailing FX to show where I'm going to pop out}
;Internal variables.
bool combatStarted
int hitCount
ObjectReference teleportGoal
ObjectReference player
actor caster
objectReference casterRef
bool inBleedout
objectReference opponent
Event OnEffectStart(Actor akTarget, Actor akCaster)
player = (Game.GetForm(0x14) as Actor)
caster = akCaster
casterRef = (caster as ObjectReference)
endEVENT
;Every 2 hits, the Caller teleports.
Event OnHit(ObjectReference akAggressor, Form weap, Projectile proj, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
opponent = akAggressor
int hitTolerance = RandomInt(iMinToTeleport, iMaxToTeleport)
hitCount = hitCount + 1
if (hitCount > hitTolerance && !caster.IsDead())
hitCount = 0
if inBleedout == FALSE && caster.isDead() == FALSE
Teleport()
endif
EndIf
; additional check - seen instances where NPC with this ability would not die!
if Caster.getActorValue("Health") < 0
caster.kill()
; debug.trace("teleport NPC killed by self (HP<0 safety net): "+caster)
endif
EndEvent
Event Teleport()
;Where's the Caller going?
int i = 0 ; incrementer for while
int maxSearch = 10 ; limit number of while recursions
while i < maxSearch
teleportGoal = FindRandomReferenceOfTypeFromRef(teleportBase, casterRef, fSearchRadius)
if teleportGoal.getDistance(opponent) < 512 || (player as actor).hasLoS(teleportGoal) == FALSE
; ;debug.trace(caster.getActorBase()+" found but doesn't prefer "+teleportGoal)
; this teleport marker isn't the best, but hold onto it as a backup option
; therefore don't kick out of the loop just yet
elseif teleportGoal.getDistance(opponent) > 512 || (player as actor).hasLoS(teleportGoal) == TRUE
; if we found a teleport marker that works, just use it!
; ;debug.trace(caster.getActorBase()+" found a good goal and kicking out of while loop "+teleportGoal)
i = maxSearch
endif
i += 1
; ;debug.trace("While Recursion #"+i+" on "+self)
endWhile
;Perform the swap.
;casterRef.Disable()
fadeOutFX.play(casterRef)
caster.setGhost(TRUE)
objectReference previousLoc = casterRef.PlaceAtMe(SummonFX)
Utility.Wait(0.5)
TrailFX.Play(previousLoc, 0.5, teleportGoal)
casterRef.MoveTo(teleportGoal)
casterRef.PlaceAtMe(SummonFX)
Utility.Wait(0.5)
;casterRef.Enable()
fadeOutFX.stop(casterRef)
caster.setGhost(FALSE)
caster.evaluatePackage()
caster.startCombat(opponent as actor)
EndEvent
EVENT onEnterBleedout()
inBleedout = TRUE
; For now never reset this boolean. Considering it part of the flow that bleeding out turns the ability off
endEVENT