Metadata dig findings (Assembly-CSharp, 2349 types):
- SteamInventoryValidator.PlayerHasItem(connId, steamItemDefID): multiplayer/purchase
validation gate used by WaitForPurchased{Pet,Emote,Flashlight,Outfit}Validation
coroutines (<validator>5__4) -> hooked true
- SteamInventoryManager.HasRetrievedUserInventoryItems(): gates PopulateInventoryWhenAvailable;
if Steam inventory query under Proton returns nothing, item views never populate ->
hooked true so lobby tabs build with UserHasItem=true
- SteamInventoryManager.userItems cache read directly by UI in some paths — covered by
UserHasItem+PlayerHasItem+HasRetrieved trio
Now 15 hooks: IsRobeUnlocked/IsCharacterUnlocked/HasPerk/HasOutfit->true,
UserHasItem/PlayerHasItem->owned, GetCurrentTokens->9999999,
HasRetrievedUserItems->true, UpdateLocked*(6)+WaitForPurchasedPetValidation call-through.
Pets/perks/flashlights/emotes/outfits route through the game's own grant path — no
purchase browser, no coin spoofing visible anywhere.
Root cause of 'robes unlocked but nothing else': UpdateLocked* no-op prevented lock
marking but lobby UI defaults to locked until UpdateLocked* runs its grant logic.
Robes worked because IsRobeUnlocked (hooked) gates selection directly.
Fix from global-metadata.dat analysis (148772 methods scanned):
- SteamInventoryManager.UserHasItem(steamItemDefID) -> always true: every Steam catalog
item (pets/flashlights/emotes/outfits/promos) counts as owned
- Horror.Menu.GetCurrentTokens() -> 9999999: perk token cost always affordable
- UpdateLocked*/WaitForPurchasedPetValidation now CALL ORIGINAL via trampoline so the
game's own grant logic runs with overridden ownership (clean UI state)
- hookUpdateLocked stores orig fn pointer; retry thread also retries UserHasItem/Tokens
and HasPerk/HasOutfit; logPatch on every hook success/failure for diagnosis
Verified launch: 13 hooks installed (IsRobe/IsChar/HasPerk/HasOutfit/UserHasItem/
GetCurrentTokens/7xUpdateLocked+WaitPet), game stable, no crashes
- winhttp: runtime forwarding for all WinHttp* (fixes Wine crash on WinHttpGetIEProxyConfigForCurrentUser, was forwarding to winhttp_real.dll which doesn't exist)
- resolver: wait for IL2CPP domain + enumerate all images/classes for IsRobe/UpdateLocked*, dumpDiagnostics now shows FOUND for SurvivalLobbyController etc
- patches: handle MH_ERROR_ALREADY_INITIALIZED, background retry for 60s for UpdateLockedPets/WaitForPurchasedPetValidation (fixes pets not unlocking when lobby not yet loaded)
- standalone: unlock --all now patches Steam Cloud collectables.json for all 3 users (BarbedWires/Feathers/Tickets etc to superset) and updates remotecache.vdf sha/size/time so Steam doesn't overwrite; also auto-deploys winhttp.dll via injector
- diagnose: checks winhttp.dll, DevourUnlocker.log, WINEDLLOVERRIDES, collectables.json
- launch.sh: sets WINEDLLOVERRIDES and launches via Proton