Patching methodology
All patches in SpawnTracker follow these conventions:Postfix-only pattern
Every patch uses[HarmonyPostfix] to run after the original method completes. This ensures:
- No interference with game logic
- Safe to observe results and state changes
- Compatible with other mods
Tracking guard
Most patches checkPlugin.disableTracker before recording events:
Logging pattern
All patches log their actions usingPlugin.log.LogInfo() for debugging.
Patch classes
SpawnInteractablesPatches
Patches theSpawnInteractables class to detect when chests and shrines spawn.
File location: Plugin.cs:280-323
Patched methods:
SpawnChests patch also handles creating the overlay GameObject on first chest spawn.
TrackStatsPatches
Patches the game’s stats tracking to detect chest opens. File location:Plugin.cs:326-338
Mathf.Max() to prevent negative counts from edge cases.
ShadyGuyPatches
PatchesInteractableShadyGuy to track mysterious NPC spawns and interactions.
File location: Plugin.cs:341-372
ref bool __result parameter in Interact - this is a Harmony feature that lets patches access the return value.
ChargeShrineStartPatch
Patches the privateChargeShrine class using runtime type lookup.
File location: Plugin.cs:375-392
TargetMethod() to patch classes that aren’t public or aren’t in referenced assemblies.
ChargeShrineCompletePatch
Detects when a charge shrine is completed. File location:Plugin.cs:394-410
MoaiPatches
PatchesInteractableShineMoai for Moai shrine interactions.
File location: Plugin.cs:242-277
MoaiSpawnPatch which patches SpawnInteractables.SpawnShrines.
GameManagerPatches
PatchesGameManager to detect round start events.
File location: Plugin.cs:413-466
GameManager.OnDied- Disables tracking and resets on deathGameManager.OnDestroy- Cleanup when GameManager is destroyed
SpawnPlayerPortal_StartPortal
Patches portal spawning to detect stage transitions. File location:Plugin.cs:498-519
Adding new patches
To patch a new game class:1. Public class with known methods
Use declarative attributes:2. Private class or runtime-only types
UseTargetMethod() pattern:
3. Accessing parameters and return values
Harmony provides special parameter names:__instance- The instance being patched (this)__result- The return value (userefto modify)- Named parameters - Match the original method’s parameter names
Best practices
- Always use Postfix unless you need to prevent execution (Prefix) or modify results
- Check tracking flags to respect round lifecycle
- Validate return values when patching methods that can fail
- Log all events for debugging and verification
- Use Mathf.Max() when decrementing counters to prevent negatives
- Test with multiple mods to ensure compatibility
Debugging patches
If a patch isn’t working:- Check BepInEx console output for Harmony errors
- Verify the target method name and signature
- Use
Plugin.log.LogInfo()to confirm patch execution - For IL2CPP games, ensure types are registered with
ClassInjector - Check that
harmony.PatchAll()is called inPlugin.Load()