Jump to content

[LE] Can "AddSpell()" adding an ability stack when used with "OnLoad()"?


maxarturo

Recommended Posts


Hi all.


Today i looked at a default vanilla script that i'm using (i've never looked at it in the past) and i noticed that it uses "OnLoad()" to add the 'Ghost Ab Spell', and i'm wondering 2 things:


1) The "OnLoad()" will add the Ab spell multiple times, won't this cause stacking of the spell ?.

* The script doesn't have a function to remove the Ab spell.

Default Vanilla Ghost Script:




Scriptname defaultGhostScript extends Actor

EFFECTSHADER PROPERTY pGhostFXShader AUTO
FORMLIST PROPERTY pDefaultGhostWeaponFlickerList AUTO
CONTAINER PROPERTY pDefaultGhostCorpse AUTO
EXPLOSION PROPERTY pdefaultGhostDeathExplosion AUTO
LEVELEDITEM PROPERTY pdefaultGhostLeveledList AUTO

BOOL PROPERTY bdefaultLoot=FALSE AUTO
{mark true if you want the default ghost loot and not the NPCs}

BOOL PROPERTY bflicker=FALSE AUTO
{don't use this yet}

SPELL PROPERTY pGhostAbilityNew AUTO
SPELL PROPERTY pGhostResistsAbility AUTO

; //any perks you want to add
PERK PROPERTY pGhostHalfDamagePerk AUTO

BOOL PROPERTY bFade=FALSE AUTO
{makes the ghost fade out instead of explode}

; //make sure only one flash is active
BOOL bFlash=FALSE

; //the person who caused the ghost to flash
ACTOR target

; //////////
; //LOOT PILE VARIABLES
; //////////

; //////////
; //ASH PILE VARIABLES
; //////////
float property fDelay = 0.75 auto
{time to wait before Spawning Ash Pile}

float property fDelayEnd = 1.65 auto
{time to wait before Removing Base Actor}

float property ShaderDuration = 0.00 auto
{Duration of Effect Shader.}

Activator property pDefaultAshPileGhost auto
{The object we use as a pile.}

Bool property bSetAlphaZero = True auto
{The Effect Shader we want.}

FormList Property pDisintegrationMainImmunityList auto
{If the target is in this list, they will not be disintegrated.}

EFFECTSHADER PROPERTY pGhostDeathFXShader AUTO
{the shader to play while dying}

race VictimRace
bool TargetIsImmune = True

; ///////////
; //ONLOAD
; ///////////
EVENT onLoad()

; // add on the abilities
SELF.addSpell(pGhostAbilityNew)
SELF.addSpell(pGhostResistsAbility)

; // for some reason this makes ghostFlash work better
IF(bFlicker)
ghostFlash(1)
ENDIF

ENDEVENT

; /////////
; //ONHIT: When the ghost is hit, if the player isnt using the proper weapon, have them fade
; /////////
EVENT onHIT(OBJECTREFERENCE akAggressor, FORM akSource, Projectile akProjectile, BOOL abPowerAttack, BOOL abSneakAttack, BOOL abBashAttack, BOOL abHitBlocked)

; //if we're supposed to flicker and we're hit by a weapon without turn and we're not blocked, flash
IF(bflicker && !pDefaultGhostWeaponFlickerList.hasForm(akSource) && !abHitBlocked && !bFlash)
bFlash = TRUE
target = akAggressor as ACTOR
ghostFlash(3)
ENDIF

ENDEVENT

; /////////
; //GHOSTFLASH: play this to flash the ghost when hit or attacking
; //
; //float time: the amount of time to be invincible
; /////////
FUNCTION ghostFlash(FLOAT time)

; //stop the effect to keep the particles
pGhostFXShader.stop(SELF)
SELF.setGhost()

; //be invincible for x seconds
utility.wait(time)

; //return the ghost to normal
SELF.setGhost(FALSE)
SELF.setAlpha(0.3)
pGhostFXShader.play(SELF)

bFlash = FALSE

ENDFUNCTION

; /////////
; //ONDYING: On dying play an explosion to mask the ghost vanishing and being replaced by his corpse
; /////////
EVENT onDYING(ACTOR killer)

IF(bFade)
SELF.blockActivation(TRUE)
disable(1)
ELSE

; //check to see if the target is in the immunity list
IF(pDisintegrationMainImmunityList == none)
TargetIsImmune = False
ELSE
ActorBase VictimBase = SELF.GetBaseObject() as ActorBase
VictimRace = VictimBase.GetRace()

IF(pDisintegrationMainImmunityList.hasform(VictimRace) || pDisintegrationMainImmunityList.hasform(VictimBase))
TargetIsImmune = True
ELSE
TargetIsImmune = False
ENDIF
ENDIF

; //if the target is not immune, disintegrate them
IF(TargetIsImmune == False)
; debug.trace("victim just died")

SELF.SetCriticalStage(SELF.CritStage_DisintegrateStart)

IF(pGhostDeathFXShader != none)
pGhostDeathFXShader.play(SELF,ShaderDuration)
ENDIF

SELF.SetAlpha (0.0,True)

; //attach the ash pile
SELF.AttachAshPile(pDefaultAshPileGhost)

IF(bdefaultLoot)
SELF.RemoveAllItems()
SELF.addItem(pdefaultGhostLeveledList)
ENDIF


utility.wait(fDelayEnd)
IF(pGhostDeathFXShader != none)
pGhostDeathFXShader.stop(SELF)
ENDIF
IF(bSetAlphaZero == True)
SELF.SetAlpha (0.0,True)
ENDIF
SELF.SetCriticalStage(SELF.CritStage_DisintegrateEnd)
ENDIF

ENDIF

ENDEVENT




2) Why the game's developers didn't just add the Ab spell directly to the npc but they choose instead to add it by script.

