Jump to content

[LE] MCM States and SetOptionFlagsST


Recommended Posts

I'm working on the MCM for my mod and I can't seem to fix one final issue. Originally I was using the "old" way of making the MCM and things worked fine, but I've switched to using States as this adds some things I like (more dynamic), seems to cut down on code, and overall is easier to follow (now that I've gotten used to it).

Basically I want to have one "master" toggle. When the master toggle is selected then the other options can be set. But when the master toggle is unselected I want the other options grayed out. I can get this to work via SetOptionFlagsST() when you stay in the same MCM page. But these flags are getting reset when I switch between pages. The selected options don't change, only the flags (grayed out or not). This isn't a huge issue, but it sure would be nice to get it fixed. Since my menu is pretty big, I made a very much condensed and generic version of my script. If I can figure out this script, I can apply the changes to mine. Any help would be appreciated!

Script:

 

 

 

 

Scriptname MIOS_MCM_quest_script extends SKI_ConfigBase

;==========
; Global Variables |
;==========

GlobalVariable Property MIOS_GV_A Auto						
GlobalVariable Property MIOS_GV_B Auto		

;=========
; Toggle States |
;=========
		
Bool BoolA_toggle = true						
Bool BoolB_toggle = true  

;=========
; OnConfigInit |
;=========

Event OnConfigInit()
	Pages = new string[2]
	Pages[0] = "Dummy Page"
	Pages[1] = "Options"
EndEvent

;=========
; OnPageReset |
;=========

Event OnPageReset(string page)

;==================
; MIOS MCM WELCOME PAGE |
;==================

	If (Page == "")
    		LoadCustomContent("My File Directory")
	Else
		UnloadCustomContent()
	EndIf

;=============
; DUMMY PAGE |
;=============
			
	If (Page == "Dummy Page")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
	    	AddHeaderOption("Dummy Page")	

;===========
; OPTIONS |
;===========

	ElseIf (Page == "Options")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
	    	AddHeaderOption("Options")

		AddToggleOptionST("BoolAToggle", "A?", BoolA_toggle)
		AddToggleOptionST("BoolBToggle", "B?", BoolB_toggle)
	EndIf
EndEvent

;======
; STATES |
;======		
		
State BoolAToggle
	Event OnHighlightST()
		SetInfoText("A?")
	EndEvent
	Event OnDefaultST()
		BoolA_toggle = true
		OnSelectST()
	EndEvent
	Event OnSelectST()
		BoolA_toggle = !BoolA_toggle	
		SetToggleOptionValueST(BoolA_toggle)					
		If BoolA_toggle == 0
			MIOS_GV_A.SetValue(0)
			SetOptionFlagsST(OPTION_FLAG_DISABLED, false, "BoolBToggle")
			ShowMessage("Bool A set to false", false, "OK")
		Else
			MIOS_GV_A.SetValue(1)
			SetOptionFlagsST(OPTION_FLAG_NONE, false, "BoolBToggle")
			ShowMessage("Bool A set to true", false, "OK")
		EndIf
	EndEvent
EndState	

State BoolBToggle
	Event OnHighlightST()
		SetInfoText("B?")
	EndEvent
	Event OnDefaultST()
		BoolB_toggle = true
		OnSelectST()
	EndEvent
	Event OnSelectST()
		BoolB_toggle = !BoolB_toggle		
		SetToggleOptionValueST(BoolB_toggle)					
		If BoolB_toggle == 0
			MIOS_GV_B.SetValue(0)
			ShowMessage("Bool B set to false.", false, "OK")
		Else
			MIOS_GV_B.SetValue(1)
			ShowMessage("Bool B set to true.", false, "OK")
		EndIf
	EndEvent
EndState 

 

 

 

Link to comment
Share on other sites

What exactly is the Boolean Proposition here? What is it that is True or False in most base form?

 

Examples

  • Is Quest Running
  • Does player have the item
  • What the global
  • what the Stage
  • Is the Bool true or false

Why use two, doesn't one work you? (A bool private variable & a Global) I need to understand more of what your trying to achieve, but below in A is a simple Toggle base base on what I saw in your code.

Scriptname MIOS_MCM_quest_script extends SKI_ConfigBase

;==========
; Global Variables |
;==========

GlobalVariable Property MIOS_GV_A Auto	;according to your code, default is false				
GlobalVariable Property MIOS_GV_B Auto		

;=========
; Toggle States |
;=========
		
;Bool BoolA_toggle = true	Why!!!!!!!	you don't need it.				
Bool BoolB_toggle = true  

