the Sim Settlements forums!

Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Making a MCM mod, need help with scripts

HyperLordBender

Active Member
Moderator
Messages
114
So I am finally getting to making some MCM mods for other mods without MCM settings. For this I want to make debug functions, such as adding items with a button. But no matter what I do either it doesnt work, or the compiler just keeps spitting out errors. Most common error is "OnPlayerLoadGame is not a script object".

Here is my script:
Code:
Scriptname HorizonMCMSettings:Main extends Quest

; ---------------------------------------------
;   Properties
Group Main
    Actor Property PlayerRef Auto Const Mandatory
    {
        The Player. FormID: 00000014
    }
    GlobalVariable Property bEnabledDebug Auto
    {
        Handles debug functions
    }
    GlobalVariable Property ModVersion Auto
    {
        Current mod version
    }
    GlobalVariable Property iExpectedHorizonVersion Auto
    {
        What horizon verion the mod is made for
    }
    GlobalVariable Property HorizonVersionCurrent Auto
    {
        What version of horizon is currently loaded
    }
    Quest Property MQ101 Auto Const Mandatory
    {
        First main quest, "War Never Changes"
    }
    Quest Property MQ102 Auto Const Mandatory
    {
        Second main quest, "Out of Time"
    }
EndGroup
Group Items
    MiscObject Property Item_PurifierRegulator Auto
    {
        This is for the purifier module. FormID: 0x00002B52
    }
EndGroup
; ---------------------------------------------

; ---------------------------------------------
;   Variables

; ---------------------------------------------
;   Events

Event Actor.OnPlayerLoadGame(Actor player)
    Self.RegisterEvents()
    Self.ManagePurifierItem()
EndEvent

; ----------------------------------------
;   Functions

Function RegisterEvents()
    Self.RegisterForRemoteEvent(PlayerRef as ScriptObject, "OnPlayerLoadGame")
EndFunction

Function ManagePurifierItem()
    PlayerRef.AddItem(Item_PurifierRegulator as Form, 1, False)
    Debug.Notification("Purifier Module Added")
EndFunction

Event OnInit()
    Self.ManagePurifierItem()
EndEvent
 

Attachments

  • Main.psc
    1.7 KB · Views: 0
Last edited:
@HyperLordBender I'm not quite sure what your config.json looks like, but this should be closer to what you are trying to achieve.
Code:
Scriptname HorizonMCMSettings:Main extends Quest
{ this script should be attached to a quest flagged 'run on game start' }

; ---------------------------------------------
;   Properties
Group Main
    Actor Property PlayerRef Auto Const Mandatory
    {
        The Player. FormID: 00000014
    }
    GlobalVariable Property bEnabledDebug Auto
    {
        Handles debug functions
    }
    GlobalVariable Property ModVersion Auto
    {
        Current mod version
    }
    GlobalVariable Property iExpectedHorizonVersion Auto
    {
        What horizon verion the mod is made for
    }
    GlobalVariable Property HorizonVersionCurrent Auto
    {
        What version of horizon is currently loaded
    }
    Quest Property MQ101 Auto Const Mandatory
    {
        First main quest, "War Never Changes"
    }
    Quest Property MQ102 Auto Const Mandatory
    {
        Second main quest, "Out of Time"
    }
EndGroup

Group Items
    MiscObject Property Item_PurifierRegulator Auto
    {
        This is for the purifier module. FormID: 0x00002B52
    }
EndGroup
; ---------------------------------------------

; ---------------------------------------------
;   Variables

; ---------------------------------------------
;   Events

Event OnInit()
    ; OnInit is triggered when the quest starts. It should only be used to fill vars!
    ; Self.ManagePurifierItem()
EndEvent

Event OnQuestInit()
    ; OnQuestInit triggers after quest has started and alias are filled.
   
    ; register script for events
    Self.RegisterEvents()
EndEvent