Is this one more Bethesda f*** up?.


* I think i need to remove completely this default vanilla script from my mod as i've done with countless other.


Thank you.

Edited by maxarturo
Link to comment
Share on other sites

I don't use default scripts ever, I just prefer to write my own so they can be tailored to the mod. Using addspell for abilities won't stack. If the npc already has the ability nothing happens. You can use the check if Npc.HasSpell(MySpell) if you're worried about it though. Using MySpell.Cast(NPC) can stack effects though.

Link to comment
Share on other sites

Hey dylbill.


I don't actually worry about issues since i've tested them to death, plus in every test i make for something else i run into those mod's ghost npcs.

* Plus i removed the vanilla script and add the Ab directly to the actors.


I made this post because i cannot understand why the game developers didn't add the 'Ghost Ab' directly to the vanilla ghost actors and they use scripted means, there must be a reason behind it... i refuse to think that they were so stupid.

* But in the other hand i've run into so many vanilla F*** UPS...


Anyway, have a pleasant day.

Edited by maxarturo
Link to comment
Share on other sites

In case the ability (or magic effect inside) have a condition like this Is3DLoaded == 1.00, imho the ability should be removed from actor. If not as dylbill has written: "If the npc already has the ability nothing happens." an ability is only a spell.

 

You asked: "Why the game's developers didn't just add the Ab spell directly to the npc but they choose instead to add it by script." .. "there must be a reason behind it.."

Probably it was convenience, because they needed a cleanup routine for ghosts by dying. And do not forget the script is prepared for using a special perk "pGhostHalfDamagePerk".

 

the vanilla script could have error as follow:

 

[08/08/2015 - 02:03:55AM] error: Cannot add a None spell to the actor
stack:
[ (000725F7)].defaultGhostScript.AddSpell() - "<native>" Line ?
[ (000725F7)].defaultGhostScript.OnLoad() - "defaultGhostScript.psc" Line 230
[08/08/2015 - 02:03:55AM] error: Cannot add a None spell to the actor
stack:
[ (000725F7)].defaultGhostScript.AddSpell() - "<native>" Line ?
[ (000725F7)].defaultGhostScript.OnLoad() - "defaultGhostScript.psc" Line 231

 

 

 

