Jump to content

Leveled list not random?


VRNord

Recommended Posts

My follower is a conjurer and I got tired of constantly seeing that damn familiar wolf so I created 4 new spells that conjure as familiar one of the 4 types of spriggans each. Works like a charm. However my follower seems to cast the lowest (bottom entry of the list) of the 4 spells maybe 90% of the time regardless of whether I add the 4 spells directly to his Actor Effects, or if I add them to a Leveled Spell List and then add that LVSP to his Actor Effects. Ideally he would cast each of them 25% of the time otherwise I still get tired of seeing the same familiar all the time.



  • Each of the familiar NPCs, magic effects and spells have identical stats and levels (in case he is selecting the most powerful, they are all the same)
  • I made the strength of their attack (the concentration spray or fire for the burnt one) deal the same damage
  • the LVSP assigns the same level ("1") to each of the spells
  • I have all 3 LVLF flags checked on the LVSP form


He does maybe 10% of the time summon one of the other Spriggans - I have seen them all conjured so I know all the other spells work - but he sticks with whichever spell I input to the bottom of the list 90% of the time.



I thought of adding all 4 MGEF's to a single spell and doing a "getrandom" number chance of 25% for each, like the DLC2 Chaos enchantment, but that runs a high chance of more than one being conjured at a time.


Is there a different way I could do this to get him to use the spells more randomly?


Link to comment
Share on other sites

My idea in shorten: A quest script is storage for two properties (the caster and a controller spell).

The controller spell has an array as property with all your familiar spells. Controller spell has to be added to follower directly (its your choice to do that). The familiar spells will be casted by controller spell.

After spell casting of familiar, the controller spell will be removed from caster. If the familiar is gone the controller spell will be addad back to caster.

 

1) create a new quest (you can duplicate an existing quest, make sure its a pure quest, no stages, no alias or any other thing), no idea whether the quest has to be "start game enabled" or not (probably not), attach next script to that quest

jaypSF_QuestScript

 

Scriptname jaypSF_QuestScript extends Quest Hidden
; https://forums.nexusmods.com/index.php?/topic/9934703-leveled-list-not-random/


  Spell PROPERTY mySpell auto            ; spell which contains magiceffect, "jaypSF_ControllerMGEFScript" is attached there
  Actor PROPERTY myCaster auto Hidden    ; will be filled during runtime


; -- EVENT -- 1 / 3

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

 

 

 

2) create a controller spell (no duration here, with type fire and forget) and attach next script to the magic effect which this spell is using

jaypSF_ControllerMGEFScript

 

Scriptname jaypSF_ControllerMGEFScript extends ActiveMagicEffect
; https://forums.nexusmods.com/index.php?/topic/9934703-leveled-list-not-random/

; spell type: fire and forget

  Quest  PROPERTY myQuest auto        ; quest you have created, "jaypSF_QuestScript" is attached

  Spell[] PROPERTY myArray auto       ; fill this property by adding with CK all the spells
  ; like vanilla summoning "ghost wolf" duplicated by you


; -- EVENT -- 2 / 3

EVENT OnEffectStart(Actor akTarget, Actor akCaster)
    myF_Action(akCaster)
ENDEVENT


; -- FUNCTION --

;----------------------------------
FUNCTION myF_Action(Actor akCaster)
;----------------------------------
    jaypSF_QuestScript ps = myQuest as jaypSF_QuestScript

IF ( ps )
ELSE
    Debug.Trace(" ERROR: 01 - quest = " +myQuest+ ", script = " +ps)
    RETURN    ; - STOP -    missing quest property or script!
ENDIF
;---------------------
IF ( ps.mySpell )
ELSE
    Debug.Trace(" ERROR: 02 - spell property is missing!")
    RETURN    ; - STOP -
ENDIF
;---------------------
    ps.myCaster = akCaster                ; store the follower (caster of familiar) to hidden quest property
    myCaster.RemoveSpell( ps.mySpell )                    ; *** now remove the controller spell

    int i = myArray.Length - 1

    IF (i < 0)
        Debug.Notification("Failure with array property.")
        Debug.Trace(self+" OnEffectStart() - Array is empty!")
    ELSE
        i = Utility.RandomInt(0, i)
        Debug.Notification("Summoning creature.. " +i)        ; !!! should be removed on release !!!

        spell sp = myArray[i]
        IF ( sp )
            sp.Cast(akCaster as ObjectReference)        ; *** spell will be added back to caster, if effect finished
        ENDIF
    ENDIF
ENDFUNCTION

 

 

 

3) now attach this script to the effect(s) which is/are used in your created spells to conjure a spriggin

jaypSF_MGEFScript

 

Scriptname jaypSF_MGEFScript extends ActiveMagicEffect
; https://forums.nexusmods.com/index.php?/topic/9934703-leveled-list-not-random/

