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