VRNord Posted April 23, 2021 Share Posted April 23, 2021 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 More sharing options...
ReDragon2013 Posted April 24, 2021 Share Posted April 24, 2021 (edited) 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 questjaypSF_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 usingjaypSF_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 sprigginjaypSF_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 April 24, 2021 by ReDragon2013 Link to comment Share on other sites More sharing options...
maxarturo Posted April 25, 2021 Share Posted April 25, 2021 (edited) 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 April 25, 2021 by maxarturo Link to comment Share on other sites More sharing options...
dylbill Posted April 25, 2021 Share Posted April 25, 2021 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 More sharing options...
maxarturo Posted April 25, 2021 Share Posted April 25, 2021 (edited) 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 April 25, 2021 by maxarturo Link to comment Share on other sites More sharing options...
dylbill Posted April 25, 2021 Share Posted April 25, 2021 Ah gotcha, yes that's a good practice to help beginners learn. As always, happy modding :) Link to comment Share on other sites More sharing options...
VRNord Posted April 25, 2021 Author Share Posted April 25, 2021 Thanks for the advice! I'm not so great with scripts so will take away to see if I can make it work. Link to comment Share on other sites More sharing options...
Recommended Posts