using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using SpawnStats.UI;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("SpawnStats")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("SpawnStats")]
[assembly: AssemblyCopyright("Copyright © 2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("42bcfad8-6e0d-4c8e-889f-2cb81eba095e")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SpawnStats
{
[BepInPlugin("nachariah.whiteknuckle.spawnstats", "SpawnStats", "1.1.1")]
[BepInProcess("White Knuckle.exe")]
public class Plugin : BaseUnityPlugin
{
public const string GUID = "nachariah.whiteknuckle.spawnstats";
public Plugin instance;
private void Awake()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Expected O, but got Unknown
instance = this;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[SpawnStats] Patching...");
Harmony val = new Harmony("nachariah.whiteknuckle.spawnstats");
val.PatchAll();
SceneManager.sceneLoaded += OnSceneLoaded;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[SpawnStats] Loaded");
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (((Scene)(ref scene)).name == "Game-Main")
{
CommandConsole.hasCheated = true;
CL_GameManager.gamemode.allowAchievements = false;
CL_GameManager.gamemode.allowCheatedScores = false;
Debug.Log((object)"[SpawnStats] Leaderboard Disabled");
}
}
public static void LabelSpawnEntityByID(UT_SpawnEntityByID instance)
{
SpawnSettings spawnSettings = instance.spawnSettings;
if (spawnSettings == null)
{
return;
}
float effectiveSpawnChance = spawnSettings.GetEffectiveSpawnChance();
if (Mathf.Approximately(effectiveSpawnChance, 1f))
{
GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(instance.idToSpawn, instance.customDatabase);
if ((Object)(object)assetGameObject != (Object)null && (Object)(object)assetGameObject.GetComponentInChildren<UT_SpawnChance>() != (Object)null)
{
return;
}
}
string displayText = "Spawner\nID: " + instance.idToSpawn + $"\nChance: {effectiveSpawnChance:P1}";
TagGO(((Component)instance).gameObject, GetModText(displayText, spawnSettings));
}
public static void ForceSpawnAndLabel(UT_SpawnChance __instance)
{
SpawnSettings spawnSettings = __instance.spawnSettings;
if (spawnSettings == null)
{
return;
}
((Component)__instance).gameObject.SetActive(true);
float effectiveSpawnChance = spawnSettings.GetEffectiveSpawnChance();
float spawnChance = spawnSettings.spawnChance;
UT_SpawnEntityByID componentInParent = ((Component)__instance).GetComponentInParent<UT_SpawnEntityByID>();
if (Mathf.Approximately(effectiveSpawnChance, 1f) && (Object)(object)componentInParent != (Object)null)
{
float effectiveSpawnChance2 = componentInParent.spawnSettings.GetEffectiveSpawnChance();
if (!Mathf.Approximately(effectiveSpawnChance2, 1f))
{
return;
}
}
string text = ((Object)((Component)__instance).gameObject).name + $"\nBase Chance: {spawnChance:P1}";
if (effectiveSpawnChance != spawnChance)
{
text += $"\nEffective Chance: {effectiveSpawnChance:P1}";
}
TagGO(((Component)__instance).gameObject, GetModText(text, spawnSettings));
}
public static void TagGO(GameObject gameObject, string displayText)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
SpawnLabelTag spawnLabelTag = gameObject.GetComponent<SpawnLabelTag>();
if ((Object)(object)spawnLabelTag == (Object)null)
{
spawnLabelTag = gameObject.AddComponent<SpawnLabelTag>();
}
if ((Object)(object)spawnLabelTag.label == (Object)null)
{
GameObject val = new GameObject("SpawnChanceLabel");
ChanceLabel chanceLabel = val.AddComponent<ChanceLabel>();
chanceLabel.Init(gameObject.transform, displayText);
spawnLabelTag.label = val;
}
else
{
ChanceLabel component = spawnLabelTag.label.GetComponent<ChanceLabel>();
if ((Object)(object)component != (Object)null)
{
component.SetText(displayText);
}
}
}
public static string GetModText(string displayText, SpawnSettings settings)
{
List<string> list = new List<string>();
float num = settings.spawnChance;
if (settings.forceIfUnlockAll && (CL_GameManager.GetCurrentGamemode().IsCompetitive() || SettingsManager.settings.unlockAll))
{
list.Add("ForceUnlockAll");
return displayText + "\nMODIFIERS:\n" + string.Join(", ", list);
}
if (settings.useProgressionUnlock && !CL_ProgressionManager.HasProgressionUnlock(settings.unlockName))
{
list.Add("Progression✗");
}
if (settings.useFlags)
{
bool flag = false;
foreach (string item in settings.flagBlacklist)
{
if (CL_GameManager.HasActiveFlag(item, false))
{
flag = true;
break;
}
}
if (flag)
{
list.Add("FlagBlocked");
}
else if (settings.flagWhitelist != null && settings.flagWhitelist.Count > 0)
{
bool flag2 = false;
foreach (string item2 in settings.flagWhitelist)
{
if (CL_GameManager.HasActiveFlag(item2, settings.flagUsesUnlockAll))
{
flag2 = true;
break;
}
}
if (!flag2)
{
list.Add("Whitelist✗");
}
}
}
if (settings.useDifficulty)
{
float num2 = num;
float num3 = Mathf.Clamp01((CL_GameManager.currentDifficulty - settings.difficultyMin) / (settings.difficultyMax - settings.difficultyMin));
num *= num3;
if (!Mathf.Approximately(num2, num))
{
list.Add($"Difficulty x{num3:F2}");
}
}
if (settings.useStats)
{
float num2 = num;
float num4 = Mathf.Clamp01(((float)StatManager.GetStatisticInt(StatManager.sessionStats, settings.sessionStat) - settings.sessionStatMin) / (settings.sessionStatMax - settings.sessionStatMin));
float num5 = settings.sessionStatModifier.Evaluate(num4);
num *= num5;
if (!Mathf.Approximately(num2, num))
{
list.Add($"Stats x{num5:F2}");
}
}
if (settings.useHardMode)
{
bool flag3 = CL_GameManager.IsHardmode();
if (settings.hardModeOnly && !flag3)
{
list.Add("HardOnly✗");
}
if (flag3)
{
float num2 = num;
num *= settings.hardModeMult;
if (!Mathf.Approximately(num2, num))
{
list.Add($"Hard x{settings.hardModeMult:F2}");
}
}
}
if (settings.checkStatList && settings.statCheckers != null && settings.statCheckers.Count > 0)
{
list.Add($"StatChecks({settings.statCheckers.Count})");
}
if (settings.useAscent)
{
float num2 = num;
float num6 = Mathf.Clamp01((CL_GameManager.gMan.GetPlayerBestTravelDistance() - settings.ascentMin) / (settings.ascentMax - settings.ascentMin));
float num7 = settings.ascentSpawnModifier.Evaluate(num6);
num *= num7;
if (!Mathf.Approximately(num2, num))
{
list.Add($"Ascent x{num7:F2}");
}
}
if (settings.settingModules != null && settings.settingModules.Count > 0)
{
float num8 = num;
foreach (SpawnSettingModule settingModule in settings.settingModules)
{
num *= settingModule.Check();
}
if (!Mathf.Approximately(num8, num))
{
list.Add($"Modules({settings.settingModules.Count})");
}
}
if (CL_GameManager.IsHardmode() && settings.hardModeMin > 0f)
{
float num9 = num;
num = Mathf.Max(num, settings.hardModeMin);
if (!Mathf.Approximately(num9, num))
{
list.Add($"HardMin {settings.hardModeMin:P0}");
}
}
if (list.Count > 0)
{
displayText += "\nMODIFIERS:";
displayText = displayText + "\n" + string.Join(", ", list);
}
return displayText;
}
}
}
namespace SpawnStats.Patchers
{
[HarmonyPatch(typeof(UT_SpawnChance), "Start")]
public static class UT_SpawnChance_Start_Patcher
{
[HarmonyPrefix]
public static bool Prefix(UT_SpawnChance __instance)
{
Plugin.ForceSpawnAndLabel(__instance);
return false;
}
}
[HarmonyPatch(typeof(UT_SpawnChance), "Check")]
public static class UT_SpawnChance_Check_Patcher
{
[HarmonyPrefix]
public static bool Prefix(UT_SpawnChance __instance)
{
Plugin.ForceSpawnAndLabel(__instance);
return false;
}
}
[HarmonyPatch(typeof(UT_SpawnEntityByID), "Spawn")]
public static class UT_SpawnEntityByID_SpawnPatch
{
[HarmonyPrefix]
public static bool Prefix(UT_SpawnEntityByID __instance)
{
Plugin.LabelSpawnEntityByID(__instance);
__instance.SpawnCustom(__instance.idToSpawn);
return false;
}
}
[HarmonyPatch(typeof(DEN_Bloodbug), "FixedUpdate")]
public static class DEN_Bloodbug_FixedUpdate_Patcher
{
[HarmonyPrefix]
public static bool Prefix(DEN_Bloodbug __instance)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Expected O, but got Unknown
FieldInfo field = typeof(DEN_Bloodbug).GetField("rigid", BindingFlags.Instance | BindingFlags.NonPublic);
Rigidbody val = (Rigidbody)field.GetValue(__instance);
val.useGravity = false;
return false;
}
}
[HarmonyPatch(typeof(DEN_Gasbag), "FixedUpdate")]
public static class DEN_Gasbag_FixedUpdate_Patcher
{
[HarmonyPrefix]
public static bool Prefix(DEN_Gasbag __instance)
{
return false;
}
}
}
namespace SpawnStats.UI
{
public class SpawnLabelTag : MonoBehaviour
{
public GameObject label;
private void OnDestroy()
{
if ((Object)(object)label != (Object)null)
{
Object.Destroy((Object)(object)label);
}
}
}
public class ChanceLabel : MonoBehaviour
{
private Transform target;
private TextMesh textMesh;
private LineRenderer line;
private float hoverOffset = 0.5f;
private static Transform overlayRoot;
private static Transform OverlayRoot
{
get
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Expected O, but got Unknown
if ((Object)(object)overlayRoot == (Object)null)
{
GameObject val = new GameObject("SpawnChanceOverlayRoot");
overlayRoot = val.transform;
Object.DontDestroyOnLoad((Object)(object)val);
}
return overlayRoot;
}
}
public void Init(Transform targetTransform, string labelText)
{
//IL_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Expected O, but got Unknown
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
target = targetTransform;
((Component)this).transform.SetParent(OverlayRoot, false);
textMesh = ((Component)this).gameObject.AddComponent<TextMesh>();
textMesh.text = labelText;
textMesh.fontSize = 64;
textMesh.anchor = (TextAnchor)4;
textMesh.alignment = (TextAlignment)1;
textMesh.characterSize = 0.015f;
textMesh.color = Color.yellow;
line = ((Component)this).gameObject.AddComponent<LineRenderer>();
line.positionCount = 2;
line.useWorldSpace = true;
line.widthCurve = AnimationCurve.Constant(0f, 1f, 0.01f);
line.numCapVertices = 4;
Material val = new Material(Shader.Find("Sprites/Default"));
if ((Object)(object)val != (Object)null)
{
val.SetInt("_SrcBlend", 5);
val.SetInt("_DstBlend", 10);
val.SetInt("_ZWrite", 0);
val.DisableKeyword("_ALPHATEST_ON");
val.EnableKeyword("_ALPHABLEND_ON");
val.DisableKeyword("_ALPHAPREMULTIPLY_ON");
val.SetInt("_ZTest", 8);
val.renderQueue = 3001;
}
((Renderer)line).material = val;
line.startColor = new Color(1f, 0.9f, 0.2f, 1f);
line.endColor = new Color(1f, 0.9f, 0.2f, 0.6f);
}
private void LateUpdate()
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)target == (Object)null)
{
Object.Destroy((Object)(object)((Component)this).gameObject);
return;
}
Collider component = ((Component)target).GetComponent<Collider>();
Vector3 position = default(Vector3);
if ((Object)(object)component != (Object)null)
{
Bounds bounds = component.bounds;
((Vector3)(ref position))..ctor(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).max.y + hoverOffset, ((Bounds)(ref bounds)).center.z);
}
else
{
position = target.position + Vector3.up * (1.5f + hoverOffset);
}
((Component)this).transform.position = position;
if ((Object)(object)Camera.main != (Object)null)
{
Vector3 val = ((Component)Camera.main).transform.position - ((Component)this).transform.position;
if (((Vector3)(ref val)).sqrMagnitude > 0.0001f)
{
((Component)this).transform.rotation = Quaternion.LookRotation(val, Vector3.up);
((Component)this).transform.Rotate(0f, 180f, 0f);
}
}
Vector3 position2 = default(Vector3);
if ((Object)(object)component != (Object)null)
{
Bounds bounds2 = component.bounds;
((Vector3)(ref position2))..ctor(((Bounds)(ref bounds2)).center.x, ((Bounds)(ref bounds2)).min.y + 0.05f, ((Bounds)(ref bounds2)).center.z);
}
else
{
position2 = target.position;
}
if ((Object)(object)line != (Object)null)
{
line.SetPosition(0, ((Component)this).transform.position);
line.SetPosition(1, position2);
}
}
public void SetText(string t)
{
if ((Object)(object)textMesh != (Object)null)
{
textMesh.text = t;
}
}
}
public class Billboard : MonoBehaviour
{
private void LateUpdate()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)Camera.main == (Object)null))
{
((Component)this).transform.LookAt(((Component)Camera.main).transform, Vector3.up);
}
}
}
}