Jump to content

[LE] Splitting MCM menu into multiple smaller scripts


Anubis22

Recommended Posts

Hey everyone,

 

I am currently working on a mod similar to SkyTweak. It is a lot more lightweight with a stronger focus on (combat-) balance and is designed to work on top of any load order, virtually conflict free. The mod is in it's last stages of refinement, but now I ran into a problem with the MCM menu script file. I am using the "State Option" method for addressing my ui elements, but I surpassed 128 states in the script and compiling will yield the following error:

"SCRIPTS: error: Class SB_MCM_Script overflowed the named state count field(s) while linking. The class is marked as invalid. A programmer must adjust the bit field sizes"

 

The MCM script got way too big for my taste anyway. I would love to split it up into several smaller scripts (for example one script for each MCM page).

Is this possible and how could I do it?

If not is there any solution except reverting back to the older non-State MCM format?

Link to comment
Share on other sites

There are a lot of parameters involved in balancing the game, even if you do not go down to the lowest levels. For a quick reference just take a look at SkyTweak, which probably exceeds 200 easily.

 

An example from my mod for Destruction Magic:

- Toggle whether to adjust Destruction

- Damage Multiplier

- Damage Level Scaling

- Cost Multiplier

- Duration Multiplier

- Experience Multiplier

 

And you could add Level Scaling for Cost and Duration too. You have the same for the other magic schools and skills. It adds up, real quick.
When using MCM with State Options every slider, checkbox and so on in your UI has a corresponding state in the script, hence why there are so many.

Link to comment
Share on other sites

A state for every single option strikes me as major overkill. Have you considered, say, using one per page? You could, say, have one page for Destruction, and all your relevant code and variables set within a DestructionPage state. That keeps your OnWhatever events from turning into truly ridiculous spaghetti, but should keep your state count sane.

Link to comment
Share on other sites

If I understand correctly, MCM allows 128 mod configuration entries (mods), 128 pages per mod, 128 option entries per page.

 

Thus instead of having only one page with 128 option entries, you can break that down into multiple pages. The OnPageReset event (explained in the MCM documentation and included in the template script) is where you can determine which options are displayed on which page. Your states can remain unchanged, just change which page calls those options to display.

 

A small example of multiple pages under one mod configuration entry

 

 

Event OnPageReset(string page)
    If  page == ""
        LoadCustomContent("")
    Else
        UnLoadCustomContent()
    EndIf
    If  page == Pages[0]
        SetCursorFillMode(TOP_TO_BOTTOM)
;        AddHeaderOption("Global Options")
        AddKeyMapOptionST("KeyMap_One", "$Modify Activation Key", KeyCodeOne)
        AddTextOptionST("KeyMap_One_Behavior","$Behavior",KMOBehave[KMOBehaveidx])
        AddToggleOptionST("ManualSaveState","$Manual Save", ManualSave)

        SetCursorPosition(1)
        If FissActive == true
            FISSInterface fiss = FISSFactory.getFISS()
            If fiss
                AddToggleOptionST("SavePreset","$SavePreset",PresetSave,OPTION_FLAG_NONE)
                AddToggleOptionST("LoadPreset","$LoadPreset",PresetLoad,OPTION_FLAG_NONE)
            Else
                AddToggleOptionST("SavePreset","$SavePreset",PresetSave,OPTION_FLAG_DISABLED)
                AddToggleOptionST("LoadPreset","$LoadPreset",PresetLoad,OPTION_FLAG_DISABLED)
            EndIf
        Else
            AddToggleOptionST("SavePreset","$SavePreset",PresetSave,OPTION_FLAG_DISABLED)
            AddToggleOptionST("LoadPreset","$LoadPreset",PresetLoad,OPTION_FLAG_DISABLED)
        EndIf
    EndIf
;more pages removed for brevity
EndEvent 

 

 

 

 

@foamyesque

The state setup for MCM is designed for one state per option with different option events dedicated to the state setup. Thus it does not get to be as 'spaghetti' like as you'd think. Its more like a pie or a cake. Each state is a piece with the OnPageReset event being the icing tying it all together. Here is an example:

 

A single option to make a 'carried' container weighted or weightless

State   Weightless0
    Event OnSelectST()
        Int index = 0
        WeightlesActive[index] = !WeightlesActive[index]
        SetToggleOptionValueST(WeightlesActive[index])
    EndEvent
    Event OnDefaultST()
        Int index = 0
        WeightlesActive[index] = false
        SetToggleOptionValueST(WeightlesActive[index])
    EndEvent
    Event OnHighlightST()
        Int index = 0
        If ComponentChoice[index] != 0
            SetInfoText("$WeightlessInfo")
        EndIf
    EndEvent
EndState
 

and that is just one of 5 options for that one container.

 

See earlier above for an OnPageReset example.

 

 

Link to comment
Share on other sites

