Project Zomboid

Project Zomboid

395 ratings
[v41] Mod Config Menu
2
3
2
2
   
Award
Favorite
Favorited
Unfavorite
File Size
Posted
Updated
86.086 KB
1 Jun, 2022 @ 7:20am
4 Aug, 2022 @ 12:56am
3 Change Notes ( view )

Subscribe to download
[v41] Mod Config Menu

Description
Howdy y'all.

This mod was born out of frustrations with the limitations of Mod Options. Instead of waiting for it to be eventually updated to include features I needed, I've built a new mod configuration manager from scratch instead. They can be used alongside each other, they shouldn't be conflicting, however to use MCM a different setup is required from modders.

The v42 version of this mod can be found here: https://steamhost.cn/steamcommunity_com/sharedfiles/filedetails/?id=3386620985

Implementing MCM into your mod

A very basic structure of a MCM implementation could look like this:

local MyModVariable = 12.5 if Mod.IsMCMInstalled_v1 then -- initialize the main mod option table local MyModOptions = ModOptionTable:New("MyMod", "My cool mod [-|-]/", false) -- Add options MyModOptions:AddModOption("MyModVariable", "number_slider", MyModVariable, { min = 1, max = 20, step = 0.5}, "My Setting", "This setting does this and that", function(value) MyModVariable = value end) end

This piece of code will result in this:



Allow me now to elaborate in detail what each bit does. First we check, if MCM is even installed at all:

if Mod.IsMCMInstalled_v1 then -- ... end

If it isn't, the rest of the MCM code will simply not run, but your mod can still function properly, it will just not be configurable and have all variables retain the value that you originally set them to.

However if MCM is present, then the next step is creating an Option Table for your mod:

-- function ModOptionTable:New(Mod_id, DisplayStr, bExtraTab) local MyModOptions = ModOptionTable:New("MyMod", "My cool mod [-|-]/", false)

Let's go over the individual arguments.

"Mod_id" is the unique identifier that MCM uses to keep track of your mod and the data it keeps saved for you. You only have to make sure that you pick an identifier that's unique and won't conflict with any other mod. Changing the identifier will make MCM "forget" about any data it might have saved about your mod.

"DisplayStr" is the string that will be displayed at the very top of your options section.

If "bExtraTab" is set to "true", then your mod will get its very own tab in the option screen, instead of sharing one page with other mods. This makes sense for large mods with overwhelmingly many options, but otherwise you should keep it to "false"

-- function ModOptionTable:AddModOption(Option_id, Option_type, DefaultValue, OptionData, DisplayStr, TooltipStr, CommitValueFunc) MyModOptions:AddModOption("MyModVariable", "number_slider", MyModVariable, { min = 1, max = 20, step = 0.5}, "My Setting", "This setting does this and that", function(value) MyModVariable = value end)

We are now getting into the interesting part. "AddModOption" is the function that describes a UI element that can be used to drive the value of a variable.

"Option_id" is another identifier that should be unique, however it only needs to be unique within your own mod.

"Option_type" determines what type of UI element this option will be, there are several to choose from for different purposes, we will get into them later.

"DefaultValue" sets the initial value of your option, it's most convenient to just place the variable here that you wish to have MCM manipulate, and place your default value there instead.

"OptionData" provides additional data to drive behavior of your UI element. It's highly dependent on what UI type you have chosen, some don't require any OptionData at all, in which case you can leave this argument as "nil". We will cover the rest later.

"DisplayStr" is the name of the option that users are going to see on their screen.

"TooltipStr" will have its contents displayed when the user hovers over your option with the mouse.

"CommitValueFunc" is the function that will be called, when your option has been manipulated by the user. You can use it to directly assign the value that MCM returns to your variable.

And that's pretty much it. The basic process for creating each option involves the same function, until you have everything you need.

Option Types

"text" - A text box that you can enter any strings into.
Value Type: String
OptionData: nil

"number" - A text box that only takes numeric values
Value Type: Number
OptionData: Table with following structure
{
(optional) min = [Lower bound of acceptable values]
(optional) max = [Upper bound of acceptable values]
(optional) step = [Number that all entered numbers must be divisible by, they will be rounded if need be. Set to 1 to only allow integers]
}

"number_slider" - A slider that can be dragged with the mouse to produce numeric values
Value Type: Number
OptionData: same as "number" but all fields are mandatory to define

"checkbox" - A single checkbox that can be either ticked or unticked
Value Type: Boolean
OptionData: nil

