Jump to content

[LE] OnHit effect for Scrolls


Recommended Posts

Hey all,

 

I created a new spell with a custom script, that uses the OnHit function on the target to determine if the player cast the right spell. If so, apply script function. In this case, I have the spell set up to work.

 

The problem is, I made a scroll for the magic effect and cannot get it to apply the same script when used. I added the same check in the magic effect as akSource == MySpell as Form, but the akSource == MySpellScroll as Form doesn't seem to work ( one is a Spell while the other is a Scroll property ).

 

How do I set it so that the script detects both the spell AND scroll effects and acts accordingly? Or use the magic effect in worst case ( but I'd like to separate the two, as the spell should increase skill XP via script while the scroll shouldn't, so... ).

Link to comment
Share on other sites

I'm not sure if i understand you correctly, but you can instead of listening for the spell, listen the 'Active Magic Effect'.

Event OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect)

MagicEffect Function GetBaseObject() native

bool Function HasMagicEffect(MagicEffect akEffect) native






* It would be more helpful to post your script and add a little more detail to your issue, there are quite a few individuals that can help you, but i fear they also didn't understand what you are trying to say.

Link to comment
Share on other sites

Just a sample to show what is happen

spell     [SPEL:00043324] Candlelight "Candlelight"
scroll    [SCRL:0009659B] CandlelightScroll "Scroll of Candlelight"

    both should have the same magic effect

effect    [MGEF:0001EA6C] LightFFSelf "Candlelight"

variant A just the magic effect

 

Scriptname xyzTestMGEFScript extends ActiveMagicEffect
; https://forums.nexusmods.com/index.php?/topic/8686563-onhit-effect-for-scrolls/

  MagicEffect PROPERTY myEffect  auto    ; the same effect from scroll or spell


; -- EVENTs --

; Event received when this effect is first started (OnInit may not have been run yet!)
EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    Debug.Trace(self+" started..")
ENDEVENT

; Event received when this effect is finished (effect may already be deleted, calling functions on this effect will fail)
EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    Debug.Trace(self+" finished..")
ENDEVENT


; Event received when a magic affect is being applied to this object
EVENT OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect)
IF (akCaster == Game.GetPlayer() as ObjectReference)
    IF (akEffect == myEffect)
        ; special effect was applied to target
    ENDIF
ENDIF
ENDEVENT

 

 

 

variant B with keyword

 

Scriptname xyzTestMGEFScript extends ActiveMagicEffect
; https://forums.nexusmods.com/index.php?/topic/8686563-onhit-effect-for-scrolls/

  Keyword     PROPERTY myKeyword auto    ; a special keyword applied to the magic effect


; -- EVENTs --

; Event received when this effect is first started (OnInit may not have been run yet!)
EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    Debug.Trace(self+" started..")
ENDEVENT

; Event received when this effect is finished (effect may already be deleted, calling functions on this effect will fail)
EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    Debug.Trace(self+" finished..")
ENDEVENT


; Event received when this object is hit by a source (weapon, spell, explosion) or projectile attack
EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
IF (akSource as Scroll) || (akSource as Spell)
    IF self.GetTargetActor().HasMagicEffectWithKeyword(myKeyword))
        Debug.Trace(" OnHit() - target was hit by players magic with " +akSource)
    ENDIF
ENDIF
ENDEVENT

 

 

 

variant C like your approach

 

Scriptname xyzTestMGEFScript extends ActiveMagicEffect
; https://forums.nexusmods.com/index.php?/topic/8686563-onhit-effect-for-scrolls/

  Spell       PROPERTY mySpell   auto
  Scroll      PROPERTY myScroll  auto


; -- EVENTs --

; Event received when this effect is first started (OnInit may not have been run yet!)
EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    Debug.Trace(self+" started..")
ENDEVENT

; Event received when this effect is finished (effect may already be deleted, calling functions on this effect will fail)
EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    Debug.Trace(self+" finished..")
ENDEVENT


; Event received when this object is hit by a source (weapon, spell, explosion) or projectile attack
EVENT OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, bool abPowerAttack, bool abSneakAttack, bool abBashAttack, bool abHitBlocked)
IF (akSource == myScroll as Form)
    Debug.Trace(" OnHit() - target was hit by players scroll " +akSource)
    RETURN    ; - STOP -
ENDIF
;---------------------
IF (akSource == mySpell as Form)
    Debug.Trace(" OnHit() - target was hit by players spell " +akSource)
;;;    RETURN    ; - STOP -
ENDIF
ENDEVENT

 

 

Link to comment
Share on other sites

I think the simplest way would be to make separate spells with separate magic effects for the spell and the scroll, and put separate scripts on the magic effects. That way you can just use OnEffectStart:

 

 

 

Scriptname TestScrollScript extends ActiveMagicEffect 