The spaghetti problem was in reference to a completely state-free implementation, where each event would need to do a comparison against every single possible option it could apply to to figure out which one it's processing. That gets really ugly quite quickly, hence the state-based system in MCM 2 in the first place.

 

However, if a. there's more than 128 options that need states and b. Papyrus only allows 128 states total -- and the compiler error would suggest that -- then going back to the optionID layout might be the choice here...

Link to comment
Share on other sites

I never done this, but papyrus is always extending something, & to create a simple test won't take long, but why don't you just extends you main MCM script.

ScriptName MCMScriptMain Extends SKI_ConfigBase

MCMPageTwo Property P2 Auto

Event OnPageReset(string a_page)
	If a_page == Pages[0]
		Self.AddTextOptionST("StateName", "string a_text", "string a_value")
	ElseIf a_page == Pages[1]
		P2.PageTwo()	
	EndIf	
EndEvent

State StateName
	Event OnSelectST()
		Self.SetTextOptionValueST("Working")
	EndEvent
EndState
ScriptName MCMPageTwo Extends MCMScriptMain

Function PageTwo()

	self.AddTextOptionST("PageTwoState", "string a_text", "string a_value")
EndFunction

State PageTwoState
	
	Event OnSelectST()
		Self.SetTextOptionValueST("Working")
	EndEvent
EndState

It compiled fine, but I obviously didn't create a test mod to see it in action, it should be possible to extend it. Who knows, what have got to lose, run some tests, if you don't get how to extends your scripts, look it up on the wiki.

 

I

 

 

You can beat the 128 States with State "" on dynamic states

Example of me use State "" in MCM, it look like old format doesn't it? Without integers, but using States

Event OnInputOpenST()
Int a_index
String sResult = GetState()
Int nClone = FDQMain.nCloneTypeID
While(a_index < nClone)
  If(sResult == "INPUT_POSITION_X_STATE" + a_index)
   Float fTemp = FDQMain.fSetPositionX[a_index]
   SetInputDialogStartText(fTemp As Int)
  ElseIf(sResult == "INPUT_POSITION_Y_STATE" + a_index)
   Float fTemp = FDQMain.fSetPositionY[a_index]
   SetInputDialogStartText(fTemp As Int)
  ElseIf(sResult == "INPUT_ROTATION_Z_STATE" + a_index)
   Float fTemp = FDQMain.fSetAngleZ[a_index]
   SetInputDialogStartText(fTemp As Int)
  EndIf
  a_index +=1
EndWhile
EndEvent

another state "" where one Event serves multiple States with a delimiter I placed in the definition of States Names

Int nIndex = 61
  Int nCount
  While(nIndex > 30)
   nIndex -= 1
   Int kSlotMask = Armor.GetMaskForSlot(nIndex)
   Form EquippedForm = PoupaREF.GetWornForm(kSlotMask)
   If(EquippedForm)
    self.AddTextOptionST("EquipForm_State" + "*" + nCount, EquippedForm.GetName(), (EquippedForm as Armor).GetArmorRating())
    nCount += 1
   EndIf
  EndWhile

**********************************************************************************************
Event OnHighlightST()
string[] sResult = StringUtil.Split(self.GetState(), "*")
If(sResult[0] == "EquipForm_State")
  self.SetInfoText("Base CK Armor Rating for Item")
EndIf
End

So yeah 128 is the limited, but doesn't mean you can't trick the compiler to get what you want with a minimum of Physical States

 

 

 

 

So really it depends what you require from your MCM? I never had a the need to exceed 128, but I have needed to create Dynamic States with Loops.

 

English is not 1st, but unlike others, I don't feel sorry about it. So no apology, here. :cool:

Link to comment
Share on other sites

Whether or not papyrus itself will not allow more than 128 states (never heard of such a limit myself), you can always create a second MCM quest in your mod. It would create another mod configuration entry (which would only be an issue if someone wants to use more than 128 mods with MCMs).

Link to comment
Share on other sites

Whether or not papyrus itself will not allow more than 128 states (never heard of such a limit myself), you can always create a second MCM quest in your mod. It would create another mod configuration entry (which would only be an issue if someone wants to use more than 128 mods with MCMs).

 

I haven't either. I'm actually going to be testing that later tonight just to see. But if there isn't such a limit, it makes me wonder what that compiler error would be caused by...

Link to comment
Share on other sites

I just checked on this. I created a script with 130+ simple states all with empty OnBeginState events. It compiled fine through SublimeText. But when I went to load the script in the CK it presented me with the error message that the OP indicated. I could not access the script in the CK until I reduced the number of states to 127 typed states and the always present empty state. Keep in mind this is not a compiler error. The compiler has no issues with the number of states. The Creation Kit itself has an issue with the number of states.

 

The real question:

Can a script with 128+ states that has been compiled outside of the CK function properly without issue within the game?

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

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