Pananacakes Posted July 6, 2016 Share Posted July 6, 2016 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 More sharing options...
cdcooley Posted July 7, 2016 Share Posted July 7, 2016 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.Install the SkyUI SDK (linked from https://github.com/schlangster/skyui/wiki) so you have the required scripts. Create a new quest for your MCM. Add a reference alias and fill it with the specific reference PlayerRef (which can be found in any cell). Attach the SKI_PlayerLoadGameAlias script to the new alias. Add a new script to the quest itself that extends SKI_ConfigBase. 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 More sharing options...
Pananacakes Posted July 7, 2016 Author Share Posted July 7, 2016 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 More sharing options...
Surilindur Posted July 7, 2016 Share Posted July 7, 2016 (edited) <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 July 7, 2016 by Contrathetix Link to comment Share on other sites More sharing options...
lofgren Posted July 7, 2016 Share Posted July 7, 2016 The old method and the state method both have advantages so if you're going to be making a lot of MCMs it's worth knowing both. There are somethings that each method can't do. Link to comment Share on other sites More sharing options...
Pananacakes Posted July 7, 2016 Author Share Posted July 7, 2016 Could mention what each one is good and not good for, Lofgren? Link to comment Share on other sites More sharing options...
lofgren Posted July 7, 2016 Share Posted July 7, 2016 (edited) 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 July 7, 2016 by lofgren Link to comment Share on other sites More sharing options...
cdcooley Posted July 8, 2016 Share Posted July 8, 2016 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 More sharing options...
Recommended Posts