;Put this on the scroll's magic effect 

Actor Property PlayerRef Auto 

Event OnEffectStart(Actor akTarget, Actor akCaster) 
    If akCaster == PlayerRef 
        ;do something, not increasing XP 
    Endif 
EndEvent 


Scriptname TestSpellScript extends ActiveMagicEffect 

;Put this on the Spell's magic effect 

Actor Property PlayerRef Auto 

Event OnEffectStart(Actor akTarget, Actor akCaster) 
    If akCaster == PlayerRef 
        ;do something, also increasing XP 
    Endif 
EndEvent

Link to comment
Share on other sites

Basically, the script fires when an alias is filled in the quest. I thought about making it a magic effect instead of spell\scroll property, but didn't know how to implement it properly here.

I get that the scroll part is completely wrong and cannot work like that. I might try the method with the keyword, as that seems to be the best one.

 

 

Spell Property OpenNoviceLock Auto
Spell Property OpenApprenticeLock Auto
Spell Property OpenAdeptLock Auto
Spell Property OpenExpertLock Auto
Spell Property OpenMasterLock Auto
Scroll Property OpenNoviceScroll Auto
Scroll Property OpenApprenticeScroll Auto
Scroll Property OpenAdeptScroll Auto
Scroll Property OpenExpertScroll Auto
Scroll Property OpenMasterScroll Auto
Sound Property UnlockSound Auto
Sound Property UnlockFailSound Auto
Sound Property UnlockFailSound2 Auto
function OnHit(ObjectReference akAggressor, Form akSource, Projectile akProjectile, Bool abPowerAttack, Bool abSneakAttack, Bool abBashAttack, Bool abHitBlocked)
Int level = self.GetReference().GetLockLevel()
if akSource == OpenNoviceLock as Form && level < 2 || akSource == OpenApprenticeLock as Form && level < 26 || akSource == OpenAdeptLock as Form && level < 51 || akSource == OpenExpertLock as Form && level < 76 || akSource == OpenMasterLock as Form && level < 101
self.GetReference().Lock(false, false)
UnlockSound.Play(self.GetReference())
if akSource == OpenNoviceLock as Form && level < 2
Game.AdvanceSkill("Alteration", 10.0)
elseif akSource == OpenApprenticeLock as Form && level < 26
Game.AdvanceSkill("Alteration", 20.0)
elseif akSource == OpenAdeptLock as Form && level < 51
Game.AdvanceSkill("Alteration", 30.0)
elseif akSource == OpenExpertLock as Form && level < 76
Game.AdvanceSkill("Alteration", 40.0)
elseif akSource == OpenMasterLock as Form && level < 101
Game.AdvanceSkill("Alteration", 50.0)
endif
elseIf akSource == OpenNoviceLock as Form && level >= 2 || akSource == OpenApprenticeLock as Form && level >= 26 || akSource == OpenAdeptLock as Form && level >= 51 || akSource == OpenExpertLock as Form && level >= 76 || akSource == OpenMasterLock as Form && level >= 101
debug.notification("This lock is too complex!")
UnlockFailSound.Play(self.GetReference())
UnlockFailSound2.Play(self.GetReference())
endIf
if akSource == OpenNoviceScroll as Form && level < 2 || akSource == OpenApprenticeScroll as Form && level < 26 || akSource == OpenAdeptScroll as Form && level < 51 || akSource == OpenExpertScroll as Form && level < 76 || akSource == OpenMasterScroll as Form && level < 101
self.GetReference().Lock(false, false)
UnlockSound.Play(self.GetReference())
elseIf akSource == OpenNoviceScroll as Form && level >= 2 || akSource == OpenApprenticeScroll as Form && level >= 26 || akSource == OpenAdeptScroll as Form && level >= 51 || akSource == OpenExpertScroll as Form && level >= 76 || akSource == OpenMasterScroll as Form && level >= 101
debug.notification("This lock is too complex!")
UnlockFailSound.Play(self.GetReference())
UnlockFailSound2.Play(self.GetReference())
endIf
endFunction
Link to comment
Share on other sites

Advice for next request for help. Give enough information to other users so they can understand your issue much better.

Keep in mind the script name should be more unique.

 

xyzUnLockAliasScript

 

Scriptname xyzUnLockAliasScript extends ReferenceAlias
; https://forums.nexusmods.com/index.php?/topic/8686563-onhit-effect-for-scrolls/

  FormList PROPERTY myList auto       ; predefined by CK with magic effects of your unlock spells/scrolls
  ; 0 ulNovice                        ; ul = unlock
  ; 1 ulApprentice
  ; 2 ulAdept
  ; 3 ulExpert
  ; 4 ulMaster
  ; 5 ulGrandmaster

  Sound PROPERTY UnlockSound      auto
  Sound PROPERTY UnlockFailSound  auto
  Sound PROPERTY UnlockFailSound2 auto


