diff --git a/Content/ExampleMod/Localization/En.json b/Content/ExampleMod/Localization/En.json
index 7d22f11..3f87a5c 100644
--- a/Content/ExampleMod/Localization/En.json
+++ b/Content/ExampleMod/Localization/En.json
@@ -14,5 +14,8 @@
},
"Actions": {
"ExampleMod.SitOnGrass": "Sit on Grass"
+ },
+ "Ui": {
+ "ExampleMod.DarkShirtSpeedOption": "Dark Shirt Speed"
}
}
diff --git a/ExampleMod.cs b/ExampleMod.cs
index 029e8d3..a2d9b73 100644
--- a/ExampleMod.cs
+++ b/ExampleMod.cs
@@ -4,6 +4,8 @@ using ExtremelySimpleLogger;
using MLEM.Data;
using MLEM.Data.Content;
using MLEM.Textures;
+using MLEM.Ui;
+using MLEM.Ui.Elements;
using TinyLife;
using TinyLife.Actions;
using TinyLife.Emotions;
@@ -18,6 +20,7 @@ public class ExampleMod : Mod {
// the logger that we can use to log info about this mod
public static Logger Logger { get; private set; }
+ public static ModOptions Options { get; private set; }
public static EmotionModifier GrassSittingModifier { get; private set; }
@@ -62,7 +65,7 @@ public class ExampleMod : Mod {
// changing the walk speed to be doubled if a person is wearing our dark shirt
person.OnGetWalkSpeed += (ref float s) => {
if (person.CurrentOutfit.Clothes.TryGetValue(ClothesLayer.Shirt, out var shirt) && shirt.Type == darkShirt)
- s *= 2;
+ s *= ExampleMod.Options.DarkShirtSpeedIncrease;
};
}
};
@@ -82,10 +85,10 @@ public class ExampleMod : Mod {
CanDoRandomly = true,
// the solved needs indicate when the AI should mark this action as important, they don't actually have to match the action's behavior
SolvedNeeds = new[] {NeedType.Energy},
- // make people more likely to sit down in the grass if they're uncomfortable
+ // make people more likely to sit down in the grass if they're uncomfortable
PassivePriority = p => p.Emotion == EmotionType.Uncomfortable ? 150 : 25
},
- // since this action doesn't use objects (like chairs etc.), we set a texture to display instead
+ // since this action doesn't use objects (like chairs etc.), we set a texture to display instead
Texture = this.uiTextures[1, 0]
});
@@ -99,6 +102,7 @@ public class ExampleMod : Mod {
public override void Initialize(Logger logger, RawContentManager content, RuntimeTexturePacker texturePacker, ModInfo info) {
ExampleMod.Logger = logger;
+ ExampleMod.Options = ModOptions.Load(info);
// loads a texture atlas with the given amount of separate texture regions in the x and y axes
// we submit it to the texture packer to increase rendering performance. The callback is invoked once packing is completed
@@ -118,4 +122,18 @@ public class ExampleMod : Mod {
yield return "CustomFurniture";
}
+ // this method can be overridden to populate the section in the mod tab of the game's options menu where this mod's options should be displayed
+ // this mod uses the ModOptions class to manage its options, though that is optional
+ // in general, options should be stored in the ModInfo.OptionsFile file that is given to the mod by the game
+ public override void PopulateOptions(Group group, ModInfo info) {
+ group.AddChild(new Paragraph(Anchor.AutoLeft, 1, _ => $"{Localization.Get(LnCategory.Ui, "ExampleMod.DarkShirtSpeedOption")}: {ExampleMod.Options.DarkShirtSpeedIncrease}"));
+ group.AddChild(new Slider(Anchor.AutoLeft, new Vector2(1, 12), 5, 5) {
+ CurrentValue = ExampleMod.Options.DarkShirtSpeedIncrease,
+ OnValueChanged = (_, v) => {
+ ExampleMod.Options.DarkShirtSpeedIncrease = v;
+ ExampleMod.Options.Save(info);
+ }
+ });
+ }
+
}
diff --git a/ExampleMod.csproj b/ExampleMod.csproj
index d1188e7..229fec5 100644
--- a/ExampleMod.csproj
+++ b/ExampleMod.csproj
@@ -5,7 +5,7 @@
-
+
@@ -13,6 +13,7 @@
+
diff --git a/ModOptions.cs b/ModOptions.cs
new file mode 100644
index 0000000..86b5d45
--- /dev/null
+++ b/ModOptions.cs
@@ -0,0 +1,36 @@
+using System.IO;
+using Newtonsoft.Json;
+using TinyLife;
+using TinyLife.Mods;
+
+namespace ExampleMod;
+
+// a simple implementation of custom options for the example mod
+public class ModOptions {
+
+ public float DarkShirtSpeedIncrease = 2;
+
+ // a simple save method for the mod options, which saves the current instance to the designated options file
+ public void Save(ModInfo info) {
+ ExampleMod.Logger.Info($"Saving options to {info.OptionsFile}");
+ if (!info.OptionsFile.Directory.Exists)
+ info.OptionsFile.Directory.Create();
+ using var writer = new JsonTextWriter(info.OptionsFile.CreateText());
+ SaveHandler.CreateSerializer(null).Serialize(writer, this);
+ }
+
+ // a simple loader for the mod options, which uses the designated options file given to us by the game
+ // this method loads an instance of the options using a JSON loader and then returns it to be used in ExampleMod
+ public static ModOptions Load(ModInfo info) {
+ ExampleMod.Logger.Info($"Loading options from {info.OptionsFile}");
+ if (info.OptionsFile.Exists) {
+ using var reader = new JsonTextReader(info.OptionsFile.OpenText());
+ return SaveHandler.CreateSerializer(null).Deserialize(reader);
+ } else {
+ var ret = new ModOptions();
+ ret.Save(info);
+ return ret;
+ }
+ }
+
+}