parent
b67d6bc9a9
commit
623d660f55
2 changed files with 304 additions and 0 deletions
Binary file not shown.
@ -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