Sphered Posted February 14, 2022 Share Posted February 14, 2022 Its a method amongst others for storing dynamic information. 128 limit is annoying for certain goals and this would be one way to side step that. Really tho the main point was if you need help with strings you def dont want to ignore a powerful SKSE script dedicated to exactly resolving strings Link to comment Share on other sites More sharing options...
ItsAlways710 Posted February 14, 2022 Author Share Posted February 14, 2022 Ahhh, point taken for certain, StringUtil has some very powerful uses, and I can see how I can use some of these features like StringUtil.Split in the future! The thought had never occurred to me to use a single string to store multple values of ANYTHING let alone hex hehehe....and I will remember the method of using a state with it... Thank you! Link to comment Share on other sites More sharing options...
ItsAlways710 Posted February 14, 2022 Author Share Posted February 14, 2022 I can see storing everything in one string with two separators, (Like this - string theory = FlamesXXX0x9DFABZZZHealingXXX0x9DFACZZZ etc,) then split on ZZZ sort the resultant list, then loop through that array splitting the form off of the spell names.... I can see why you are directing me to look further at StringUtil, VERY powerful indeed... Link to comment Share on other sites More sharing options...
ItsAlways710 Posted February 16, 2022 Author Share Posted February 16, 2022 I had time to play with this some more, and have landed on something like this, in very early stages but it is doing what I want it to do. I actually had the OnInit going much faster, but found this to be a bad thing, I think the OnPlayerLoadGame will be the only one that the speed will matter that much, and even in it's current form it's not horrible, but I'm sure could be improved. ;Import PO3_Events_Alias ;Import PO3_SKSEFunctions ; https://github.com/powerof3/PapyrusExtenderSSE/tree/master/src/Papyrus ;Import StorageUtil ; https://github.com/Vicyntae/SCLSE/blob/master/Data/Source/Scripts/StorageUtil.psc ; StorageUtil name: "HAC_Spells" ; list of strings, names of spells the player has currently ; StorageUtil name: "HAC_RaceSpells" ; list of strings, names of spells the player has initially ; StorageUtil name: "map" ; list of strings as keyname to formID as value ; used in MCM script with StorageUtil.GetFormValue(None, (StorageUtil.StringListGet(None, "HAC_Spells", INDEX+1))) ; -- Events -- 3 Event OnInit() ; called first time mod will be seen on game (newgame or savegame) Debug.Notification("HAC: Initializing Spell List") CreateInitSpellList() CreateRaceSpells() InsertMenu_HAC_Spells() ; Insert the escape menu Debug.Notification("HAC: Spell List Initiated") PO3_Events_Alias.RegisterForSpellLearned(self) ; register for special event EndEvent Event OnPlayerLoadGame() ; called every time a mod was loaded by savegame (player alias script only!) PO3_Events_Alias.UnRegisterForSpellLearned(self) ; unregister for the special event Debug.Notification("HAC: Starting Spell Maintenance") CreateSpellList() InsertMenu_HAC_Spells() ; Insert the escape menu Debug.Notification("HAC: Spell Maintenance Completed") PO3_Events_Alias.RegisterForSpellLearned(self) ; register for special event EndEvent Event OnSpellLearned(Spell akSpell) ; added by Papyrus Extender SSE StorageUtil.StringListRemoveAt(None, "HAC_Spells", 0) ; remove the escape menu, before adding a new spell to stringlist Update_HAC_Spells(akSpell) ; add this spell to stringlist InsertMenu_HAC_Spells() ; insert the escape menu EndEvent ; -- Functions -- 5 Function Update_HAC_Spells(Spell akSpell) ;-------- 2 string s = akSpell.GetName() ; get the spell name as string StorageUtil.SetFormValue(None, s, akSpell as Form) ; Make sure that the spell name string is mapped to the correct formid StorageUtil.StringListAdd(None, "HAC_Spells", s, False) ; Add a new spell name to stringlist with allowdupes == FALSE EndFunction Function InsertMenu_HAC_Spells() ;-------- 3 StorageUtil.StringListSort(None, "HAC_Spells") ; Sort the stringlist before insert the menu entry! ; Insert to stringlist at index 0 an escape menu as way out StorageUtil.StringListInsert(None, "HAC_Spells", 0, "Back / Cancel / No Change") EndFunction Function CreateSpellList() ;-------- 4 actor player = Game.GetPlayer() string s StorageUtil.StringlistClear(None, "HAC_Spells") ; *** clear *** If StorageUtil.StringListCount(None, "HAC_RaceSpells") StorageUtil.StringListCopy(None, "HAC_Spells", StorageUtil.StringListToArray(None, "HAC_RaceSpells")) ; add race specific spells EndIf ; https://www.creationkit.com/index.php?title=GetSpellCount_-_Actor ; https://www.creationkit.com/index.php?title=GetNthSpell_-_Actor int i = player.GetSpellCount() While (i) i = i - 1 spell akSpell = player.GetNthSpell(i) ; GetNthSpell(0) is the last added spell If akSpell.GetNthEffectMagicEffect(0).GetCastingType() s = akSpell.GetName() ; get the spell name as string StorageUtil.SetFormValue(None, s, akSpell as Form) ; Make sure that the spell name string is mapped to the correct formid StorageUtil.StringListAdd(None, "HAC_Spells", s, False) ; Add a new spell name to stringlist EndIf EndWhile EndFunction Function CreateInitSpellList() ;-------- 4 actor player = Game.GetPlayer() StorageUtil.StringlistClear(None, "HAC_RaceSpells") ; *** clear *** ; https://www.creationkit.com/index.php?title=GetSpellCount_-_Actor ; https://www.creationkit.com/index.php?title=GetNthSpell_-_Actor spell[] a = PO3_SKSEFunctions.GetAllSpells() ; Build a temp array with all spells in the game int i = a.length While (i) i = i - 1 If a[i].GetNthEffectMagicEffect(0).GetCastingType() If player.HasSpell( a[i] ) ; check spell from array to see if the player knows it or not Update_HAC_Spells(a[i]) EndIf EndIf EndWhile EndFunction Function CreateRaceSpells () actor player = Game.GetPlayer() string s StorageUtil.StringListCopy(None, "HAC_RaceSpells", StorageUtil.StringListToArray(None, "HAC_Spells")) int i = player.GetSpellCount() While (i) i = i - 1 spell akSpell = player.GetNthSpell(i) ; GetNthSpell(0) is the last added spell If akSpell.GetNthEffectMagicEffect(0).GetCastingType() s = akSpell.GetName() StorageUtil.StringListRemove(None, "HAC_RaceSpells", s, True) EndIf EndWhile EndFunction Link to comment Share on other sites More sharing options...
ItsAlways710 Posted February 17, 2022 Author Share Posted February 17, 2022 I've had a bit more time to work on it and have tried implementing some things I have learned, please let me know if I'm not doing something correctly or I am doing something that is pointless, some changes from the last version: - Refresh State and bool- RegisterForSingleUpdate- Reorganized, removed some pointless lines, more comments ;Import PO3_Events_Alias ;Import PO3_SKSEFunctions ; https://github.com/powerof3/PapyrusExtenderSSE/tree/master/src/Papyrus ;Import StorageUtil ; https://github.com/Vicyntae/SCLSE/blob/master/Data/Source/Scripts/StorageUtil.psc ; StorageUtil name: "HAC_Spells" ; list of strings, names of spells the player has currently ; StorageUtil name: "HAC_RaceSpells" ; list of strings, names of spells the player has initially ; StorageUtil name: "map" ; list of strings as keyname to formID as value ; used in MCM script with StorageUtil.GetFormValue(None, (StorageUtil.StringListGet(None, "HAC_Spells", INDEX+1))) Bool bRefresh ; [default=False] ; ------------ ; -- Events -- 3 + "Refresh" ; ------------ Event OnInit() ; called first time mod will be seen on game (newgame or savegame) InitList() endEvent Event OnPlayerLoadGame() ; called every time a mod was loaded by savegame (player alias script only!) InitList() endEvent Event OnSpellLearned(Spell akSpell) ; added by Papyrus Extender SSE While ( bRefresh ) Utility.Wait(0.1) ; just in case, do not allow another thread to sneak in to an update in progress endWhile bRefresh = TRUE ; *T* StorageUtil.StringListRemoveAt(None, "HAC_Spells", 0) ; remove the escape menu, before adding a new spell to stringlist Update_HAC_Spells(akSpell) ; add this spell to stringlist InsertMenu_HAC_Spells() ; insert the escape menu bRefresh = False ; *** endEvent State Refresh Function InitList() ; empty here, OnInit() or OnPlayerLoadGame() event can be the first ("first come, first serve") endFunction Event OnUpdate() If ( bRefresh ) RETURN ; - STOP - Just in case! endIf ; ------------------------ bRefresh = TRUE ; *T* PO3_Events_Alias.UnRegisterForSpellLearned(self) ; unregister for the special event If StorageUtil.StringListCount(None, "HAC_RaceSpells") == 0 ; if Event is OnInit Debug.Notification("HAC: Initializing Spell List") CreateInitSpellList() ; Create Initial Spell List grabbing race spells at the same time CreateRaceSpells() ; Make "HAC_RaceSpells" array and store in StorageUtil InsertMenu_HAC_Spells() ; Insert the escape menu Debug.Notification("HAC: Spell List Initiated") gotoState("") ; ### STATE ### Else ; if Event is OnPlayerLoadGame Debug.Notification("HAC: Starting Spell Maintenance") CreateSpellList() ; Create spell list using GetNthSpell and adding "HAC_RaceSpells" to array InsertMenu_HAC_Spells() ; Insert the escape menu Debug.Notification("HAC: Spell Maintenance Completed") gotoState("") ; ### STATE ### endIf PO3_Events_Alias.RegisterForSpellLearned(self) ; register for special event bRefresh = False ; *** endEvent endState ; -- Functions -- 6 Function InitList() ;-------- 1 gotoState("Refresh") ; ### STATE ### RegisterForSingleUpdate(0.1) endFunction Function CreateInitSpellList() ;-------- 2 actor player = Game.GetPlayer() StorageUtil.StringlistClear(None, "HAC_RaceSpells") ; *** clear *** spell[] a = PO3_SKSEFunctions.GetAllSpells() ; Build a temp array with all spells in the game int i = a.length While (i) i = i - 1 If a[i].GetNthEffectMagicEffect(0).GetCastingType() ; Ensure spell is castable If player.HasSpell(a[i]) ; Check spell from array to see if the player knows it or not Update_HAC_Spells(a[i]) ; Update HAC_Spells and MAP endIf endIf endWhile endFunction Function CreateRaceSpells () ;-------- 3 actor player = Game.GetPlayer() string s StorageUtil.StringListCopy(None, "HAC_RaceSpells", StorageUtil.StringListToArray(None, "HAC_Spells")) ; Insert HAC_Spells as HAC_RaceSpells int i = player.GetSpellCount() While (i) i = i - 1 spell akSpell = player.GetNthSpell(i) ; GetNthSpell(0) is the last added spell If akSpell.GetNthEffectMagicEffect(0).GetCastingType() ; Ensure spell is castable s = akSpell.GetName() ; get the spell name as string StorageUtil.StringListRemove(None, "HAC_RaceSpells", s, True) ; Remove all instances of string returned by GetNthSpell from HAC_RaceSpells endIf endWhile endFunction Function CreateSpellList() ;-------- 4 actor player = Game.GetPlayer() StorageUtil.StringlistClear(None, "HAC_Spells") ; *** clear *** StorageUtil.StringListCopy(None, "HAC_Spells", StorageUtil.StringListToArray(None, "HAC_RaceSpells")) ; add race specific spells int i = player.GetSpellCount() While (i) i = i - 1 spell akSpell = player.GetNthSpell(i) ; GetNthSpell(0) is the last added spell If akSpell.GetNthEffectMagicEffect(0).GetCastingType() ; Ensure spell is castable Update_HAC_Spells(akSpell) ; Update HAC_Spells and MAP endIf endWhile endFunction Function Update_HAC_Spells(Spell akSpell) ; Helper ;-------- 5 string s = akSpell.GetName() ; get the spell name as string StorageUtil.SetFormValue(None, s, akSpell as Form) ; Make sure that the spell name string is mapped to the correct formid StorageUtil.StringListAdd(None, "HAC_Spells", s, False) ; Add a new spell name to stringlist with allowdupes == FALSE endFunction Function InsertMenu_HAC_Spells() ;-------- 6 StorageUtil.StringListSort(None, "HAC_Spells") ; Sort the stringlist before insert the menu entry! StorageUtil.StringListInsert(None, "HAC_Spells", 0, "Back / Cancel / No Change") ; Insert to stringlist at index 0 an escape menu as way out endFunction The OnInit takes 20 seconds in a smaller load order, about 40 seconds in a very large one, the OnPlayerLoadGame depends on the number of player spells, but even with about two hundred spells it's under 6 seconds, which seems acceptable. Please let me know of any way I can improve it. -IA710 Link to comment Share on other sites More sharing options...
Recommended Posts