[PR #30] [MERGED] kb: Stick It To The Stickman - instant-fail choice prompts via Harmony death-path patches #69

Closed
opened 2026-10-15 20:53:09 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/rehan-remade/universal-modder/pull/30
Author: @chickennan
Created: 10/3/2026
Status: ✅ Merged
Merged: 10/4/2026
Merged by: @rehan-remade

Base: main ← Head: kb/stick-it-to-the-stickman-instant-fail-choice-prompts-patching-a-unity-level-s


📝 Commits (4)

  • 2b4a0a3 kb: Instant-fail choice prompts: patching a Unity level's death path with Harmony (Stick It To The Stickman)
  • 92966cf kb: record base death-handler suppression confirmed in a second played run
  • 6d82672 kb: separate human-confirmed visual layout from agent-unverifiable capture
  • 078b85f Merge main into kb/stick-it-to-the-stickman-instant-fail-choice-prompts-patching-a-unity-level-s and regenerate the kb index

📊 Changes

3 files changed (+253 additions, -1 deletions)

View changed files

📝 knowledge/INDEX.md (+2 -1)
➕ knowledge/games/stick-it-to-the-stickman/instant-fail-choice-prompts-patching-a-unity-level-s-death-p.md (+221 -0)
📝 knowledge/index.json (+30 -0)

📄 Description

What this adds

A field note for Stick It To The Stickman (Steam 2085540, Unity 2022.3.4, Mono) covering a
BepInEx 5 / Harmony mod that puts choice prompts in a level and kills the hero instantly on a wrong
pick. status: working, verified across two hand-played Normal Tower runs.

Why it's worth reading even if you never touch this game

Three findings generalise past this title:

  1. Patch the base of a virtual, not just the overrides. Only 8 of the game's level-logic
    controllers override TryManagePlayerDeath. Normal Tower's controller inherits it, so an
    overrides-only patch reported "8 types patched" and did nothing in the very level it was
    configured for. It looked fine anyway, because a time freeze and a defeat-UI intercept were
    masking the hole — the guarantee was accidental. Patching base and overrides is required, and
    neither alone suffices: an override that calls base keeps running its own post-base code if only
    the base is prefixed.

  2. A patch that logs on engagement is how you find this. The absence of a suppressed ...
    line in a log where a death had occurred was the only evidence that gave the bug away. Logging
    the concrete __instance.GetType().Name also shows which path ran — it revealed
    LevelLogicControllerTower as the class inheriting rather than overriding.

  3. Unity lifecycle: OnLevelDidStart fires mid-transition. LevelManager.Level is still null
    there, so caching the level name at that event made an allowlist silently match nothing for the
    entire run — every popup skipped, no error anywhere. Re-read identity at the point of use.

Also recorded: the game destroys the BepInEx plugin GameObject seconds after startup (long-lived
state needs its own DontDestroyOnLoad host and its own log file); ScriptableEnum costs a ~35s
synchronous Resources.LoadAll on first level access; Health.SetCurrentHealth(float) assigns
without ever calling Die(); and why a "load a level by name" debug command was written, measured
and then deleted.

Gotchas section

Nine numbered symptom → cause → fix entries, including two about verification itself:

  • main-thread stalls that make a command file look lossy when it is merely slow (~17s and ~32s
    measured) — wait before concluding a command was dropped;
  • a window-capture path that returns frames not showing the Unity render at all, which is why this
    note leans on logs rather than screenshots, and why a decoy screenshot is gitignored in the mod repo.

Verification honesty

Visual layout was confirmed by a human looking at the screen — prompt and FAIL card both
rendered correctly, text alignment good. It could not be confirmed by an agent, because capture on
this machine doesn't show the Unity render. The note separates those two claims rather than blurring
them.

Still open: the other seven levels that declare their own TryManagePlayerDeath override are patched
but untested in play. Only Normal Tower has been run.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/rehan-remade/universal-modder/pull/30 **Author:** [@chickennan](https://github.com/chickennan) **Created:** 10/3/2026 **Status:** ✅ Merged **Merged:** 10/4/2026 **Merged by:** [@rehan-remade](https://github.com/rehan-remade) **Base:** `main` ← **Head:** `kb/stick-it-to-the-stickman-instant-fail-choice-prompts-patching-a-unity-level-s` --- ### 📝 Commits (4) - [`2b4a0a3`](https://github.com/rehan-remade/universal-modder/commit/2b4a0a3a924e2b5ede29d8cfddb9d9273a5ad19b) kb: Instant-fail choice prompts: patching a Unity level's death path with Harmony (Stick It To The Stickman) - [`92966cf`](https://github.com/rehan-remade/universal-modder/commit/92966cf4297b17e06968a8c34c1565ef347bee2e) kb: record base death-handler suppression confirmed in a second played run - [`6d82672`](https://github.com/rehan-remade/universal-modder/commit/6d8267283fa5fc69dce882e8ef2cfda9cd44bb16) kb: separate human-confirmed visual layout from agent-unverifiable capture - [`078b85f`](https://github.com/rehan-remade/universal-modder/commit/078b85f250060787212c460db1e305ed9b5e589f) Merge main into kb/stick-it-to-the-stickman-instant-fail-choice-prompts-patching-a-unity-level-s and regenerate the kb index ### 📊 Changes **3 files changed** (+253 additions, -1 deletions) <details> <summary>View changed files</summary> 📝 `knowledge/INDEX.md` (+2 -1) ➕ `knowledge/games/stick-it-to-the-stickman/instant-fail-choice-prompts-patching-a-unity-level-s-death-p.md` (+221 -0) 📝 `knowledge/index.json` (+30 -0) </details> ### 📄 Description ## What this adds A field note for **Stick It To The Stickman** (Steam 2085540, Unity 2022.3.4, Mono) covering a BepInEx 5 / Harmony mod that puts choice prompts in a level and kills the hero instantly on a wrong pick. `status: working`, verified across two hand-played Normal Tower runs. ## Why it's worth reading even if you never touch this game Three findings generalise past this title: 1. **Patch the base of a virtual, not just the overrides.** Only 8 of the game's level-logic controllers override `TryManagePlayerDeath`. Normal Tower's controller *inherits* it, so an overrides-only patch reported "8 types patched" and did nothing in the very level it was configured for. It looked fine anyway, because a time freeze and a defeat-UI intercept were masking the hole — the guarantee was accidental. Patching base **and** overrides is required, and neither alone suffices: an override that calls `base` keeps running its own post-base code if only the base is prefixed. 2. **A patch that logs on engagement is how you find this.** The absence of a `suppressed ...` line in a log where a death *had* occurred was the only evidence that gave the bug away. Logging the concrete `__instance.GetType().Name` also shows *which* path ran — it revealed `LevelLogicControllerTower` as the class inheriting rather than overriding. 3. **Unity lifecycle: `OnLevelDidStart` fires mid-transition.** `LevelManager.Level` is still null there, so caching the level name at that event made an allowlist silently match nothing for the entire run — every popup skipped, no error anywhere. Re-read identity at the point of use. Also recorded: the game destroys the BepInEx plugin `GameObject` seconds after startup (long-lived state needs its own `DontDestroyOnLoad` host and its own log file); `ScriptableEnum` costs a ~35s synchronous `Resources.LoadAll` on first level access; `Health.SetCurrentHealth(float)` assigns without ever calling `Die()`; and why a "load a level by name" debug command was written, measured and then deleted. ## Gotchas section Nine numbered symptom → cause → fix entries, including two about verification itself: - main-thread stalls that make a command file *look* lossy when it is merely slow (~17s and ~32s measured) — wait before concluding a command was dropped; - a window-capture path that returns frames not showing the Unity render at all, which is why this note leans on logs rather than screenshots, and why a decoy screenshot is gitignored in the mod repo. ## Verification honesty Visual layout was confirmed **by a human** looking at the screen — prompt and FAIL card both rendered correctly, text alignment good. It could not be confirmed *by an agent*, because capture on this machine doesn't show the Unity render. The note separates those two claims rather than blurring them. Still open: the other seven levels that declare their own `TryManagePlayerDeath` override are patched but untested in play. Only Normal Tower has been run. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-10-15 20:53:09 +00:00
Sign in to join this conversation.
No labels
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
rehan-remade/universal-modder#69
No description provided.