I rewrote the script a bit and add some comments

defaultGhostScript

 

Scriptname defaultGhostScript extends Actor  
{v1.4a ReDragon 2020}

  FormList     PROPERTY pDefaultGhostWeaponFlickerList auto
  Container    PROPERTY pDefaultGhostCorpse            auto  ; UnUSED
  LeveledItem  PROPERTY pdefaultGhostLeveledList       auto

  EffectShader PROPERTY pGhostFXShader                 auto
  Explosion    PROPERTY pdefaultGhostDeathExplosion    auto

  Perk  PROPERTY pGhostHalfDamagePerk auto       ; UnUSED, placeholder for a perk you want to add
  Spell PROPERTY pGhostAbilityNew     auto
  Spell PROPERTY pGhostResistsAbility auto


  Bool PROPERTY bflicker     = False auto        ; Do not use this yet !!!
  Bool PROPERTY bdefaultLoot = False auto        ; mark true if you want the default ghost loot and not the NPCs
  Bool PROPERTY bFade        = False auto        ; makes the ghost fade out instead of explode
  Bool bFlash                                    ; [default=False], make sure only one flash is active

  ;Actor target                                  ; *) UnUSED, the person who caused the ghost to flash

; ASH PILE Properties and Vars for dying
; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  FormList  PROPERTY pDisintegrationMainImmunityList auto    ; If the target is in this list, they will not be disintegrated.
  Activator PROPERTY pDefaultAshPileGhost            auto    ; The object we use as a pile.

  EffectShader PROPERTY pGhostDeathFXShader  auto            ; the shader to play while dying
  Bool         PROPERTY bSetAlphaZero = TRUE auto            ; The Effect Shader we want.

  Float PROPERTY fDelay         = 0.75 auto        ; time to wait before Spawning Ash Pile
  Float PROPERTY fDelayEnd      = 1.65 auto        ; time to wait before Removing Base Actor
  Float PROPERTY ShaderDuration = 0.00 auto        ; Duration of Effect Shader.

 ;Race VictimRace                                ; UnUSED
 ;Bool TargetIsImmune = TRUE                    ; UnUSED, code optimization


; -- FUNCTION --

;------------------------------
FUNCTION ghostFlash(Float time)
;------------------------------
; play this to flash the ghost when hit or attacking

; "The effects created by play() function stack, so using multiple times without stopping may cause frame rate issues."
    pGhostFXShader.Stop(self)    ; stop

    self.SetGhost(TRUE)                    ; switch on status ghost
    Utility.Wait(time)                    ; amount of time for actor to be invincible
    self.SetGhost(False)                ; switch off status ghost

    self.SetAlpha(0.3)
    pGhostFXShader.Play(self)    ; play
    
    bFlash = False    
ENDFUNCTION


; -- EVENTs -- 3

; https://www.creationkit.com/index.php?title=AddSpell_-_Actor
; bool Function AddSpell(Spell akSpell, bool abVerbose = true) native

EVENT OnLoad()
    IF ( pGhostAbilityNew )
        self.AddSpell(pGhostAbilityNew)            ; (error line 230)
    ENDIF

    IF ( pGhostResistsAbility )
        self.AddSpell(pGhostResistsAbility)        ; (error line 231)
    ENDIF

IF ( bFlicker )
    ghostFlash(1.0)
ENDIF
ENDEVENT


EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
; When the ghost is hit and the player is not using the proper weapon, fade them out only

IF ( b4 )
    RETURN    ; - STOP -    hit was blocked
ENDIF
;--------------------- by default "bFlicker is False", that means OnHit() event has no action inside
IF ( bFlicker )
    IF ( bFlash )
        RETURN    ; - STOP -    flash action is still running
    ENDIF