Event Actor.OnPlayerLoadGame(Actor akSender)
    ; Self.RegisterEvents()
    ; Self.ManagePurifierItem()
    Self.HandlePlayerLoadGame()
EndEvent

; ----------------------------------------
;   Functions

Function RegisterEvents()
    ; Self.RegisterForRemoteEvent(PlayerRef as ScriptObject, "OnPlayerLoadGame")
    ; you do not need to cast PlayerRef as ScriptObject, you are registering for an event on Actor script so the first arg should be an Actor
    Self.RegisterForRemoteEvent(PlayerRef, "OnPlayerLoadGame")
EndFunction

Function HandlePlayerLoadGame()
    ; player has loaded the game, do stuff that needs to happen every load here
EndFunction

Function MCM_AddPurifierItem()
    ; this is the function your MCM button should call
    PlayerRef.AddItem(Item_PurifierRegulator as Form, 1, False)
    Debug.Notification("Purifier Module Added")
EndFunction

;/    MCM Button
{
    "text": "Spawn Purifier Regulator",
    "type": "button",
    "help": "Spawn Purifier Regulator in player inventory when you click this.",
    "action": {
        "type": "CallFunction",
        "form": "myMod.esp|myFormIDinHEX",    // myFormIDinHEX would be the FormID of this quest
        "scriptName": "HorizonMCMSettings:Main",
        "function": "MCM_AddPurifierItem",    // the function on your script this button should call
        "params": []    // params my function expects, specify with {b}, {i}, {f} and {s} for bool, int, float, string - example "{b}{value}" would pass the switcher value as a bool to the script function call
                        // you can pass the new value "{b}{value}" with the function call to update things in your script when the setting is changed.
    }
}
/;
It also seems you have some global variables defined that could be replaced with bool / int / float properties.

Also, you do not need to cast MiscObject to Form. The compiler will auto cast this for you. Item_PurifierRegulator as Form
 
@HyperLordBender I'm not quite sure what your config.json looks like, but this should be closer to what you are trying to achieve.
Code:
Scriptname HorizonMCMSettings:Main extends Quest
{ this script should be attached to a quest flagged 'run on game start' }

; ---------------------------------------------
;   Properties
Group Main
    Actor Property PlayerRef Auto Const Mandatory
    {
        The Player. FormID: 00000014
    }
    GlobalVariable Property bEnabledDebug Auto
    {
        Handles debug functions
    }
    GlobalVariable Property ModVersion Auto
    {
        Current mod version
    }
    GlobalVariable Property iExpectedHorizonVersion Auto
    {
        What horizon verion the mod is made for
    }
    GlobalVariable Property HorizonVersionCurrent Auto
    {
        What version of horizon is currently loaded
    }
    Quest Property MQ101 Auto Const Mandatory
    {
        First main quest, "War Never Changes"
    }
    Quest Property MQ102 Auto Const Mandatory
    {
        Second main quest, "Out of Time"
    }
EndGroup

Group Items
    MiscObject Property Item_PurifierRegulator Auto
    {
        This is for the purifier module. FormID: 0x00002B52
    }
EndGroup
; ---------------------------------------------

; ---------------------------------------------
;   Variables

; ---------------------------------------------
;   Events

Event OnInit()
    ; OnInit is triggered when the quest starts. It should only be used to fill vars!
    ; Self.ManagePurifierItem()
EndEvent

Event OnQuestInit()
    ; OnQuestInit triggers after quest has started and alias are filled.
 
    ; register script for events
    Self.RegisterEvents()
EndEvent

Event Actor.OnPlayerLoadGame(Actor akSender)
    ; Self.RegisterEvents()
    ; Self.ManagePurifierItem()
    Self.HandlePlayerLoadGame()
EndEvent

; ----------------------------------------
;   Functions

Function RegisterEvents()
    ; Self.RegisterForRemoteEvent(PlayerRef as ScriptObject, "OnPlayerLoadGame")
    ; you do not need to cast PlayerRef as ScriptObject, you are registering for an event on Actor script so the first arg should be an Actor
    Self.RegisterForRemoteEvent(PlayerRef, "OnPlayerLoadGame")
