Repository navigation
[BUG] IL2CPP custom NPC portraits disappear after returning to menu and reloading a save #356
Description
Summary
On IL2CPP game 0.4.7f11, custom NPC portraits are available on the first save load but are missing after quitting to the menu and loading the save again. This was reproduced with PR #353 alone, without either NPC lookup optimization (#354 or #355).
Environment
- Schedule I beta 0.4.7f11, Steam build 25770926, updated and validated with SteamCMD.
- S1API PR fix: keep packaging-content patches working on game 0.4.7f11 #353 exact head:
8c22c42e2a3703320fc6af58424d0109957cbb84(beta.8 lineage plus the packaging compatibility change). - IL2CPP, MelonLoader 0.7.3, fresh f11 interop wrappers.
- Isolated game installation with S1API and a disposable minimal probe registering four automatic custom NPC roles: plain, customer, dealer, and supplier.
- Copied save fixture originally created on 0.4.6f8 Alternate. A newly created f11 save was not tested.
Steps to reproduce
- Register one automatic custom NPC for each of the four roles in a minimal test mod.
- Start the IL2CPP game and load the copied save. Wait until Main is loaded and normal gameplay is available.
- Check that all four custom NPCs have portraits.
- Quit to the main menu without restarting the game process.
- Load the same save and check the four portraits again.
- Repeat the menu/reload cycle once more.
Expected behavior
All four custom NPC portraits are available after each load, as on the first load.
Observed behavior
All four have portraits on load 1. All four report missing portraits on loads 2 and 3, with eight portrait capture errors across those reloads. Other probe observations remain stable: four NPCs, expected voice, walk speed, renderers, contacts, and PoI membership.
Representative retained state markers:
NPC|Load=1|Id=s1api_pr_customernpc|Walk=1.2|Voice=Hippie VO|Portrait=True|Pois=1|Circles=1|Objects=36
NPC|Load=2|Id=s1api_pr_customernpc|Walk=1.2|Voice=Hippie VO|Portrait=False|Pois=1|Circles=1|Objects=36
NPC|Load=3|Id=s1api_pr_customernpc|Walk=1.2|Voice=Hippie VO|Portrait=False|Pois=1|Circles=1|Objects=36
Controls and investigation limits
The #353-only control and the #353+#354+#355 integration produce identical per-NPC state reports and the same eight portrait errors. The Mono control on 0.4.7f11 Alternate (build 25770882) retains portraits through all three loads and has zero portrait errors.
This establishes reproduction without the optimization PRs. It does not establish the root cause or the first affected S1API version. The latest published prerelease was not separately exercised for this portrait scenario. Complete raw capture logs and the disposable probe were removed after validation; the counts and state markers above were retained.
Acceptance criteria
Reproduce and identify the responsible reload/capture lifecycle path, then verify that all four roles retain usable portraits through three same-process save loads on IL2CPP. Keep the passing Mono behavior intact.
Activity
ifBars commentedon Oct 8, 2026
@Diffuin Investigate this. Make sure your assembly copies are up to date. Find out why this would happen. Also look at code archiver commits for recent beta update changes related to this.
diffuin commentedon Oct 8, 2026
Issue investigation
Confidence: Low
The retained errors place the failure in portrait capture or validation, before icon assignment. An unusable render rig after reload is the leading hypothesis, but the initiating cause remains unproven. A missing-avatar path demonstrably skips the capture callback and can produce the reported error after a timeout. Assembly freshness could not be verified or refreshed: no game assemblies or IL2CPP wrappers were available, and the local beta archiver ends at f10.
Recommended next steps
Open questions
Evidence and validation
Evidence inspected
Validation performed
Runtime validation remaining
Diffuin run details
codexgpt-6.1-solhigh(Luna advisor: complexity (high); baseline source-backed technical request)01a119d9-bcf7-7530-912e-2394bd0c58b3AI notice: Generated with AI assistance and not guaranteed accurate. Verify findings and plans against the current source and runtime.
ifBars commentedon Oct 8, 2026
The f11 reload reproduction now isolates a pose failure: callbacks complete, but the cloned render avatar's head moves from about 1.62m to 1.25m during the settled frame. Visible portrait pixels drop from roughly 76,500 to 3,585, so coverage validation correctly rejects the image. Hip position and appearance scale remain unchanged.
A disposable diagnostic that disables gameplay animation on the owned fallback clone and rebinds/freezes its Animator preserves the upright portrait on first load and reload: all eight captures have 78,184 visible pixels and all four icons remain available. The known-good 410b552 capture flow supports keeping serialization and Update plus end-of-frame settling intact.
I will make that reset specific to the owned fallback mugshot rig, preserving workbench preview animation, live NPC animation, appearance application, explicit icons, and spawn/finalization order. Then validate the production change separately on Mono and IL2CPP before opening the fix PR.
ifBars commentedon Oct 8, 2026
The larger reproduction found why creation-time freezing was incomplete: native Avatar.Awake caches the live source's transient hip position; Avatar.Update restores it on the cloned rig during the settled frame. At #358 head
6052288, the owned clone records its rebound hip position so Update keeps the upright pose. Serialized capture and the frame wait are preserved.With #359 and optimization PRs #354/#355 included, both runtimes pass 32 NPC types over two same-process loads: 64 nonblank captures per runtime, matching saved/current hips to four decimal places, and one native NPC component per object. Controlled gender/weight capture checks also preserve the native blend-shape values. The workbench's inherited disabled-animator regression was reproduced and repaired on its separate preview clone.
Fresh IL2CPP co-op reload/rejoin is still an unresolved validation limit; real Steam transport is untested. PR #358 remains open with green hosted checks. No merge or release was performed.
ifBars commentedon Oct 9, 2026
Fixed by #358 and shipped in 3.2.1-beta.9.
The fallback clone now records its rebound hip position in the native saved-position field, so the next Avatar.Update retains the capture pose. Captures remain serialized with the existing settled-frame timing. The separate workbench clone has its animators enabled for pose controls.
On game beta 0.4.7f11 with MelonLoader 0.7.3, the final combined source generates 64 nonblank portraits from 32 custom NPC types over two loads on each runtime. Controlled gender/weight captures and preview pose checks pass on both runtimes. The final beta.9 DLLs also retain nonblank portraits on both peers during first load and same-process multiplayer reload/rejoin, with normal gameplay readiness checked. Closing as completed; real Steam transport remains untested.