;=========
; OnConfigInit |
;=========

Event OnConfigInit()
	Pages = new string[2]
	Pages[0] = "Dummy Page"
	Pages[1] = "Options"
EndEvent

;=========
; OnPageReset |
;=========

Event OnPageReset(string page)

;==================
; MIOS MCM WELCOME PAGE |
;==================

	If (Page == "")
    		LoadCustomContent("My File Directory")
	Else
		UnloadCustomContent()
	EndIf

;=============
; DUMMY PAGE |
;=============
			
	If (Page == "Dummy Page")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
	    AddHeaderOption("Dummy Page")	

;===========
; OPTIONS |
;===========

	ElseIf (Page == "Options")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
	    AddHeaderOption("Options")

		AddToggleOptionST("BoolAToggle", "A?", MIOS_GV_A.GetValue() as Bool) ; Real Game Value, less buggy, way more professional
		AddToggleOptionST("BoolBToggle", "B?", BoolB_toggle)
	EndIf
EndEvent

;======
; STATES |
;======		
		
State BoolAToggle
	
	Event OnSelectST()
		Bool BoolA_toggle = MIOS_GV_A.GetValue() 
		BoolA_toggle = !BoolA_toggle
		SetToggleOptionValueST(BoolA_toggle)
		ShowMessage("Switching to " + BoolA_toggle, false, "OK")
		MIOS_GV_A.SetValue(BoolA_toggle as float)
	EndEvent
	Event OnDefaultST()
		Bool BoolA_toggle = MIOS_GV_A.GetValue()
		If BoolA_toggle
			OnSelectST()
		EndIf 
	EndEvent
	Event OnHighlightST()
		SetInfoText("A?")
	EndEvent
;Keep Variables in the event or function where possible Okay
EndState	

State BoolBToggle
	Event OnHighlightST()
		SetInfoText("B?")
	EndEvent
	Event OnDefaultST()
		BoolB_toggle = true
		OnSelectST()
	EndEvent
	Event OnSelectST()
		BoolB_toggle = !BoolB_toggle		
		SetToggleOptionValueST(BoolB_toggle)					
		If BoolB_toggle == 0
			MIOS_GV_B.SetValue(0)
			ShowMessage("Bool B set to false.", false, "OK")
		Else
			MIOS_GV_B.SetValue(1)
			ShowMessage("Bool B set to true.", false, "OK")
		EndIf
	EndEvent
EndState 

I hope you can see it. A is mine, B is yours, Example only, not tested. Best of luck with your Scripting, English isn't my 1st language, so my code does the main talking for me.

 

If you have any questions? I do my best to answer them.

Link to comment
Share on other sites

Maybe I oversimplified my code a bit too much (and didn't provide enough accompanying information).

 

Basically I want the first Toggle to control whether certain items appear in the game (e.g. whether humans drop human hearts). This is achieved by setting a GV (in the above instance MIOS_GV_A), which controls whether the action takes place (via a condition which checks for the global variable).

 

Subsequent Toggles will control the modulation of those items (e.g. rate at which hearts drop, whether they are automatically added to loot or have to be harvested, etc). In my example above I only added one "modulation" (Toggle B) for the sake of simplicity, but I will need roughly 5-6 Toggles to achieve what I want (each Toggle exerting its effects via global variables). Changing these Toggles doesn't make sense if the first Toggle is set to 0/false (i.e. why change if hearts need to be actively harvested if they won't appear?). Thus I'd prefer to have these options grayed out if the first Toggle is set to 0/false.

 

Hopefully this clarifies what I'm trying to do.

 

Btw, I really appreciate the help. Especially with the idea to replace the bools with (GV as bool) in AddToggleOptionST(). Great suggestion, makes perfect sense.

Edited by candlepin
Link to comment
Share on other sites

You maybe need a manual Int property to control the Enable & Disable of the States, depending on the primary Global.

 

This mine for a PapyrusUtil json file MCM back up, It fades(disabled loading if there no BackUp, & Disables it also when a certain quest is running{making a backup})

 

It will be out of context, I hope you will see what I am trying to say