; -- EVENTs -- 2

EVENT OnInit()
   Debug.Trace(" OnInit() - has been reached.. " +self)    ; debugging only
ENDEVENT

EVENT OnCellDetach()
   Debug.Trace(" OnCellDetach() - out of players loaded cells")
;;; self.Clear()       ; remove binding from alias with objectReference
ENDEVENT

EVENT OnMagicEffectApply(ObjectReference akCaster, MagicEffect akEffect)
IF (akCaster == Game.GetPlayer() as ObjectReference)
ELSE
    RETURN    ; - STOP -    not affected by players magic
ENDIF
;---------------------
    objectReference selfRef = self.GetReference()
    int o = myF_GetLock(selfRef)             ; o = level of lock

IF (o == 0)
    RETURN    ; - STOP -    not locked
ENDIF
;---------------------
    int i = myF_GetStrength(akEffect)

    IF (i >= o)
        selfRef.Lock(False, False)           ; unlock
        UnlockSound.Play(selfRef)            ; sound effect
        myF_GiveXP(i)                                               ; the strength of magic
;;;        myF_GiveXP(o)                                            ; the lock level
    ELSE
        Debug.Notification("This lock is too complex!")
        UnlockFailSound.Play(selfRef)
        UnlockFailSound2.Play(selfRef)
    ENDIF
ENDEVENT


; -- FUNCTIONs -- 3

;------------------------------------------------
Int FUNCTION myF_GetLock(ObjectReference selfRef)
;------------------------------------------------
; https://www.creationkit.com/index.php?title=GetLockLevel_-_ObjectReference

IF selfRef.IsLocked()
ELSE
    RETURN 0    ; already unlocked
ENDIF
;---------
    int i = selfRef.GetLockLevel()        ; get the level of door, chest or something else

IF (i < 2)
    RETURN 1    ; novice (0,1)
ENDIF
;---------
IF (i < 26)
    RETURN 2    ; Apprentice (2 .. 25)
ENDIF
;---------
IF (i < 51)
    RETURN 3    ; Adept (26 .. 50)
ENDIF
;---------
IF (i < 76)
    RETURN 4    ; Expert (51 .. 75)
ENDIF
;---------
IF (i < 101)
    RETURN 5    ; Master (76 .. 100)
ENDIF
;---------
    RETURN 6    ; Grandmaster (101 .. 255)
ENDFUNCTION


;-------------------------------------------------
Int FUNCTION myF_GetStrength(MagicEffect akEffect)  ; Keep in mind: formlists starts with ZERO
;-------------------------------------------------
    int i = myList.GetSize()        ; get size of formlist
    WHILE (i)
        i = i - 1
        form fm = myList.GetAt(i)
        IF (fm == akEffect as Form)
            RETURN (i+1)            ; novice = 1, apprentice = 2, adept = 3, expert = 4, master = 5, grandmaster = 6
        ENDIF
    ENDWHILE
    RETURN 0                        ; unknown effect = 0
ENDFUNCTION


;-------------------------
FUNCTION myF_GiveXP(Int i)
;-------------------------    
    float f = i as Float

    IF (i < 6)
        f = f * 10.0                                       ; 1 -> 10.0 .. 5 -> 50.0
    ELSE
        f = self.GetReference().GetLockLevel() as Float    ; 6 -> 101.0 .. 255.0
    ENDIF

    Game.AdvanceSkill("Alteration", f)
ENDFUNCTION

 

 

 

You need six magic effects, which could be the same. but must have different formIDs. Duplicate the magic effect you already have to get the other five effects.

Create a new formlist and put all these magic effects inside from novice up to grandmaster.

 

And that also means you have 5 scrolls and 5 spells, you should create another scroll and spell for grandmaster.

Edited by ReDragon2013
Link to comment
Share on other sites

Thanks for all the help and sorry if I wasn't clear enough.

 

ReDragon2013, you've added a lot of stuff to the script, and explained very well, so thank you. But I'll point out a few things, since I didn't explain it clearly before:

 

First - I did create 5 spells, each with their respective scroll. There is no need for the 6th, as that would allow the player to access places that require a key, which could potentially break the game.

 

Second - The OnCellDetach is quite a useful function, as I noticed using it the aliases don't bug out sometimes anymore. Thank you for reminding me of its existence.

 

Third - I'm not sure what you meant by script name, as I didn't even post that line, and I believe it to be quite unique, since I can easily find it.

 

Fourth - How the hell do you set the script to be formatted like that in your post? I could really use that.

 

 

Also note that I tend to minimalize the code, as to why I made it as you've seen it. Again, thank you for all the help. I'll try it out soon.

Link to comment
Share on other sites

  • Recently Browsing   0 members

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