GAMECHANGE
How to create a DLL mod with Humankind Mod Tool - Printable Version

+- GAMECHANGE (https://gc2021.com)
+-- Forum: Humankind Mod Tool (https://gc2021.com/forumdisplay.php?fid=1)
+--- Forum: Humankind Mod Tool Tutorials (https://gc2021.com/forumdisplay.php?fid=3)
+--- Thread: How to create a DLL mod with Humankind Mod Tool (/showthread.php?tid=13)



How to create a DLL mod with Humankind Mod Tool - _A_ - 08-24-2021

This tutorial goes over how to create a shareable DLL mod for Humankind.

You will need:
1. Humankind installed
2. BepInEx installed 
3. Humankind Mod Tool installed with your game path configured. (Tutorial)
4. A C# editor. Visual Studio Code or Visual Studio is recommended. You can also use a text editor and the command line dotnet compiler.

1. Start HMT.
2. Click the "Create" tab.
3. If you haven't done so already, click Decompile Game Scripts. This will create a Visual Studio solution with all of the game dlls decompiled. You can use this as a reference to know what you want to change and see how the original code worked.
4. Click "Create New Project". It will create a C# project that references the game DLLs (from the references folder of Documents/Humankind Mod Tool) as well as BepInEx and Harmony which are needed to create mods.
5. If you have installed Visual Studio Code and set it up in your settings, click "Open" on your project in the project list. Otherwise, you will need to open the .csproj file manually with a C# editor of your choice.
6. Once you have opened your project, fill in the information about your mod in the BepInPlugin attribute in the generated C# file.
7. Using the decompiled source code, find a part that you want to change and copy it into the class generated for you. Depending on what you are replacing, the next steps may differ. Using Harmony patches, alter whichever part of the game that you wish. 

8. Once you are done making your modifications, compile your project. If you are using VS Code, a build task is included in your project. The output path should already be set to go to your Humankind/BepInEx/plugins folder. 

9. Your mod should now show on the "Manage" tab of HMT. Make sure that it is enabled, and test in game.

Example code below:
Code:
using Amplitude.Mercury.Simulation;
using Amplitude.Mercury.Interop;
using BepInEx;
using HarmonyLib;
using System.Reflection;
namespace AOM.Humankind.NoFogofWar
{
    //Set the mod name and version. This is generated by HMT, but you can change it if you want to.
    [BepInPlugin(PLUGIN_GUID, "No Fog of War", "1.0.0.0")]
    public class NoFogofWar : BaseUnityPlugin
    {
        //Set your plugin id. One will be generated for you by HMT
        const string PLUGIN_GUID = "AOM.Humankind.NoFogOfWar";
        void Awake()
        {
            //This initializes Harmony
            var harmony = new Harmony(PLUGIN_GUID);
            //This applies all patches in your current project
            harmony.PatchAll();

        }
    }
    //This tells Harmony which class you are patching
    [HarmonyPatch(typeof(DepartmentOfTheInterior))]
    public class DepartmentOfTheInterior_Patch_Load
    {
        //Since many of Humankind's classes are internal, you will need to use reflection often times. HMT will make all types public, but if the original is internal, you need reflection to use members even if they are public.
        static MethodInfo ProcessOrderEnableFogOfWar = typeof(DepartmentOfTheInterior)
                        .GetMethod(
                            nameof(ProcessOrderEnableFogOfWar),
                            //Specifiy Public or NonPublic depending on the access modifier of the original method and Instance or Static, or you will get a null reference exception
                            BindingFlags.NonPublic | BindingFlags.Instance
                        );
        //This tells Harmony that you want to change the "Load" method of "DepartmentOfTheInterior" class.
        [HarmonyPatch(nameof(Load))]
        //This tells Harmony that you want your code to run before the original code.
        [HarmonyPrefix]
        //Note: all Harmony patch methods must be static even if the original is not.
        public static void Load(
            DepartmentOfTheInterior __instance //This is a Harmony specific way of getting access to the instance of the class you are patching (if the original method is not static)
        )
        {
            //This is the actual modded code. It simply turns off the FOW with an order. Note, it uses the reflection because even though Load is a public method, DepartmentOfTheInterior is not, so if you try to access it directly, you will get a runtime error.
            ProcessOrderEnableFogOfWar.Invoke(__instance, new object[]{ new OrderEnableFogOfWar
            {
                Enable = false
            }});
        }
    }
}