;    ----------------------
    IF pDefaultGhostWeaponFlickerList.HasForm(akSource)
        RETURN    ; - STOP -    do no flash caused by weapon hit
    ENDIF
;    ----------------------
    bFlash = TRUE
    ;target = akAggressor as Actor                ; *) ??? see script variable on top
    ghostFlash(3.0)
ENDIF
ENDEVENT


;==========================
state Done  ; busy with disintegration process
;=========
    EVENT OnLoad()
    ENDEVENT
    
    EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProj, Bool b1, Bool b2, Bool b3, Bool b4)
    ENDEVENT
;=======
endState


EVENT OnDying(Actor akKiller)  ; its a bit different to script "defaultGhostScriptRefAlias.psc"
IF ( bFade )
    self.BlockActivation(TRUE)
    self.Disable(TRUE)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF ( pDisintegrationMainImmunityList )
    actorBase AB = self.GetBaseObject() as ActorBase                ; AB = VictimeBase
    IF pDisintegrationMainImmunityList.HasForm( AB.GetRace() )
        RETURN    ; - STOP -
    ENDIF
;    ----------------------
    IF pDisintegrationMainImmunityList.HasForm(AB)
        RETURN    ; - STOP -
    ENDIF
;    ----------------------
ENDIF

    gotoState("Done")                ; ### STATE ###
    pGhostFXShader.Stop(self)                            ; *** added by ReDragon 2020 ***

    self.SetCriticalStage( self.CritStage_DisintegrateStart )  ; Ashpile started
;    ---------------------------------------------------------
    IF ( pGhostDeathFXShader )
        pGhostDeathFXShader.Play(self, ShaderDuration)
    ENDIF

    self.SetAlpha(0.0, TRUE)
    self.AttachAshPile(pDefaultAshPileGhost)

    IF ( bdefaultLoot )                ; == TRUE
        self.RemoveAllItems()
        self.AddItem(pdefaultGhostLeveledList)
    ENDIF

    Utility.Wait(fDelayEnd)                ; by default, wait here for 1.65 sec

    IF ( pGhostDeathFXShader )
        pGhostDeathFXShader.Stop(self)
    ENDIF

    IF ( bSetAlphaZero )            ; == TRUE
        self.SetAlpha(0.0, TRUE)
    ENDIF
;    -------------------------------------------------------
    self.SetCriticalStage( self.CritStage_DisintegrateEnd )  ; Ashpile finished
ENDEVENT

 

 

Edited by ReDragon2013
Link to comment
Share on other sites

There are some vanilla friendly ghost npcs that they only use the 'Ab Spell' and nothing more from the script, to those npcs i'm mostly referring.


If they won't use 'Effect Shaders' - 'Explosions'... etc, why add the Ghost Ab by script and not directly, especially since they are 'Unique' actors.


Thanks for the reply.

Link to comment
Share on other sites

Can you give an example of one of those NPCs?

 

For ones I've ran across that use both the ability and the script, Beth was being fancy with trying to simulate the ghosts "phasing" in and out of existence every time they are hit with a weapon. This is done by turning off the shader and turning it back on. The script function appears to override the ability in this manner. Also, the ashpiles needs to be applied when they die.

Link to comment
Share on other sites

Hey Rasikko.


First of all i would like to say thanks and a big SORRY to anyone that read this post !, please just pretend that this never happened...


The last couple of days i ate too much sugar, and i'm not allow to eat sugar or more than 1 cup of coffee per day, sugar has a very bad effect on me... worse than lsd !.


Everybody keep sending all those sweets and cakes for christmas, and i'm all alone, my girlfriend is out of town so there isn't anyone around to control me, plus i can't go out cause of the 'quarantine lockdown', so i fell into a meaningless stupid mind trip.


I woke up today and i feel like i've been swimming against the current for days, i took a look at the things i did the last two days... and O My God !!@!! i deleted everything...


No more sugar for me please...


Happy new year to everyone !!.

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...