Installation
Creation
Misc
Installation
Creation
Misc
This is an old revision of the document!
This guide will help you create a simple Slime Rancher Mod for UMF that lets you modify your max health.
It will guide you through all the different methods you could use to modify the players max health, along with the method best suited for this particular task.
It is up to you to determine which method is better suited for anything else you might attempt to mod.
maxHealth
.MyFirstSRModConfig.cs
with the following code.//Add your config vars here.
public static int MaxHealth;
//Add your settings here
MaxHealth = cfg.Read("MaxHealth", new UMFConfigInt(999, 1, 9999), "This is the player's max health.");
using System; using UModFramework.API; namespace MyFirstSRMod { public class MyFirstSRModConfig { private static readonly string configVersion = "1.0"; //Add your config vars here. public static int MaxHealth; internal static void Load() { MyFirstSRMod.Log("Loading settings."); try { using (UMFConfig cfg = new UMFConfig()) { string cfgVer = cfg.Read("ConfigVersion", new UMFConfigString()); if (cfgVer != string.Empty && cfgVer != configVersion) { cfg.DeleteConfig(false); MyFirstSRMod.Log("The config file was outdated and has been deleted. A new config will be generated."); } //cfg.Write("SupportsHotLoading", new UMFConfigBool(false)); //Uncomment if your mod can't be loaded once the game has started. cfg.Read("LoadPriority", new UMFConfigString("Normal")); cfg.Write("MinVersion", new UMFConfigString("0.52.1")); //cfg.Write("MaxVersion", new UMFConfigString("0.54.99999.99999")); //Uncomment if you think your mod may break with the next major UMF release. cfg.Write("UpdateURL", new UMFConfigString("")); cfg.Write("ConfigVersion", new UMFConfigString(configVersion)); MyFirstSRMod.Log("Finished UMF Settings."); //Add your settings here MaxHealth = cfg.Read("MaxHealth", new UMFConfigInt(999, 1, 9999), "This is the player's max health."); MyFirstSRMod.Log("Finished loading settings."); } } catch (Exception e) { MyFirstSRMod.Log("Error loading mod settings: " + e.Message + "(" + e.InnerException?.Message + ")"); } } } }
This method uses only Unity Scripting and the game's own code to modify the max health value.
You can find this method by looking through the game code which will take some experience and analyzing.
For this particular scenario this method is not the best to use.
In Slime Rancher the PlayerModel class instance can be accessed through the GameModel instance class which in turn can be retrieved from the SceneContext using the SRSingleton class.
We can set this value directly using the following line:
SRSingleton<SceneContext>.Instance.GameModel.GetPlayerModel().maxHealth = MyFirstSRModConfig.MaxHealth;This would set maxHealth to whatever the config value is set to, in the default case 999.
MyFirstSRMod.cs
add the following at the top: using MonomiPark.SlimeRancher.DataModel;
//[UMFHarmony(1)]
private static PlayerModel playerModel;
MyFirstSRModConfig.Load();
if (!Levels.isSpecial() && SRSingleton<SceneContext>.Instance?.GameModel != null) //Makes sure we are in game and that the GameModel exists. { playerModel = SRSingleton<SceneContext>.Instance.GameModel.GetPlayerModel(); } if (playerModel != null) //Make sure that the PlayerModel has been retrieved. { playerModel.maxHealth = MyFirstSRModConfig.MaxHealth; //Set the max health to our config value. }
MyFirstSRMod.cs
should now look something like this:using UnityEngine; using UModFramework.API; using System; using System.Linq; using System.Collections.Generic; using MonomiPark.SlimeRancher.DataModel; namespace MyFirstSRMod { //[UMFHarmony(1)] //Set this to the number of harmony patches in your mod. [UMFScript] class MyFirstSRMod : MonoBehaviour { private static PlayerModel playerModel; internal static void Log(string text, bool clean = false) { using (UMFLog log = new UMFLog()) log.Log(text, clean); } [UMFConfig] public static void LoadConfig() { MyFirstSRModConfig.Load(); } void Awake() { Log("MyFirstSRMod v" + UMFMod.GetModVersion().ToString(), true); UMFGUI.RegisterPauseHandler(Pause); MyFirstSRModConfig.Load(); } public static void Pause(bool pause) { TimeDirector timeDirector = null; try { timeDirector = SRSingleton<SceneContext>.Instance.TimeDirector; } catch { } if (!timeDirector) return; if (pause) { if (!timeDirector.HasPauser()) timeDirector.Pause(); } else timeDirector.Unpause(); } void Update() { if (!Levels.isSpecial() && SRSingleton<SceneContext>.Instance?.GameModel != null) //Makes sure we are in game and that the GameModel exists. { playerModel = SRSingleton<SceneContext>.Instance.GameModel.GetPlayerModel(); } if (playerModel != null) //Make sure that the PlayerModel has been retrieved. { playerModel.maxHealth = MyFirstSRModConfig.MaxHealth; //Set the max health to our config value. } } } }
Patch_PURPOSEOFPATCH.cs
before building.
This method is the easiest way to do it, but it's still not entirely optimal.
MyFirstSRMod.cs
. [UMFHarmony(1)]
//MyFirstSRModConfig.Load();
Patch_PURPOSEOFPATCH.cs
.MyFirstSRMod.cs
should now look something like this:using UnityEngine; using UModFramework.API; using System; using System.Linq; using System.Collections.Generic; using MonomiPark.SlimeRancher.DataModel; namespace MyFirstSRMod { [UMFHarmony(1)] //Set this to the number of harmony patches in your mod. [UMFScript] class MyFirstSRMod : MonoBehaviour { //private static PlayerModel playerModel; internal static void Log(string text, bool clean = false) { using (UMFLog log = new UMFLog()) log.Log(text, clean); } [UMFConfig] public static void LoadConfig() { MyFirstSRModConfig.Load(); } void Awake() { Log("MyFirstSRMod v" + UMFMod.GetModVersion().ToString(), true); UMFGUI.RegisterPauseHandler(Pause); //MyFirstSRModConfig.Load(); } public static void Pause(bool pause) { TimeDirector timeDirector = null; try { timeDirector = SRSingleton<SceneContext>.Instance.TimeDirector; } catch { } if (!timeDirector) return; if (pause) { if (!timeDirector.HasPauser()) timeDirector.Pause(); } else timeDirector.Unpause(); } /*void Update() { if (!Levels.isSpecial() && SRSingleton<SceneContext>.Instance?.GameModel != null) //Makes sure we are in game and that the GameModel exists. { playerModel = SRSingleton<SceneContext>.Instance.GameModel.GetPlayerModel(); } if (playerModel != null) //Make sure that the PlayerModel has been retrieved. { playerModel.maxHealth = MyFirstSRModConfig.MaxHealth; //Set the max health to our config value. } }*/ } }
Patch_PURPOSEOFPATCH.cs
to Patch_MaxHealth.cs
along with the class name for it.Patch_MaxHealth.cs
: using MonomiPark.SlimeRancher.DataModel;
[HarmonyPatch(typeof(PlayerModel))]
[HarmonyPatch("ApplyUpgrade")]
public static void Postfix(PlayerModel __instance) { }
__instance.maxHealth = MyFirstSRModConfig.MaxHealth;
Patch_MaxHealth.cs
should now look something like this:using UnityEngine; using HarmonyLib; using MonomiPark.SlimeRancher.DataModel; namespace MyFirstSRMod.Patches { [HarmonyPatch(typeof(PlayerModel))] [HarmonyPatch("ApplyUpgrade")] static class Patch_MaxHealth { public static void Postfix(PlayerModel __instance) { __instance.maxHealth = MyFirstSRModConfig.MaxHealth; } } }
This method will show you how you can use a Transpiler to overwrite code in memory rather than inject new code into an existing function.
This method is really solid for when you really need to modify something that can't be otherwise modified with Method 1 or 2.
Coming tomorrow
Coming tomorrow
Since this is just an example mod you should not publicize it anywhere since anyone can easily do this.
However for the purpose of completion these steps should be taken before releasing any mod.
ModInfo.txt
to whatever you want to show users who install or update the mod.Properties\AssemblyInfo.cs
and fill in all the details of your mod.configVersion
in MyFirstSRModConfig.cs
to match the version in AssemblyInfo.cs
.