EndFunction

Function HandlePlayerLoadGame()
    ; player has loaded the game, do stuff that needs to happen every load here
EndFunction

Function MCM_AddPurifierItem()
    ; this is the function your MCM button should call
    PlayerRef.AddItem(Item_PurifierRegulator as Form, 1, False)
    Debug.Notification("Purifier Module Added")
EndFunction

;/    MCM Button
{
    "text": "Spawn Purifier Regulator",
    "type": "button",
    "help": "Spawn Purifier Regulator in player inventory when you click this.",
    "action": {
        "type": "CallFunction",
        "form": "myMod.esp|myFormIDinHEX",    // myFormIDinHEX would be the FormID of this quest
        "scriptName": "HorizonMCMSettings:Main",
        "function": "MCM_AddPurifierItem",    // the function on your script this button should call
        "params": []    // params my function expects, specify with {b}, {i}, {f} and {s} for bool, int, float, string - example "{b}{value}" would pass the switcher value as a bool to the script function call
                        // you can pass the new value "{b}{value}" with the function call to update things in your script when the setting is changed.
    }
}
/;
It also seems you have some global variables defined that could be replaced with bool / int / float properties.

Also, you do not need to cast MiscObject to Form. The compiler will auto cast this for you. Item_PurifierRegulator as Form
Thanks for the info. I got so annoyed at the dang thing that I rewrote it. I got it working with referring to the Item_PurifierRegulator as a MiscObject. Now I just need to make other things work properly, like updating globals so they properly work...

Ive attached my mod as it currently stands.
EDIT:
Im really starting to hate this language. Most common error? Compiling a script that doesnt exist...
Trying to do this
Code:
Fallout 4\Data\Scripts\Source\User\HorizonMCMSettings.psc
, when the file is
Code:
Fallout 4\Data\Scripts\Source\User\HorizonMCMSettings\MCMSettings.psc
. Any ideas for this one?
 
Last edited:
Scriptname HorizonMCMSettings:Main extends Quest
The secret is in this statement. ;)
HorizonMCMSettings:Main HorizonMCMSettings is the name space and Main is the filename. The default root is Fallout 4\Data\Scripts\Source\User\ so with the declared name space, Main.psc should be located in Fallout 4\Data\Scripts\Source\User\HorizonMCMSettings

So if you declared ScriptName A:B:C:D:E:ThisScript the file should be saved in Fallout 4\Data\Scripts\Source\User\A\B\C\D\E\ThisScript.psc
In the CK, if you go to Gameplay > Papyrus Script Manager you can right-click > New. A popup will allow you to name the new script and define a name space and the script you are extending. This will create a new psc file in the correct directory with ScriptName defined.

You may want to bookmark this page:

Good luck with the MCM config.json. There is not much documentation to be found. If you find something interesting, post it here.
Maybe some day I'll have enough knowledge to create a tutorial.
 
So for some reason the CK doesnt like this line:
Code:
If (EnableStartingItems.GetValueInt() == 0 && (PlayerRef.GetLevel() >= 3 || IgnorePlayerLevel.GetValueInt() == 1))
 
So for some reason the CK doesnt like this line:
Code:
If (EnableStartingItems.GetValueInt() == 0 && (PlayerRef.GetLevel() >= 3 || IgnorePlayerLevel.GetValueInt() == 1))
Compile error? I assume you have EnableStartingItems and IgnorePlayerLevel defined as GlobalVariable properties and PlayerRef defined as an Actor property? (or local variables)
You should avoid convenience functions like GetValueInt. Its better coding to inline cast as required. int iValue = SomeGlobal.GetValue() as int
So you could rewrite the posted statement as:
If ( EnableStartingItems.GetValue() == 0.0 && (PlayerRef.GetLevel() >= 3 || IgnorePlayerLevel.GetValue() == 1.0) )
 
Top