; attach this script to each MagicEffect
; "so I created 4 new spells that conjure as familiar one of the 4 types of spriggans each"

; we assume one effect for each summoning spell, in case there is one effect for all spells no problem here
; each spell will be used for array in "jaypSF_ControllerMGEFScript"


  Quest PROPERTY myQuest auto        ; we need a place to store caster and spell


; -- EVENT -- 3 / 3

EVENT OnEffectFinish(Actor akTarget, Actor akCaster)
    jaypSF_QuestScript ps = myQuest as jaypSF_QuestScript       ; try to get the quest script

    IF ( ps )
        actor aRef = ps.myCaster                                ; get the stored caster
        IF ( aRef )
            ps.myCaster = None                ; release actor persistent by quest script
            aRef.AddSpell( ps.mySpell )       ; give back the controller spell to summon another familiar
        ENDIF
    ENDIF
ENDEVENT

 

 

 

Do not forget to fill the properties. And keep in mind its an approach, maybe something has to be fine tuned or its not working as intended.

 

Limitation: This is working for one NPC only. It cannot handle multiple actors which are using the controller spell.

Edited by ReDragon2013
Link to comment
Share on other sites

Another approach is to add directly to your follower a simple script to manage randomly which spell the actor will use.

Example script:

*The script 'Extends Actor'.



Spell Property Spell01 Auto
Spell Property Spell02 Auto
Spell Property Spell03 Auto
Spell Property Spell04 Auto


EVENT OnCombatStateChanged(Actor attacker, int aeCombatState)
If ( aeCombatState == 0 ) ; Actor has exit combat
CheckSpell() ; Function to remove spell when actor exits combat
ElseIf ( aeCombatState == 1 ) ; Actor enters combat
Int RS = RandomInt(0, 3) ; We generate a random number and it adds the corresponding spell
If ( RS == 0 )
Self.AddSpell(Spell01)
ElseIf ( RS == 1 )
Self.AddSpell(Spell02)
ElseIf ( RS == 2 )
Self.AddSpell(Spell03)
ElseIf ( RS == 3 )
Self.AddSpell(Spell04)
EndIf
EndIf
ENDEVENT


FUNCTION CheckSpell() ; Function to remove spell when actor exits combat
If ( Self.HasSpell(Spell01) )
Self.RemoveSpell(Spell01)
EndIf
If ( Self.HasSpell(Spell02) )
Self.RemoveSpell(Spell02)
EndIf
If ( Self.HasSpell(Spell03) )
Self.RemoveSpell(Spell03)
EndIf
If ( Self.HasSpell(Spell04) )
Self.RemoveSpell(Spell04)
EndIf
ENDFUNCTION



NOTE 01:

You don't need to add any of the spells to the actor, the script will handle that.


NOTE 02:

When the actor enter "Bleed Out" will fire again the "OnCombatStateChanged()" event adding again a spell, we can add a 'Fail Safe' to not add more than 1 spell each time the actor/follower enters combat and in the same combat session the actor enters the "Bleed Out" state.

But i think living the script as it is adds a little more "Random Behavior" in combat, since in this particular circumstance the actor may use different spells in the same combat session making him a little more interesting.

* The same applies if the actor is in combat > then loses the target but it searching for it > and then it enters combat again.


Have a happy modding.

Edited by maxarturo
Link to comment
Share on other sites

Hey Maxaturo, I like your script. Just a tip, for getting random forms, use an array instead for better performance. This cuts down on If and Elseif condition checks. Most of the time this isn't an issue, but if you're like me and always install a lot of mods for your playthrough it can be a problem if a lot of scripts are running at the same time. You can also just remove all the spells when combat ends, instead of checking each for the same reason.

Spell[] Property SummonSpells Auto
;fill this array with spells to choose from in the CK

EVENT OnCombatStateChanged(Actor attacker, int aeCombatState)
    If ( aeCombatState == 0 )          ; Actor has exit combat
        Int M = SummonSpells.Length 
        While M > 0 ;iterate through and remove all spells from the SummonSpells array
            M -= 1 
            Self.RemoveSpell(SummonSpells[M])
        EndWhile
        
    ElseIf ( aeCombatState == 1 )          ; Actor enters combat
        Self.AddSpell(SummonSpells[Utility.RandomInt(0, 3)])  ; We generate a random number and it adds the corresponding spell
    EndIf
ENDEVENT
Link to comment
Share on other sites

Yes you are right, but when i post 'Example' scripts i try to make them as simple as possible so that the OP (which in most circumstances is a newby) may understand it, study it and evolve his own scripting style.


Arrays, States... and a bounch of other stuff that make scripts faster and/or more flexible may not be that easy to understand if you don't have the basic knowledge.

Edited by maxarturo
Link to comment
Share on other sites

  • Recently Browsing   0 members

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