Nightgate cache bag fix - Thief 1.9.2.4 - 2026-10-02

Cause and lifecycle audit
-------------------------
bd_cachethief_sc.OnEquipped calls hp_thdea_sc.IsCanOpenCache. The original
predicate allows only a stopped bd_sq_help or current stage 300, 310, 312.
Stage 400 has the Complete Quest flag, but its Fragment_90 is empty and
never calls Stop(). Completion alone does not stop the running quest.

Do NOT add Stop() to stage 400:
SCEN 047D56C4 (bd_sq_help_28_farewell_end, drinking route) binds phase 0
end to Fragment_3, which sets stage 400 and restores saving. Phase 2 end
calls Fragment_6, which can provide the true-memory reminder and display
bd_MQ objective 710. Phase 3 end calls Fragment_2, which sets stage 341
and SetDefaultNGI=True. Stage 341 unlocks the inn doors, disables the
thief/innkeeper references and starts hp_ThiefRew. Stopping the owning
quest at 400 risks cutting off those remaining scene actions/aliases.
The refusal route SCEN 047F88F4 instead calls 341 at phase 1 end, then
400 at scene end. Both routes therefore eventually have BOTH stages done.
Stage 312 explicitly starts hp_ThiefRew and stops bd_sq_help; stage 311
also explicitly stops it. A missing Stop at 400 cannot be treated as the
same case: the successful Nightgate scene ordering depends on continuing.
Author intent beyond these observable dependencies is not established.

Fix
---
Only hp_thdea_sc.IsCanOpenCache gains an early True return when both
GetStageDone(400) and GetStageDone(341) are true. All original conditions
remain bytecode-identical after the five new instructions. Do not use
GetStage()==341: the engine can retain the higher stage 400 even after
executing 341. No quest stopping, resets, stage advancement, aliases,
rewards, item-transfer code, or plugin records are changed.

Build and validation
--------------------
Original PEX disassembled/reassembled with Bethesda PapyrusAssembler.
Assembly: 0 errors, 0 warnings. Parsed PEX comparison: only the intended
five instructions added; all other functions, properties and variables
unchanged. 104 predicate combinations tested using the actual parsed
instructions, including stopped tasks, original allowed stages, active
negotiation, incomplete cleanup, and both terminal stages done.
Champollion parses the output but misrenders the early-return structure;
the supplied PSC is the manually corrected equivalent source. The PAS
and build_patch.py reproduce the installed bytecode. See validation.json.

Installation and in-game checks (pending)
----------------------------------------
Installed scripts/hp_thdea_sc.pex plus source/scripts/hp_thdea_sc.psc and
.pas. Existing fixes and Thief - Fixes.esp are unchanged. Default profile
already enables Thief - Fixes after the original mod in priority order.
Exit Skyrim fully and relaunch through MO2. On the existing post-farewell
save, use a cache bag from inventory; one bag should disappear and its
contents should be transferred. Repeat for remaining bags. No StopQuest
or SetStage command is needed. If blocked, query GetStageDone bd_sq_help
400 and GetStageDone bd_sq_help 341; both must be 1. Verify both farewell
routes and that bags remain blocked during unfinished negotiations.
