Patching Functions Using Harmony - alexneargarder/BroforceMods GitHub Wiki
Harmony
Harmony is a library for patching or replacing .NET methods during runtime. It's the way we actually change the game's code.
This page will provide a brief overview of the most important methods I use to make Broforce mods, but if you would like an in-depth look at what Harmony can do, you can read the official documentation.
Patches
In order to use Harmony, you have to create a patch. There are two types of patches, prefix and postfix. Prefix patches run before the patched method, and postfix patches run afterwards.
Prefix Patches
A prefix patch could look like this. This patch simply writes a message to the log when the player presses the gesture button, which is the flex button.
// Player is the class that contains the method you're patching
// GetInput is the method you're patchhing
[HarmonyPatch(typeof(Player), "GetInput")]
// Player_GetInput_Patch is simply a name for the class that contains the patch
// You can use any name here but I would recommend using a consistent naming scheme
static class Player_GetInput_Patch
{
// Player __instance provides a reference to the current object
// that is running the method
// You can access the original arguments of the method by including
// arguments with the same name and type with the ref keyword added
public static void Prefix(Player __instance, ref bool buttonGesture)
{
// I would recommend including this in all of your patches
// If the mod is toggled off, enabled will be set to false,
// so we can simply return to avoid modifying the game behavior at all
if (!Main.enabled)
{
return;
}
if (buttonGesture)
{
// This message will display multiple times because the GetInput method is called many times per second
Main.Log("Player taunted");
}
}
}
If you change the value of the parameters in the prefix patch, that change will be carried over to the original method when it's executed.
You can also have a prefix patch that completely replaces the original method:
[HarmonyPatch(typeof(Player), "GetInput")]
static class Player_GetInput_Patch
{
public static bool Prefix(Player __instance, ref bool buttonGesture)
{
if (!Main.enabled)
{
return true;
}
return false;
}
}
With these types of prefix patches, if you return true, the original method will still be executed afterwards, in which case it's the same as a normal prefix patch, and if you return false, the original method will be skipped.
If you're patching a method that has a return value, you can also add an additional parameter to your patch like this:
ref bool __result
Replace bool with whatever the return type of the original method is. Whatever value you assign to __result is the value the original method will return if you skip the original method, otherwise the original method will overwrite the return value.
Postfix patches
A postfix patch could look like this:
[HarmonyPatch(typeof(Player), "IsInvulnerable")]
static class Player_IsInvulnerable_Patch
{
public static void Postfix(Player __instance, ref bool __result)
{
if (!Main.enabled)
{
return;
}
__result = true;
}
}
Postfix patches work basically the same as prefix patches except they run after the original method. They cannot be used to control whether the original method is executed or change the parameters of the original method, but they can change the return value of the original method with the __result parameter.