Splitting your MCM script

Update: save yourself quite a lot of pain and use MCM Helper instead.


MCM scripts are one of the worst parts of creating a mod, since they easily get really huge and hard to manage and maintain.

I found a way to split your MCM code, so you can divide all your thousands of lines among many little and easier to manage scripts. As many Papyrus programming things, it's mostly a hack and has its own drawbacks, but it gets the job done.

Overview

As you have read from the official MCM SDK wiki, you should create a script that extends SKI_ConfigBase and add it to a quest before you can see your MCM.
My idea for splitting MCM code is to leverage script inheritance so we can use code defined in other scripts than the one that gets added to a quest.

By the way, you need to use the MCM state options for this to work.

Here's a graphical overview:

MCM script spltting overview

Split code 1 is the first script written by you. It must always inherit (extend) from SKI_ConfigBase. Whatever you code here will be available to all scripts below.

Whenever you want to create a new script, you just need to extend from whatever script you have above the "quest script" (the one that gets added to a quest in the CK).

Example

I'll create some simple hierarchy to show you how to do this.



Copy and paste this code to get started right now:

Scriptname Split1 extends SKI_ConfigBase Hidden

Function Split1_Show()
    AddHeaderOption("It works")
    AddTextOptionST("split1_Txt", "Test", "text")
EndFunction

State split1_Txt
    Event OnHighlightST()
        SetInfoText("Proof this is working")
    EndEvent
EndState


Scriptname Split2 extends Split1 Hidden

Function Split2_Show()
    AddTextOptionST("split2_Txt", "Split 2", "Meh")
EndFunction

State split2_Txt
    Event OnHighlightST()
        SetInfoText("Split 2 is working too")
    EndEvent
EndState


Scriptname QuestScript extends Split2

event OnPageReset(string aPage)
    ShowMenu()
endEvent

Function ShowMenu()
    SetCursorFillMode(TOP_TO_BOTTOM)
    Split1_Show()
    Split2_Show()
EndFunction

This example is, of course, a bare bones sample of how you can do this.
Don't be fooled by its apparent simplicity. You can create fully fledged menus by using this technique.
For example, every single header (and options under it) in this picture comes from an individual script with around 150 lines each:
Menus, sliders, etc... all of them work as the user would've expected.
And this is how it looks like from code.

General workflow

The general workflow for each split script is:

Caveats

Wrap up

Be happy. Now you can split your thousands of lines between many smaller and easier to maintain scripts.

It's a bit of a headache to keep track of the script hierarchy, but it's way worse to manage a 1500+ lines script, to be honest.