Int nFLAG_QUEST_RUNNING_DISABLED  =  _FDQ_QUST_D05X.IsRunning() As Int
AddHeaderOption("MCM Data Utility")
		AddTextOptionST("TEXT_SAVE_JSON_BAK_STATE", "Export Data","Click Me", nFLAG_QUEST_RUNNING_DISABLED)
		Int nFLAG_DATA_EXISTS_NONE = BakDataExists_NONE() As Int
		AddTextOptionST("TEXT_LOAD_JSON_BAK_STATE", "Import Data", "Click Me", (nFLAG_DATA_EXISTS_NONE || nFLAG_QUEST_RUNNING_DISABLED) As Int)
		AddTextOptionST("TEXT_CLEAR_JSON_BAK_STATE", "Clear Data", "Click Me", (nFLAG_DATA_EXISTS_NONE || nFLAG_QUEST_RUNNING_DISABLED) As Int)

The entire code is in the

Event OnPageReset(String a_page)

with no Private Variables, just variables contain in the event. So you need to do something with the

int property		OPTION_FLAG_NONE		= 0x00 autoReadonly
int property		OPTION_FLAG_DISABLED	= 0x01 autoReadonly
int property		OPTION_FLAG_HIDDEN		= 0x02 autoReadonly			; @since 3
int property		OPTION_FLAG_WITH_UNMAP	= 0x04 autoReadonly			; @since 3

to achieve what you want. I understood this, but where was the code? So I worked with I saw. Baby steps.

 

Post the entire Toggle Code that need to be Disable & Enable for a opinion on whats going wrong.

Link to comment
Share on other sites

You should notice I "Cast" alot to simplify want I am trying to achieve. Bools into Floats or Ints & vice visa. Also I Cast into Ints into Ints, to get some things to work as I intend, so that they don't add up to Unmap, but just Disable & Enable.

 

Hope you don't find this confusing?

Link to comment
Share on other sites

Sorry, you lost me with your code.

 

(nFLAG_DATA_EXISTS_NONE || nFLAG_QUEST_RUNNING_DISABLED) As Int

The way I read this, this will return a value of 0 if both these ints are 0 and a value of 1 if either of these conditions is 1. But the required parameter here is a flag. I don't get how an integer = a flag. Seems I'm missing something here/misunderstanding something. DO the flags correspond to numbers? If so, that would make my life so much easier....

 

int property OPTION_FLAG_NONE = 0x00 autoReadonly
int property OPTION_FLAG_DISABLED = 0x01 autoReadonly
int property OPTION_FLAG_HIDDEN = 0x02 autoReadonly ; @since 3
int property OPTION_FLAG_WITH_UNMAP = 0x04 autoReadonly

You really lost me here.

 

 

For helping with my code, let me expand upon my earlier example:

 

 

 

ElseIf (Page == "Options")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
	    AddHeaderOption("Options")

		AddToggleOptionST("BoolAToggle", "A?", MIOS_GV_A.GetValue() as Bool)
		AddToggleOptionST("BoolBToggle", "B?", BoolB_toggle, XXXXXXXXXXX) 
                AddToggleOptionST("BoolCToggle", "C?", BoolC_toggle, XXXXXXXXXXX)
                AddToggleOptionST("BoolDToggle", "D?", BoolD_toggle, XXXXXXXXXXX)
	EndIf
EndEvent

 

 

MIOS_GV_A can be either 0 or 1.
If it's zero, I'd like Toggles B, C, and D set to disabled, i.e. XXXXXXXXXXX to be set to OPTION_FLAG_DISABLED if MIOS_GV_A == 0.
But if MIOS_GV_A == 1, I'd like XXXXXXXXXXX to be set to OPTION_FLAG_NONE. I don't understand how to make XXXXXXXXXXX conditional with text like that. I have a condition within the OnSelectST() of Toggle A that disables and enables the Toggles for B, C, and D when Toggle A is set to 0 or 1, respectively. The problem, however, is that this seems to be forgotten when switching between MCM pages. As you pointed out, I think this is due to me not controlling the flags of these Toggles during the OnPageReset Event.
Btw, even though I don't quite get what you're saying (yet!), I really appreciate the help!
Link to comment
Share on other sites

Ok lets say on the Global, 0 = false & 1 = true. So it works as a Bool. Very Important!! That doesn't work with SkyUI Options of OPTION_FLAG_NONE = 0 & OPTION_FLAG_DISABLED = 1 So lets create a manual read only property to get what we want.

Int Property FLAG_DISABLED_ALL

	Int Function Get()
		Bool bIsEnable = MIOS_GV_A.GetValue()
		If bIsEnable
			return OPTION_FLAG_NONE 
		EndIf
		return OPTION_FLAG_DISABLED
	EndFunction
EndProperty

Now we use this Int property to Enable or Disable All certain Options at once, depending of the Primary Global of MIOS_GV_A as Boolean

