DevourUnlocker/BepInEx/DevourUnlocker.cs
MiTHRAL 4dd7b8d393
Some checks are pending
Build DevourUnlocker / windows-cross (push) Waiting to run
Build DevourUnlocker / linux (push) Waiting to run
Build DevourUnlocker / standalone (push) Waiting to run
always-on: BepInEx + winhttp always return true, no GUI toggle
- BepInEx: Patches now always-on (IsRobe/IsCharacter/HasPerk/HasOutfit true, UpdateLocked* skipped, WaitForPurchasedPetValidation skipped), GUI hidden by default, no selective checks
- native winhttp: src/main.cpp minimal HookThread that waits for GameAssembly + IL2CPP domain then installPatches (no ImGui/D3D11 dummy, no AllocConsole, no libgcc dep) — fixes crash at 0xB5A02F8 strlen null
- patches: hIsRobe/hIsChar etc now always true, hookUpdateLocked always bypass, retry for 60s until lobby
- winhttp_proxy: runtime forwarding to C:\Windows\System32\winhttp.dll for all 26 WinHttp* (fixes Wine crash)
- standalone: _patch_collectables_all now exact full sets (BarbedWires 6, Feathers 2, Tickets 7 etc) not superset 8, so HasCollectedAll* passes; diagnose checks WINEDLLOVERRIDES
2026-08-23 23:31:56 -04:00

84 lines
5 KiB
C#

using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using System;
using System.Linq;
namespace DevourUnlocker.BepInEx
{
[BepInPlugin("com.mithral.devourunlocker", "DevourUnlocker", "2.0.0")]
public class Plugin : BaseUnityPlugin
{
internal static ManualLogSource Log;
private Harmony _harmony;
void Awake()
{
Log = Logger;
Log.LogInfo("DevourUnlocker BepInEx v2 loaded — selective unlock");
_harmony = new Harmony("com.mithral.devourunlocker");
try {
_harmony.PatchAll();
Log.LogInfo("Harmony patches applied");
} catch (Exception e) { Log.LogError(e); }
}
void OnGUI()
{
if (!DevourGUI.visible) return;
DevourGUI.Draw();
}
void Update()
{
if (UnityEngine.Input.GetKeyDown(UnityEngine.KeyCode.F6)) DevourGUI.visible = !DevourGUI.visible;
}
void OnDestroy() { _harmony?.UnpatchSelf(); }
}
// Generic unlock patches — try multiple owner classes
// Always-on: every IsRobe/IsCharacter/Has* check returns true, every UpdateLocked* is skipped
static class Patches
{
static System.Reflection.MethodBase Find(string typeName, string method) {
var t = AccessTools.TypeByName(typeName);
if (t==null) return null;
var m = AccessTools.Method(t, method);
if (m!=null) Plugin.Log?.LogInfo($"Found {typeName}.{method}");
return m;
}
static System.Reflection.MethodBase FindAny(string method, params string[] types){
foreach(var tn in types){ var m=Find(tn,method); if(m!=null) return m; }
Plugin.Log?.LogWarning($"{method} not found in {string.Join(",",types)}");
return null;
}
[HarmonyPatch] class IsRobeUnlockedPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("IsRobeUnlocked","NolanRankController","SurvivalLobbyController","LobbyController"); static bool Prefix(ref bool __result){ __result=true; return false; } }
[HarmonyPatch] class IsCharacterUnlockedPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("IsCharacterUnlocked","NolanRankController","SurvivalLobbyController"); static bool Prefix(ref bool __result){ __result=true; return false; } }
[HarmonyPatch] class HasPerkPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("HasPerk","NolanRankController"); static bool Prefix(ref bool __result){ __result=true; return false; } }
[HarmonyPatch] class HasOutfitPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("HasOutfit","NolanRankController"); static bool Prefix(ref bool __result){ __result=true; return false; } }
[HarmonyPatch] class HasCollectedAllPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("HasCollectedAllBarbedWires","NolanRankController"); static bool Prefix(ref bool __result){ __result=true; return false; } }
// UpdateLocked* — skip (return false to prevent original from marking locked)
[HarmonyPatch] class UpdateLockedPetsPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("UpdateLockedPets","SurvivalLobbyController","LobbyController"); static bool Prefix()=> false; }
[HarmonyPatch] class UpdateLockedPerksPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("UpdateLockedPerks","SurvivalLobbyController"); static bool Prefix()=> false; }
[HarmonyPatch] class UpdateLockedFlashlightsPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("UpdateLockedFlashlights","SurvivalLobbyController"); static bool Prefix()=> false; }
[HarmonyPatch] class UpdateLockedEmotesPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("UpdateLockedEmotes","SurvivalLobbyController"); static bool Prefix()=> false; }
[HarmonyPatch] class UpdateLockedOutfitsPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("UpdateLockedOutfits","SurvivalLobbyController"); static bool Prefix()=> false; }
[HarmonyPatch] class UpdateLockedRobesPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("UpdateLockedRobes","SurvivalLobbyController"); static bool Prefix()=> false; }
[HarmonyPatch] class WaitForPurchasedPetValidationPatch { static System.Reflection.MethodBase TargetMethod()=> FindAny("WaitForPurchasedPetValidation","SurvivalLobbyController"); static bool Prefix()=> false; }
}
static class DevourGUI
{
public static bool visible = false; // always-on, GUI hidden by default (F6 to show debug)
public static void Draw()
{
var rect = new UnityEngine.Rect(20, 20, 400, 100);
UnityEngine.GUI.Box(rect, "");
GUILayout.BeginArea(rect);
GUILayout.Label("DevourUnlocker — Always On (all robes/chars/perks/pets unlocked)");
GUILayout.Label("F6 to toggle this debug window");
GUILayout.EndArea();
}
}
}