Jump to content

Populating MCM AddMenuOptionST with player spells and lesser powers


Recommended Posts

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

  • Replies 54
  • Created
  • Last Reply

Top Posters In This Topic

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

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

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

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

  • Recently Browsing   0 members

    • No registered users viewing this page.

×
×
  • Create New...