ElseIf (Page == "Options")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
	        AddHeaderOption("Options")

		AddToggleOptionST("BoolAToggle", "A?", MIOS_GV_A.GetValue() as Bool)
		AddToggleOptionST("BoolBToggle", "B?", BoolB_toggle, FLAG_DISABLED_ALL) 
                AddToggleOptionST("BoolCToggle", "C?", BoolC_toggle, FLAG_DISABLED_ALL)
                AddToggleOptionST("BoolDToggle", "D?", BoolD_toggle, FLAG_DISABLED_ALL)
	EndIf
EndEvent

Tweak it has you find necessary, but that it.

 

OH navigate to Skyrim\Data\SCRIPTS\Source find:

SKI_ConfigBase.psc

It's the source code for extending the MCM, it's were I got those int values from, read it, then go to SKI_SDK website for clarification, or read, or decompile MCM from other Modder's to learn from them.

 

Once again let me apologize for my English, but that should solve your Problem, with my baby step. And you should have a better understanding of is happening, instead of giving this code first time round.

 

Good Luck with everything

 

Sincerely

 

Cloud PeterMartyr.

Link to comment
Share on other sites

I took too long creating this response (and got distracted for a while while writing it) so PeterMartyr beat me to the real problem in your script. You need to use the 4th parameter for AddToggleOptionST if you're trying to use toggle A as the master switch for all other options.

Putting all of the things above together your script can look something like this:

Scriptname MIOS_MCM_quest_script extends SKI_ConfigBase

;==========
; Global Variables |
;==========

GlobalVariable Property MIOS_GV_A Auto  ; Master Toggle blocks all others when not enabled
GlobalVariable Property MIOS_GV_B Auto	; example secondary value	

;=========
; OnConfigInit |
;=========

Event OnConfigInit()
	Pages = new string[2]
	Pages[0] = "Dummy Page"
	Pages[1] = "Options"
EndEvent

;=========
; OnPageReset |
;=========

Event OnPageReset(string page)

;==================
; MIOS MCM WELCOME PAGE |
;==================

	If (Page == "")
		LoadCustomContent("My File Directory")
	Else
		UnloadCustomContent()
	EndIf

;=============
; DUMMY PAGE |
;=============
			
	If (Page == "Dummy Page")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
		AddHeaderOption("Dummy Page")	

;===========
; OPTIONS |
;===========

	ElseIf (Page == "Options")
		SetCursorFillMode(TOP_TO_BOTTOM)
		SetCursorPosition(0)
		AddHeaderOption("Options")

		int option_flag = OPTION_FLAG_DISABLED	; assume all but master toggle should be disabled by default
		if MIOS_GV_A.GetValue() as bool    ; if master toggle is active then allow setting other values normally
			option_flag = OPTION_FLAG_NONE
		endif

		AddToggleOptionST("BoolAToggle", "A?", MIOS_GV_A.GetValue() as Bool)
		AddToggleOptionST("BoolBToggle", "B?", MIOS_GV_B.GetValue() as Bool, option_flag)
		; AddToggleOptionST("BoolCToggle", "C?", MIOS_GV_C.GetValue() as Bool, option_flag)
		; AddToggleOptionST("BoolDToggle", "D?", MIOS_GV_D.GetValue() as Bool, option_flag)

	EndIf
EndEvent

;======
; STATES |
;======		
		
State BoolAToggle
	Event OnHighlightST()
		SetInfoText("A?")
	EndEvent
	Event OnDefaultST()
		MIOS_GV_A.SetValue(1)  ; real default is false
		OnSelectST()
	EndEvent
	Event OnSelectST()
		if MIOS_GV_A.GetValue() as bool
			MIOS_GV_A.SetValue(0)
		Else
			MIOS_GV_A.SetValue(1)
		EndIf
		ForcePageReset()  ; to update the option_flag value for all of the secondary options
	EndEvent
EndState	

State BoolBToggle
	Event OnHighlightST()
		SetInfoText("B?")
	EndEvent
	Event OnDefaultST()
		MIOS_GV_B.SetValue(1)   ; real default is false
		OnSelectST()
	EndEvent
	Event OnSelectST()
		If MIOS_GV_B.GetValue() as bool
			MIOS_GV_B.SetValue(0)
		Else
			MIOS_GV_B.SetValue(1)
		EndIf
		SetToggleOptionValueST(MIOS_GV_B.GetValue() as bool)					
	EndEvent
EndState

I didn't use a property for my option_flag variable because that would recalculate the value every time you use it.

Edited by cdcooley
Link to comment
Share on other sites

  • Recently Browsing   0 members

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