Jump to content

Looking for someone who can make a small MCM


Recommended Posts

I recently published a mod and I'd like it to have an MCM. I've tried but...honestly I'm dazed by the attempt. I have no experience with GUI programming and learning the MCM code looks to me harder than all the rest of Papyrus.

 

I think it's a lot to ask but I'm looking for someone to make my MCM for me. It needs 4 toggles and 5 sliders and I have a plan for it.

 

Any takers? I don't know what I might offer in exchange but I'm open to ideas.

 

Link to comment
Share on other sites

Basic MCM scripts are actually pretty easy if you use the newer state system.

 

Since the mod itself already exists without an MCM I assume the values behind those toggles and sliders either live in script properties or global variables. If the values are really only used by a single script it's usually best to just make the value a property in that script and let the MCM modify it as needed. If the value gets used by multiple scripts then global variables are usually the better choice. It's almost never a good idea to store the actual configuration values in the MCM script itself (despite the early examples that you might find).

 

Here are the steps for making a simple, one-page MCM.

  1. Install the SkyUI SDK (linked from https://github.com/schlangster/skyui/wiki) so you have the required scripts.
  2. Create a new quest for your MCM.
  3. Add a reference alias and fill it with the specific reference PlayerRef (which can be found in any cell).
  4. Attach the SKI_PlayerLoadGameAlias script to the new alias.
  5. Add a new script to the quest itself that extends SKI_ConfigBase.
  6. You'll need an OnPageReset event which defines how the options appear on the MCM page and a state and a few events for each of the options. Here's a minimal example with all of the pieces you would need. I've given the code for how to use both toggles and sliders stored in either global variables or in a quest script. Technically you can pull values and set values from anywhere. In the Inigo MCM page I use InigoRef.GetActorValue("AttackDamageMult")*100.0 to get a useful value and then set it back using InigoRef.ForceActorValue("AttackDamageMult", value/100.0) to modify his attack damage multiplier.
ScriptName SimpleMCMScript extends SKI_ConfigBase

; Assume one toggle and one slider are stored in global variables.
GlobalVariable property Toggle1GV auto
GlobalVariable property Slider1GV auto

; Assume another pair are stored as properties in a quest script.
; (assumes a bool property called Toggle2 and a float property called Slider2)
MainModQuestScript property MainModQuest auto

Event OnPageReset(string a_page)
	SetCursorFillMode(TOP_TO_BOTTOM)

	SetCursorPosition(0) ; position so toggles are on the left side
	AddHeaderOption("Some Example Toggle Options") ; headers can be helpful but are not needed
	AddToggleOptionST("TOGGLE1", "First toggle", Toggle1GV.GetValue() as bool)
        AddToggleOptionST("TOGGLE2", "Second toggle", MainModQuest.Toggle2)

	SetCursorPosition(1) ; position so sliders are on the right
	AddHeaderOption("Some Example Slider Options")
	AddSliderOptionST("SLIDER1", "First Slider", Slider1GV.GetValue(), "{0}") ; value displays like an int
	AddSliderOptionST("SLIDER2", "Second Slider", MainModQuest.Slider2, "{0}%") ; this one displays like a percent
EndEvent


State TOGGLE1
; This is for the toggle stored in a global variable

	Event OnHiglightST()
		SetInfoText("This is the text that shows at the bottom of the screen when the item is highlighted.")
	EndEvent

	Event OnDefaultST()
		SetToggleOptionST(true) ; assumes the default for toggle1 is true
		Toggle1GV.SetValue(1.0) ; globals can really only hold float values
	EndEvent

	Event OnSelectST()
		if Toggle1GV.GetValue() as bool ; currently true
			SetToggleOptionST(false) ; change to false
			Toggle1GV.SetValue(0.0)
		else ; currently false
			SetToggleOptionST(true) ; change to true
			Toggle1GV.SetValue(1.0)
		endif
	EndEvent

EndState


State TOGGLE2
; This is for the toggle stored in a bool property in a script.

	Event OnHiglightST()
		SetInfoText("This is the text that shows at the bottom of the screen when the item is highlighted.")
	EndEvent

	Event OnDefaultST()
		SetToggleOptionST(true) ; assumes the default for toggle2 is true
		MainModQuest.Toggle2 = true
	EndEvent

	Event OnSelectST()
		MainModQuest.Toggle2 = !MainModQuest.Toggle2 ; new value is opposite of old one
		SetToggleOptionST(MainModQuest.Toggle2)
	EndEvent

EndState


State SLIDER1

	Event OnHiglightST()
		SetInfoText("This is the text that shows at the bottom of the screen when the item is highlighted.")
	EndEvent

	Event OnSliderAcceptST(float value)
		SetSliderOptionValueST(value) ; updates display
		Slider1GV.SetValue(value) ; changes the actual value
	EndEvent

	Event OnSliderOpenST()
		SetSliderDialogStartValue(Slider1GV.GetValue())  ; initial slider position
		SetSliderDialogDefaultValue(100.0) ; default value (when player chooses that option)
		SetSliderDialogRange(10.0, 300.0) ; the minimum and maximum allowed
		SetSliderDialogInterval(5.0) ; smallest amount changed by sliding bar
                ; with the settings above the slider bar will accept values 10, 15, 20, 25, etc.
	EndEvent

EndEvent

State SLIDER2

	Event OnHiglightST()
		SetInfoText("This is the text that shows at the bottom of the screen when the item is highlighted.")
	EndEvent

	Event OnSliderAcceptST(float value)
		SetSliderOptionValueST(value) ; updates display
		MainModQuest.Slider2 = value ; changes the actual value
	EndEvent

	Event OnSliderOpenST()
		SetSliderDialogStartValue(MainModQuest.Slider2)  ; initial slider position
		SetSliderDialogDefaultValue(50.0) ; default value (when player chooses that option)
		SetSliderDialogRange(0.0, 100.0) ; the minimum and maximum allowed
		SetSliderDialogInterval(1.0) ; smallest amount changed by sliding bar
                ; this one is set up for percentages between 0 and 100.
	EndEvent

EndEvent

The script looks long (and yours will be even longer with 4 toggles and 5 sliders) but once you've got your first option of each type working you just need to copy it, edit the help text, state and variable names, and default values.

 

 

Give it a try and if you have problems or want more specific advice I'll try to help.

Link to comment
Share on other sites

Thanks cdcooley. I guess I spoke too soon because now I'm starting to figure it out. I forgot Don't Panic. I used a tutorial that mostly describes the old way and now I'll try to get my head around this states way you're showing. It looks do-able.

 

A question though: where are the GoToState statements?

Link to comment
Share on other sites

<snip>

 

Now THAT looks brilliant. Thank you, cdcooley. I used the old method for my own mods, with option IDs, because I did not read the state feature explanations. The old method of using option IDs is right up there in the quickstart quide, so I used that, and not the state ones. Maybe if they moved the state method to the quickstart guide, people might learn the right way from the get-go. Or maybe it was just me not reading enough. Anyway, thank you for the tip. :laugh:

 

Pananacakes, apparently SkyUI takes care of the state stuff, which seems to be the idea behind the whole new system. The states are defined in the option additions, like AddToggleOptionST("TOGGLE1", "Something", false) where the TOGGLE1 is the state used for that option item. The documentation is in the Github wiki cdcooley linked, it seems easy enough to potentially understand, I started with it myself (and apparently read the wrong section, and did it the old way, but still :blush: ): https://github.com/schlangster/skyui/wiki/MCM-State-Options

Edited by Contrathetix
Link to comment
Share on other sites

The old method is better if you have a lot of options that are very similar, for example a bunch of sliders that all have the same maximum and minimum and do basically the same thing with only minor differences.

 

The state method is better if you have a lot of options that are very different.

 

If you have only a few options, then you should use whichever method is more comfortable for you. Personally I always use the state method unless I have a good reason not to.

 

You can mix and match in the same script, depending on what works best for you. My Training Options mod uses the old method on the skill training and rewards pages, but the state method everywhere else. There are two groups of up to 20 sliders that all do basically the same thing. That was much easier to create and maintain with the old method than the state method.

Edited by lofgren
Link to comment
Share on other sites

There are some interesting optimization tricks you can play with the state method too. The trick is that state names are also strings that you can access using the GetState() function. My favorite is to use SKSE's translation system to provide the info text for every option with just a single function call. For example in my Storage Helpers mod I use this one (declared outside of any state).

Event OnHighlightST()
	{Text supplied in translation files, so can use a single event handler.}
	SetInfoText("$SHMCMIT_"+GetState())
EndEvent

My translation file then has lines like:

$SHMCMIT_MoveSoulGems	This controls which types of soul gems are moved with the Put Most feature.
$SHMCMIT_KeySlow	Modifier key used to make items move more slowly.\n(See General page for other uses.)
Link to comment
Share on other sites

  • Recently Browsing   0 members

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