"checkbox_multi" - An array of checkboxes, each with their own value
Value Type: Table of Boolean values, corresponding to one tickbox each
OptionData: Table with Strings, containing the labels for each individual tick box

"color" - A color picker
Value Type: Table with following structure
{
(mandatory) r = [Number from 0 to 1]
(mandatory) g = [Number from 0 to 1]
(mandatory) b = [Number from 0 to 1]
}
OptionData: nil

"combobox" - A dropdown menu offering a finite amount of choices
Value Type: Number (to use as an index in your own code)
OptionData: Table with Strings, containing the labels for each individual dropbox entry

"keybind" - A special option, that doesn't return a value when set in the options menu, but invokes the function in "CommitValueFunc" when the user presses the associated key.
DefaultValue: Key code to bind action to initially.
OptionData: nil
CommitValueFunc: Function to run when key is pressed.

AddModOptionTable
AddModOptionTable is a syntactic alternative to AddModOption, that takes a table instead of loose arguments:

local Option = {} Option.Option_id = "MyModVariable" Option.Option_type = "number_slider" Option.DefaultValue = MyModVariable Option.OptionData = { min = 1, max = 20, step = 0.5} Option.DisplayStr = "My Setting" Option.TooltipStr = "This setting does this and that" Option.CommitValueFunc = function(value) MyModVariable = value end MyModOptions:AddModOptionTable(Option)

Using this is identical in effect to AddModOption, it's simply a different way of conveying the same information to MCM, which may be more convenient in some cases.

Custom Sandbox Settings
MCM can also allow modders to add additional options to Sandbox. It works similarly to normal mod options, but is more restricted at the moment. I will provide short documentation for it later.

Further Help
If you still want something clarified, feel free to give me a shout. I also included a working example mod, that implements the various different option types. Feel free to copy implementations from there or use them as a reference.



Contribute!
If you want to help improve MCM, whether that is by fixing bugs, extending functionality or making the UI prettier to look at, you can contribute and submit pull requests on github:

https://github.com/MerelyMezz/PZModConfigMenu

I don't have any particular guidelines for contributing yet, but I reserve the right to reject PRs if I have gripes with them.

Workshop ID: 2815552312
Mod ID: MCM_ExampleMod
Mod ID: ModConfigMenu
54 Comments
mezz  [author] 18 Dec, 2024 @ 3:40am 
I've updated the mod to v42: https://steamhost.cn/steamcommunity_com/sharedfiles/filedetails/?id=3386620985

It is now necessary to put MCM at the top of the load order, above any mod that uses it. Otherwise nothing about the implementation has changed.
Coldsteel 8 Aug, 2024 @ 3:35am 
Can you add an option for just a button, which immediately invokes the callback when you press it with no arguments? I have an extremely complicated settings window which is completely unreasonable to implement in any modconfig mod so I have to make my own UI window, but I need a way to open it from the settings screen. Right now I'm doing it by hacking into the UI and adding a button there next to one of my options, but ideally it would be simply supported out of the box.
Revion 17 Mar, 2024 @ 1:12am 
Makes sense. I found the checks that they use in Mod Options and they're very simple, so I think that should work for my needs.

Already had stuff running on apply, but broke things by running them in the main menu instead of inside the game.
mezz  [author] 17 Mar, 2024 @ 12:49am 
If you want to run code when "apply" is pressed, you can simply put it in your commit function. You can run checks in there, whether you are in the menu or in the game and run what you want accordingly.
Revion 16 Mar, 2024 @ 10:02pm 
Is there a function like OnApplyMainMenu or OnApplyInGame for this? They are functions that exist in "Mod Options"
Revion 8 Mar, 2024 @ 12:45pm 
Really love how powerful this MCM is. Thank you for making this. Works mostly as expected and was able to get exactly what I wanted.
Raptorkoda 15 Feb, 2024 @ 12:27pm 
work in game. on dedicated server?
mezz  [author] 1 Dec, 2023 @ 9:42am 
If someone else wants to, they can fork MCM and take over maintaining it. I'm not particularly active in PZ atm and have some other things going on. I won't really be able to take care of it.
Captain Tofu 1 Dec, 2023 @ 1:49am 
(since the pages pile up, maybe create a discussion topic on this. That is kinda critically important). you can do that at the top of the page, right between mod name and first mod picture
mezz  [author] 1 Dec, 2023 @ 1:23am 
Due to the recent forced 2FA thing that Github does now, I privated any repos that nobody was gonna need anyway. Now that I am locked out of my account for good, I wasn't gonna maintain it there anyway. If you want to look at the code, you can simply download the workshop addon and take a peek inside.