Added the Unnecessarily Fixed Fixed Dragon Stalking Fix by tarlazo and KirbonatedBeverage
This commit is contained in:
parent
b67d6bc9a9
commit
623d660f55
BIN
scripts/dragonactorscript.pex
Normal file
BIN
scripts/dragonactorscript.pex
Normal file
Binary file not shown.
304
source/scripts/dragonactorscript.psc
Normal file
304
source/scripts/dragonactorscript.psc
Normal file
@ -0,0 +1,304 @@
|
||||
scriptname dragonActorSCRIPT extends actor
|
||||
{Base Actor Script for all Dragons}
|
||||
; _____________
|
||||
;| |
|
||||
;| SETUP |
|
||||
;|_____________|
|
||||
ImageSpaceModifier property dragonFOVfx auto
|
||||
{FX played for various impacts in dragon combat}
|
||||
float property deathFXrange = 1024.0 auto
|
||||
{max range to play death FX on player}
|
||||
quest property MQkillDragon auto
|
||||
{used to invoke deathSequence() function in MQKillDragonScript.psc}
|
||||
actor property player auto hidden
|
||||
{For quick reference and clean-looking script}
|
||||
float property FOVfalloff auto hidden
|
||||
{choosing not to expose this and clutter the prop list in CS, since it won't be touched often}
|
||||
sound property NPCDragonFlyby auto
|
||||
{Sound played when dragon passes by a target}
|
||||
explosion property knockBackExplosion auto
|
||||
{explosion used to knock back enemies}
|
||||
; NOTE - the dragon breed/skin settings are deprecated and have no effect.
|
||||
armor property SnowDragonSkin auto
|
||||
{deprecated - do not use}
|
||||
armor property TundraDragonSkin auto
|
||||
{deprecated - do not use}
|
||||
armor property forestDragonSkin auto
|
||||
{deprecated - do not use}
|
||||
int property dragonBreed = 0 auto
|
||||
{deprecated - do not use}
|
||||
|
||||
WIFunctionsScript Property WI Auto ;added by jduvall
|
||||
{Pointer to WIFunctionsScript on WI quest. Used to create script event to get nearby NPCs to react to the death of the dragon}
|
||||
|
||||
ImpactDataSet Property FXDragonTakeoffImpactSet Auto
|
||||
{Impact data set to use for the dragon takeoff}
|
||||
ImpactDataSet Property FXDragonLandingImpactSet Auto
|
||||
{Impact data set to use for the dragon landing}
|
||||
ImpactDataSet Property FXDragonTailstompImpactSet Auto
|
||||
{Impact data set to use for the tailstomp}
|
||||
|
||||
|
||||
;*****ADDED FOR DLC2--------------
|
||||
bool MiraakIntroductionHappened
|
||||
bool MiraakAppeared
|
||||
Location Property DLC2ApocryphaLocation Auto
|
||||
WorldSpace Property DLC2ApocryphaWorld auto
|
||||
;*****----------------------------
|
||||
|
||||
; _____________
|
||||
;| |
|
||||
;| EVENTS |
|
||||
;|_____________|
|
||||
EVENT onInit()
|
||||
; just initialize any variables, etc.
|
||||
player = game.getPlayer() ; store player reference
|
||||
FOVfalloff = 1600 ; range at which impact doesn't play FOV
|
||||
|
||||
if deathFXrange == 0
|
||||
deathFXrange = 1000
|
||||
endif
|
||||
|
||||
if !isDead() && isGhost()
|
||||
; redundancy check to prevent invincible, "ghosted" dragons from respawning.
|
||||
setGhost(FALSE)
|
||||
endif
|
||||
|
||||
gotoState("alive")
|
||||
endEVENT
|
||||
|
||||
EVENT onReset()
|
||||
; if we're resetting a previously-killed dragon, make sure it's not a ghost.
|
||||
setGhost(FALSE)
|
||||
endEVENT
|
||||
|
||||
EVENT onLoad()
|
||||
; change markings based on breed of this dragon
|
||||
; first, support random selection
|
||||
; if dragonBreed == 4
|
||||
; dragonBreed = utility.randomInt(0,3)
|
||||
; endif
|
||||
; then assign the markings, either way.
|
||||
; if dragonBreed == 1
|
||||
; equipItem(snowDragonSkin)
|
||||
; elseif dragonBreed == 2
|
||||
; equipItem(tundraDragonSkin)
|
||||
; elseif dragonBreed == 3
|
||||
; equipItem(forestDragonSkin)
|
||||
; endif
|
||||
|
||||
; Block rewritten by USKP which fixes bug of respawned dragons not burning up or giving the player a soul
|
||||
if !isDead()
|
||||
|
||||
if isGhost()
|
||||
; redundancy check to prevent invincible, "ghosted" dragons from respawning.
|
||||
setGhost(FALSE)
|
||||
endif
|
||||
|
||||
; Block rewritten by tarlazo to fix a possible rare glitch as consequence of animation events registered for a dead dragon
|
||||
registerForAnimationEvent(self, "DragonLandEffect")
|
||||
registerForAnimationEvent(self, "DragonForcefulLandEffect")
|
||||
registerForAnimationEvent(self, "DragonTakeoffEffect")
|
||||
registerForAnimationEvent(self, "DragonBiteEffect")
|
||||
registerForAnimationEvent(self, "DragonTailAttackEffect")
|
||||
registerForAnimationEvent(self, "DragonLeftWingAttackEffect")
|
||||
registerForAnimationEvent(self, "DragonRightWingAttackEffect")
|
||||
registerForAnimationEvent(self, "DragonPassByEffect")
|
||||
registerForAnimationEvent(self, "flightCrashLandStart") ; Considered temp for showing injury FX test
|
||||
registerForAnimationEVENT(self, "DragonKnockbackEvent")
|
||||
|
||||
gotoState("alive")
|
||||
endif
|
||||
|
||||
; registerForAnimationEvent(self, "DragonLandEffect")
|
||||
; registerForAnimationEvent(self, "DragonForcefulLandEffect")
|
||||
; registerForAnimationEvent(self, "DragonTakeoffEffect")
|
||||
; registerForAnimationEvent(self, "DragonBiteEffect")
|
||||
; registerForAnimationEvent(self, "DragonTailAttackEffect")
|
||||
; registerForAnimationEvent(self, "DragonLeftWingAttackEffect")
|
||||
; registerForAnimationEvent(self, "DragonRightWingAttackEffect")
|
||||
; registerForAnimationEvent(self, "DragonPassByEffect")
|
||||
; registerForAnimationEvent(self, "flightCrashLandStart") ; Considered temp for showing injury FX test
|
||||
; registerForAnimationEVENT(self, "DragonKnockbackEvent")
|
||||
endEVENT
|
||||
|
||||
|
||||
Event OnLocationChange(Location akOldLoc, Location akNewLoc)
|
||||
;USED TO GET DIALOGUE CONDITIONED ON DRAGON HAVING ATTACKED A TOWN -- only happens if he lands on the ground in a location - ie death, or to land to fight (not on a perch)
|
||||
;see also DragonPerchScript
|
||||
|
||||
; debug.trace(self + "OnLocationChange() calling WI.RegisterDragonAttack(" +akNewLoc + ")")
|
||||
;USKP 2.0.3 - So. Now it seems like you won't even call this out of here with a None? Ok.....
|
||||
if( akNewLoc != None )
|
||||
WI.RegisterDragonAttack(akNewLoc, self)
|
||||
EndIf
|
||||
|
||||
if !isDead() && isGhost()
|
||||
; redundancy check to prevent invincible, "ghosted" dragons from respawning.
|
||||
setGhost(FALSE)
|
||||
endif
|
||||
|
||||
EndEvent
|
||||
|
||||
STATE alive
|
||||
Event OnCombatStateChanged(Actor akTarget, int aeCombatState)
|
||||
|
||||
if !isDead() && isGhost()
|
||||
; redundancy check to prevent invincible, "ghosted" dragons from respawning.
|
||||
setGhost(FALSE)
|
||||
endif
|
||||
|
||||
if akTarget == Game.GetPlayer()
|
||||
WI.updateWIDragonTimer() ;used to prevent dragons from appearing too frequently
|
||||
endif
|
||||
endEvent
|
||||
|
||||
EVENT onAnimationEvent(objectReference deliverator, string eventName)
|
||||
; debug.trace("AnimEvent: " + eventName + " delivered by Dragon ("+self+") ")
|
||||
if (eventName == "DragonLandEffect")
|
||||
; ;debug.trace("Dragon AnimPayLoad: DragonLandEffect")
|
||||
game.shakeCamera(self, 1)
|
||||
game.shakeController(95, 95, 2)
|
||||
KnockAreaEffect(1, getLength())
|
||||
animateFOV() ; call the FOV function
|
||||
PlayImpactEffect(FXDragonTakeoffImpactSet, "NPC Pelvis", 0, 0, -1, 512)
|
||||
elseIf (eventName == "DragonForcefulLandEffect")
|
||||
; ;debug.trace("Dragon AnimPayLoad: DragonForcefulLandEffect")
|
||||
PlayImpactEffect(FXDragonLandingImpactSet, "NPC Pelvis", 0, 0, -1, 512)
|
||||
KnockAreaEffect(1, 2*getLength())
|
||||
;notification ("Dragon Forceful Land Effect")
|
||||
elseIf (eventName == "DragonTakeoffEffect")
|
||||
; debug.trace("Dragon AnimPayLoad: DragonTakeoffEffect")
|
||||
PlayImpactEffect(FXDragonTakeoffImpactSet, "NPC Tail8", 0, 0, -1, 2048)
|
||||
elseIf (eventName == "DragonBiteEffect")
|
||||
;Removed spit effect on 6/1/10. Leaving logic in case we need to sub in other fx or sounds.
|
||||
; ;debug.trace("Dragon ("+self+") AnimPayLoad: DragonBiteEffect")
|
||||
;DragonBiteFX.Play(Self, 2)
|
||||
;notification ("Dragon Bite Effect")
|
||||
elseIf (eventName == "DragonTailAttackEffect")
|
||||
; ;debug.trace(" Dragon AnimPayoload: DragonTailAttackEffect")
|
||||
PlayImpactEffect(FXDragonTailstompImpactSet, "NPC Tail8", 0, 0, -1, 512)
|
||||
;notification("Dragon Tail Attack Effect")
|
||||
elseIf (eventName == "DragonLeftWingAttackEffect")
|
||||
; ;debug.trace("Dragon AnimPayLoad: DragonLeftWingAttackEffect")
|
||||
PlayImpactEffect(FXDragonTailstompImpactSet, "NPC LHand", 0, 0, -1, 512)
|
||||
;notification ("Dragon Left Wing Attack Effect")
|
||||
elseIf (eventName == "DragonRightWingAttackEffect")
|
||||
; ;debug.trace("Dragon AnimPayLoad: DragonRightWingAttackEffect")
|
||||
PlayImpactEffect(FXDragonTailstompImpactSet, "NPC RHand", 0, 0, -1, 512)
|
||||
;notification ("Dragon Right Wing Attack Effect")
|
||||
elseIf (eventName == "DragonPassByEffect")
|
||||
NPCDragonFlyby.Play(self)
|
||||
game.shakeCamera(self, 0.85)
|
||||
game.shakeController(0.65, 0.65, 0.5)
|
||||
;elseIf (eventName == "flightCrashLandStart")
|
||||
;Removed by mark since leaking magic is a bust. May replace with leaking blood at some point as a second test.
|
||||
; apply injury FX art when I crash land.
|
||||
;FXinjuryLeaks.play(self, -1)
|
||||
elseIf (eventName == "DragonKnockbackEvent")
|
||||
; dragon needs to stagger everyone in radius a bit larger than my length
|
||||
; ;debug.trace(self + " is knocking back actors within " + 1.5*getLength() + " of self @ " + self.x + ", " + self.y)
|
||||
;self.placeAtMe(knockBackExplosion)
|
||||
KnockAreaEffect(1, 1.5*getLength())
|
||||
animateFOV(1.5*getLength())
|
||||
endif
|
||||
endEVENT
|
||||
|
||||
EVENT onDeath(actor killer)
|
||||
;debug.trace("Remove mouth/injury FX art, begin death FX sequence for " + self)
|
||||
;USKP 2.1.3 Bug #19214 - Dialogue in the quest has options that get skipped with this line below the gotoState call.
|
||||
WI.startWIDragonKillQuest(self) ;used to create a scene if any NPCs are nearby when the dragon dies. See WIFunctionsScript attached to WI quest which creates a story manager script event, and WIDragonKilled quest which handles the scene.
|
||||
gotoState("deadAndWaiting")
|
||||
|
||||
; removing update registration in favor of a while() in the STATE below
|
||||
;registerForUpdate(1)
|
||||
endEVENT
|
||||
endSTATE
|
||||
|
||||
STATE deadAndWaiting
|
||||
|
||||
;-------------------CHANGED FOR DLC2---------------------------
|
||||
EVENT onBeginState()
|
||||
|
||||
MQKillDragonScript MQKillDragonS = MQkillDragon as MQKillDragonScript
|
||||
|
||||
;If in Apocrypha, this is the boss fight so do not wait for distance
|
||||
if DLC2ApocryphaLocation && DLC2ApocryphaWorld && (game.getPlayer().isInLocation(DLC2ApocryphaLocation) || game.getPlayer().getWorldSpace() == DLC2ApocryphaWorld)
|
||||
gotoState("deadDisintegrated")
|
||||
MQkillDragonS.deathSequence(self)
|
||||
RegisterForSingleUpdateGameTime(0.5)
|
||||
elseif MQKillDragonS.ShouldMiraakAppear(self) && MiraakAppeared == false
|
||||
gotoState("deadDisintegrated")
|
||||
; Debug.Trace(self + "MiraakAppears")
|
||||
MiraakAppeared = true
|
||||
MQkillDragonS.deathSequence(self, MiraakAppears = true)
|
||||
RegisterForSingleUpdateGameTime(0.5)
|
||||
else
|
||||
;NORMAL BASE GAME BEHAVIOR
|
||||
while getDistance(player) > deathFXrange
|
||||
utility.wait(1.0)
|
||||
endWhile
|
||||
; debug.trace("player close enough to absorb" + self)
|
||||
gotoState("deadDisintegrated")
|
||||
MQkillDragonS.deathSequence(self)
|
||||
RegisterForSingleUpdateGameTime(0.5)
|
||||
|
||||
endif
|
||||
|
||||
endEVENT
|
||||
;--------------------------------------------------------------------------------------------
|
||||
|
||||
; EVENT onUpdate()
|
||||
; if getDistance(player) < deathFXrange
|
||||
; ; debug.trace("player close enough to absorb" + self)
|
||||
; gotoState("deadDisintegrated")
|
||||
; unRegisterforUpdate()
|
||||
; (MQkillDragon as MQKillDragonScript).deathSequence(self)
|
||||
; endif
|
||||
;endEVENT
|
||||
endSTATE
|
||||
|
||||
STATE deadDisintegrated
|
||||
; nothing happens here - dead and just bones.
|
||||
event OnUpdateGameTime()
|
||||
cell myDragonCell = self.getparentcell()
|
||||
if !myDragonCell.IsAttached()
|
||||
NoStalking()
|
||||
else
|
||||
RegisterForSingleUpdateGameTime(0.5)
|
||||
endIf
|
||||
endEvent
|
||||
endSTATE
|
||||
|
||||
; _____________
|
||||
;| |
|
||||
;| FUNCTIONS |
|
||||
;|_____________|
|
||||
function AnimateFOV(float fFOVfalloff = 1600.0)
|
||||
; Function that animates FOV with an ismod. Declaring here in case needed frequently
|
||||
float playerDist = player.getDistance(self) ; get and store the player's current distance from me
|
||||
if playerDist < fFOVfalloff
|
||||
float FOVpower = (1- (1/(fFOVfalloff/(playerDist)))) ; consider offset to compensate for collision size
|
||||
if FOVpower > 1.0
|
||||
FOVpower = 1.0 ; clamp to prevent wacky values
|
||||
endif
|
||||
; ;debug.trace("player is " + playerDist + " from landing dragon")
|
||||
; ;debug.trace("dragon FOV fx power is" + FOVpower)
|
||||
dragonFOVfx.apply(FOVpower) ;animated FOV effect. Strength based on distance from player
|
||||
endif
|
||||
endFunction
|
||||
|
||||
Bool function IsDurnehviir()
|
||||
|
||||
return self.GetActorBase() as form == game.GetFormFromFile(0x000030D8, "Dawnguard.esm")
|
||||
endFunction
|
||||
|
||||
function NoStalking()
|
||||
|
||||
if self.IsDurnehviir()
|
||||
return
|
||||
else
|
||||
self.DispelAllSpells()
|
||||
self.SetCriticalStage(self.CritStage_DisintegrateEnd)
|
||||
endIf
|
||||
endFunction
|
Loading…
Reference in New Issue
Block a user