using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace FatigueMod
{
internal static class BleedingBridge
{
private static bool _searched;
private static Type _trackerType;
private static FieldInfo _isBleedingField;
private static FieldInfo _levelField;
private static void EnsureCached()
{
if (_searched)
{
return;
}
_searched = true;
try
{
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
for (int i = 0; i < assemblies.Length; i++)
{
Type type = assemblies[i].GetType("BleedingMod.BleedingTracker");
if (!(type == null))
{
_trackerType = type;
_isBleedingField = type.GetField("s_isBleeding", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
_levelField = type.GetField("s_level", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
ManualLogSource logger = FatiguePlugin.Logger;
if (logger != null)
{
logger.LogInfo((object)"[BleedingBridge] BleedingMod detected — synergy enabled.");
}
break;
}
}
}
catch (Exception ex)
{
ManualLogSource logger2 = FatiguePlugin.Logger;
if (logger2 != null)
{
logger2.LogWarning((object)("BleedingBridge init failed: " + ex.Message));
}
}
}
public static int GetBleedLevel()
{
EnsureCached();
if (_trackerType == null || _isBleedingField == null || _levelField == null)
{
return 0;
}
try
{
if (!(bool)_isBleedingField.GetValue(null))
{
return 0;
}
object value = _levelField.GetValue(null);
return (value != null) ? ((int)value) : 0;
}
catch
{
return 0;
}
}
}
internal static class Bugle_Patch
{
private static Vector3 GetBuglePos(Component __instance)
{
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Expected O, but got Unknown
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Expected O, but got Unknown
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Expected O, but got Unknown
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
try
{
FieldInfo field = ((object)__instance).GetType().GetField("item", BindingFlags.Instance | BindingFlags.NonPublic);
if (field != null)
{
object value = field.GetValue(__instance);
Item val = (Item)((value is Item) ? value : null);
if ((Object)(((Object)(object)val != (Object)null) ? val.holderCharacter : null) != (Object)null)
{
return ((Component)val.holderCharacter).transform.position;
}
}
}
catch
{
}
Character componentInParent = __instance.GetComponentInParent<Character>();
if (!((Object)componentInParent != (Object)null))
{
return __instance.transform.position;
}
return ((Component)componentInParent).transform.position;
}
public static void OnStart(Component __instance)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
try
{
Character localCharacter = Character.localCharacter;
if (!((Object)localCharacter == (Object)null) && !(Vector3.Distance(((Component)localCharacter).transform.position, GetBuglePos(__instance)) > 30f))
{
FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
if (!((Object)component == (Object)null))
{
component.bugledUntil = Time.time + 60f;
}
}
}
catch
{
}
}
public static void OnEnd(Component __instance)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
try
{
Character localCharacter = Character.localCharacter;
if (!((Object)localCharacter == (Object)null))
{
FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
if ((Object)component != (Object)null)
{
component.bugledUntil = -1f;
}
}
}
catch
{
}
}
}
[HarmonyPatch(typeof(Character), "Awake")]
internal static class Character_Awake_Patch
{
[HarmonyPostfix]
private static void Postfix(Character __instance)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Expected O, but got Unknown
if ((Object)((Component)__instance).GetComponent<FatigueTracker>() == (Object)null)
{
((Component)__instance).gameObject.AddComponent<FatigueTracker>();
}
}
}
[BepInPlugin("com.tambistudios.fatigue", "Fatigue", "1.3.1")]
public class FatiguePlugin : BaseUnityPlugin
{
public const string MOD_GUID = "com.tambistudios.fatigue";
public const string MOD_NAME = "Fatigue";
public const string MOD_VERSION = "1.3.1";
public static FatiguePlugin Instance;
public static ManualLogSource Logger;
public static ConfigEntry<bool> debugMode;
public static ConfigEntry<float> cfgEnergyMax;
public static ConfigEntry<float> cfgCostClimbUp;
public static ConfigEntry<float> cfgCostClimbSide;
public static ConfigEntry<float> cfgCostClimbDown;
public static ConfigEntry<float> cfgCostClimbHang;
public static ConfigEntry<float> cfgCostRopeMove;
public static ConfigEntry<float> cfgCostRopeHang;
public static ConfigEntry<float> cfgCostVineMove;
public static ConfigEntry<float> cfgCostVineHang;
public static ConfigEntry<float> cfgClimbJumpCost;
public static ConfigEntry<float> cfgEnergyRegenGround;
public static ConfigEntry<float> cfgEnergyRegenAir;
public static ConfigEntry<float> cfgCampfireEnergyRegen;
public static ConfigEntry<bool> cfgEnableBleedSynergy;
public static ConfigEntry<float> cfgBleedSynergyMult;
public const float ENERGY_MAX = 6.5f;
public const float CLIMBJUMP_ENERGY_COST = 1.5f;
public const float CLIMBJUMP_WINDOW = 0.3f;
public const float COST_CLIMB_UP = 1f;
public const float COST_CLIMB_SIDE = 1.3f;
public const float COST_CLIMB_DOWN = 0.5f;
public const float COST_CLIMB_HANG = 0.1f;
public const float GROUND_REST_DELAY = 1.5f;
public const float ENERGY_REGEN_PER_SEC = 1f;
public const float ENERGY_REGEN_AIR = 0.4f;
public const float COST_ROPE_MOVE = 0.3f;
public const float COST_ROPE_HANG = 0.1f;
public const float COST_VINE_MOVE = 0.9f;
public const float COST_VINE_HANG = 0.1f;
public const float DROWSY_GAIN_ACTIVE = 0.05f;
public const float DROWSY_GAIN_HANG = 0.025f;
public const float BUGLE_RANGE = 30f;
public const float BUGLE_DROWSY_REDUCTION = 0.05f;
public const float BUGLE_DURATION = 2f;
public const float CAMPFIRE_DROWSY_MULTIPLIER = 4f;
public const float VERTICAL_SPEED_THRESHOLD = 0.5f;
public const float HANG_SPEED_THRESHOLD = 0.3f;
internal static readonly Color EnergyBarColor = new Color(0.25f, 0.75f, 0.25f, 1f);
internal static readonly Color EnergyBarColorLight = new Color(0.55f, 0.98f, 0.55f, 1f);
internal static readonly Color EnergyBarBgColor = new Color(0.04f, 0.18f, 0.04f, 0.85f);
private RectTransform _fillRect;
private Image _fillImage;
private StaminaBar _staminaBarRef;
private FieldInfo _fullBarField;
private bool _barCreated;
private float _prevEnergy = -1f;
private float _pulseTimer;
private float _displayedWidth = -1f;
private void Awake()
{
//IL_024e: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Expected O, but got Unknown
//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
//IL_02f1: Expected O, but got Unknown
//IL_031f: Unknown result type (might be due to invalid IL or missing references)
//IL_032c: Expected O, but got Unknown
Instance = this;
Logger = ((BaseUnityPlugin)this).Logger;
debugMode = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "EnableDebugKeys", false, "Enables on-screen debug HUD showing energy budget and movement state.");
cfgEnergyMax = ((BaseUnityPlugin)this).Config.Bind<float>("Budget", "EnergyMax", 6.5f, "Total energy budget you start every climb with.");
cfgCostClimbUp = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "ClimbUpPerSec", 0.48f, "Energy drained per second while climbing up. (1.6x easier)");
cfgCostClimbSide = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "ClimbSidePerSec", 0.63f, "Energy drained per second while climbing sideways.");
cfgCostClimbDown = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "ClimbDownPerSec", 0.24f, "Energy drained per second while climbing down.");
cfgCostClimbHang = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "ClimbHangPerSec", 0.05f, "Energy drained per second while hanging on a wall.");
cfgCostRopeMove = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "RopeMovePerSec", 0.14f, "Energy drained per second while moving on a rope.");
cfgCostRopeHang = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "RopeHangPerSec", 0.05f, "Energy drained per second while hanging on a rope.");
cfgCostVineMove = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "VineMovePerSec", 0.43f, "Energy drained per second while moving on a vine.");
cfgCostVineHang = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "VineHangPerSec", 0.05f, "Energy drained per second while hanging on a vine.");
cfgClimbJumpCost = ((BaseUnityPlugin)this).Config.Bind<float>("Costs", "ClimbJumpBurst", 0.72f, "Instant energy cost per climb-jump.");
cfgEnergyRegenGround = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "EnergyRegenOnGround", 3.2f, "Energy regenerated per second while on the ground.");
cfgEnergyRegenAir = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "EnergyRegenInAir", 1.28f, "Passive energy regeneration per second in air.");
cfgCampfireEnergyRegen = ((BaseUnityPlugin)this).Config.Bind<float>("Regen", "CampfireEnergyRegen", 4.8f, "Extra energy regenerated per second inside a campfire's zone.");
cfgEnableBleedSynergy = ((BaseUnityPlugin)this).Config.Bind<bool>("Synergy", "EnableBleedSynergy", true, "Heavy bleeding (from Tambi_Studios-Bleeding) increases energy drain. Requires the Bleeding mod installed.");
cfgBleedSynergyMult = ((BaseUnityPlugin)this).Config.Bind<float>("Synergy", "BleedDrainMultiplier", 1.5f, "Multiplier applied to energy drain while bleeding heavily. 1.5 = +50% drain.");
try
{
Harmony val = new Harmony("com.tambistudios.fatigue");
val.PatchAll();
Type type = null;
Type[] types = typeof(Character).Assembly.GetTypes();
foreach (Type type2 in types)
{
if (type2.Name == "BugleSFX")
{
type = type2;
break;
}
}
if (type != null)
{
MethodInfo methodInfo = AccessTools.Method(type, "RPC_StartToot", (Type[])null, (Type[])null);
MethodInfo methodInfo2 = AccessTools.Method(type, "RPC_EndToot", (Type[])null, (Type[])null);
if (methodInfo != null)
{
val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Bugle_Patch), "OnStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Logger.LogInfo((object)"Bugle: patched RPC_StartToot");
}
if (methodInfo2 != null)
{
val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Bugle_Patch), "OnEnd", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
Logger.LogInfo((object)"Bugle: patched RPC_EndToot");
}
if (methodInfo == null && methodInfo2 == null)
{
Logger.LogWarning((object)"BugleSFX found but no matching methods.");
}
}
else
{
Logger.LogWarning((object)"BugleSFX class not found — bugle relief disabled.");
}
Logger.LogInfo((object)"[Fatigue 1.3.1] Loaded.");
}
catch (Exception arg)
{
Logger.LogError((object)$"Harmony patch failed: {arg}");
}
}
public static float GetEtcDamageMultiplier()
{
try
{
return Ascents.etcDamageMultiplier;
}
catch
{
return 1f;
}
}
public static bool IsFatigueDisabled()
{
return TambiAfflictionOption.GetValue("Fatigue") == 0;
}
public static bool IsInLobby()
{
try
{
return !GameHandler.IsInGameplayScene;
}
catch
{
return false;
}
}
public static float GetCostMultiplier()
{
return TambiAfflictionOption.GetValue("Fatigue") switch
{
0 => 0f,
1 => 1f,
2 => 1.5f,
3 => 2f,
_ => 1.5f,
};
}
private void Update()
{
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0059: Expected O, but got Unknown
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Expected O, but got Unknown
if (_barCreated && (Object)_fillRect == (Object)null)
{
_barCreated = false;
_staminaBarRef = null;
_displayedWidth = -1f;
}
Character localCharacter = Character.localCharacter;
if ((Object)localCharacter != (Object)null && (Object)((Component)localCharacter).GetComponent<FatigueTracker>() == (Object)null)
{
((Component)localCharacter).gameObject.AddComponent<FatigueTracker>();
Logger.LogInfo((object)"FatigueTracker attached (fallback).");
}
if (!_barCreated && (Object)localCharacter != (Object)null)
{
TryCreateEnergyBar();
}
}
private void LateUpdate()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Expected O, but got Unknown
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Expected O, but got Unknown
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: Expected O, but got Unknown
//IL_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Expected O, but got Unknown
//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
//IL_0112: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_0197: Unknown result type (might be due to invalid IL or missing references)
//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
if (!_barCreated || (Object)_fillRect == (Object)null || (Object)_staminaBarRef == (Object)null)
{
return;
}
Character localCharacter = Character.localCharacter;
if ((Object)localCharacter == (Object)null)
{
return;
}
FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
if (!((Object)component == (Object)null))
{
float energy = component.energy;
float num = energy / ((cfgEnergyMax != null) ? cfgEnergyMax.Value : 6.5f);
object obj = _fullBarField?.GetValue(_staminaBarRef);
RectTransform val = (RectTransform)((obj is RectTransform) ? obj : null);
float num2 = (((Object)val != (Object)null) ? (val.sizeDelta.x * 0.9f) : 200f) * num;
if (_displayedWidth < 0f)
{
_displayedWidth = num2;
}
_displayedWidth = Mathf.Lerp(_displayedWidth, num2, Time.deltaTime * 5f);
Vector2 sizeDelta = _fillRect.sizeDelta;
sizeDelta.x = _displayedWidth;
_fillRect.sizeDelta = sizeDelta;
bool num3 = _prevEnergy >= 0f && energy < _prevEnergy - 0.001f;
_prevEnergy = energy;
if (num3)
{
_pulseTimer += Time.deltaTime;
float num4 = (Mathf.Sin(_pulseTimer * 9f) + 1f) * 0.5f;
((Graphic)_fillImage).color = Color.Lerp(EnergyBarColor, EnergyBarColorLight, num4 * 0.45f);
}
else
{
_pulseTimer = 0f;
((Graphic)_fillImage).color = EnergyBarColor;
}
}
}
private void TryCreateEnergyBar()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: 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_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Unknown result type (might be due to invalid IL or missing references)
//IL_015e: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01a0: Expected O, but got Unknown
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0201: Unknown result type (might be due to invalid IL or missing references)
//IL_0215: Unknown result type (might be due to invalid IL or missing references)
//IL_0232: Unknown result type (might be due to invalid IL or missing references)
//IL_0264: Unknown result type (might be due to invalid IL or missing references)
//IL_0269: Unknown result type (might be due to invalid IL or missing references)
//IL_0276: Unknown result type (might be due to invalid IL or missing references)
//IL_027e: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Unknown result type (might be due to invalid IL or missing references)
//IL_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_02c0: Unknown result type (might be due to invalid IL or missing references)
//IL_02d1: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
try
{
StaminaBar val = Object.FindObjectOfType<StaminaBar>();
if (!((Object)val == (Object)null))
{
_fullBarField = AccessTools.Field(typeof(StaminaBar), "fullBar");
object obj = _fullBarField?.GetValue(val);
RectTransform val2 = (RectTransform)((obj is RectTransform) ? obj : null);
if ((Object)val2 == (Object)null)
{
Logger.LogWarning((object)"StaminaBar.fullBar not found");
return;
}
Transform parent = ((Component)val2).transform.parent;
float x = val2.sizeDelta.x;
float num = x * 0.9f;
float num2 = val2.sizeDelta.y / 3.23f;
float num3 = val2.anchoredPosition.x - val2.pivot.x * x;
float num4 = val2.anchoredPosition.y + val2.sizeDelta.y * 0.5f + num2 * 0.5f + 10f;
Sprite sprite = MakeRoundedSprite(12, 4);
Sprite sprite2 = MakeRingSprite(28, 12, 4);
GameObject val3 = new GameObject("FatigueEnergyBg");
val3.transform.SetParent(parent, false);
RectTransform obj2 = val3.AddComponent<RectTransform>();
obj2.anchorMin = val2.anchorMin;
obj2.anchorMax = val2.anchorMax;
obj2.pivot = new Vector2(0f, 0.5f);
obj2.sizeDelta = new Vector2(num, num2);
obj2.anchoredPosition = new Vector2(num3, num4);
Image obj3 = val3.AddComponent<Image>();
((Graphic)obj3).color = EnergyBarBgColor;
obj3.sprite = sprite;
obj3.type = (Type)1;
GameObject val4 = new GameObject("FatigueEnergyFill");
val4.transform.SetParent(parent, false);
_fillRect = val4.AddComponent<RectTransform>();
_fillRect.anchorMin = val2.anchorMin;
_fillRect.anchorMax = val2.anchorMax;
_fillRect.pivot = new Vector2(0f, 0.5f);
_fillRect.sizeDelta = new Vector2(num, num2);
_fillRect.anchoredPosition = new Vector2(num3, num4);
_fillImage = val4.AddComponent<Image>();
((Graphic)_fillImage).color = EnergyBarColor;
_fillImage.sprite = sprite;
_fillImage.type = (Type)1;
float num5 = num2 * 0.26f;
GameObject val5 = new GameObject("FatigueEnergyOutline");
val5.transform.SetParent(parent, false);
RectTransform obj4 = val5.AddComponent<RectTransform>();
obj4.anchorMin = val2.anchorMin;
obj4.anchorMax = val2.anchorMax;
obj4.pivot = new Vector2(0f, 0.5f);
obj4.sizeDelta = new Vector2(num + num5 * 2f, num2 + num5 * 2f);
obj4.anchoredPosition = new Vector2(num3 - num5, num4);
Image obj5 = val5.AddComponent<Image>();
((Graphic)obj5).color = new Color(1f, 1f, 1f, 0.85f);
obj5.sprite = sprite2;
obj5.type = (Type)1;
_staminaBarRef = val;
_barCreated = true;
Logger.LogInfo((object)$"FatigueEnergyBar created. pos=({num3:F0},{num4:F0})");
}
}
catch (Exception ex)
{
Logger.LogWarning((object)("Energy bar setup failed: " + ex.Message));
}
}
private static Sprite MakeRingSprite(int size, int radius, int ring)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Expected O, but got Unknown
//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
//IL_00df: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: 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)
Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
Color[] array = (Color[])(object)new Color[size * size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
bool flag = InRoundedRect(j, i, size, size, radius);
bool flag2 = j >= ring && i >= ring && j < size - ring && i < size - ring && InRoundedRect(j - ring, i - ring, size - ring * 2, size - ring * 2, Math.Max(0, radius - ring));
array[i * size + j] = ((flag && !flag2) ? Color.white : Color.clear);
}
}
val.SetPixels(array);
val.Apply();
return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)radius, (float)radius, (float)radius, (float)radius));
}
private static Sprite MakeRoundedSprite(int size, int radius)
{
//IL_0004: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Expected O, but got Unknown
//IL_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
Texture2D val = new Texture2D(size, size, (TextureFormat)4, false);
((Texture)val).filterMode = (FilterMode)1;
((Texture)val).wrapMode = (TextureWrapMode)1;
Color[] array = (Color[])(object)new Color[size * size];
for (int i = 0; i < size; i++)
{
for (int j = 0; j < size; j++)
{
array[i * size + j] = (InRoundedRect(j, i, size, size, radius) ? Color.white : Color.clear);
}
}
val.SetPixels(array);
val.Apply();
return Sprite.Create(val, new Rect(0f, 0f, (float)size, (float)size), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0, new Vector4((float)radius, (float)radius, (float)radius, (float)radius));
}
private static bool InRoundedRect(int x, int y, int w, int h, int r)
{
if (x >= r && x <= w - 1 - r)
{
return true;
}
if (y >= r && y <= h - 1 - r)
{
return true;
}
int num = ((x < r) ? r : (w - 1 - r));
int num2 = ((y < r) ? r : (h - 1 - r));
float num3 = x - num;
float num4 = y - num2;
return num3 * num3 + num4 * num4 <= (float)r * (float)r;
}
private void OnGUI()
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Expected O, but got Unknown
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0042: Expected O, but got Unknown
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
if (!debugMode.Value)
{
return;
}
Character localCharacter = Character.localCharacter;
if (!((Object)localCharacter == (Object)null))
{
FatigueTracker component = ((Component)localCharacter).GetComponent<FatigueTracker>();
if (!((Object)component == (Object)null))
{
GUIStyle val = new GUIStyle();
val.fontSize = 18;
val.normal.textColor = Color.white;
float etcDamageMultiplier = GetEtcDamageMultiplier();
float costMultiplier = GetCostMultiplier();
string text = (IsFatigueDisabled() ? "DISABLED" : $"x{costMultiplier:F1}");
float currentStatus = localCharacter.refs.afflictions.GetCurrentStatus((STATUSTYPE)6);
float lastVerticalVelocity = component.lastVerticalVelocity;
float lastSpeed = component.lastSpeed;
GUI.Label(new Rect(20f, 200f, 700f, 30f), $"Energy: {component.energy:F2}/{((cfgEnergyMax != null) ? cfgEnergyMax.Value : 6.5f):F1} State: {component.lastState} etcMult: {etcDamageMultiplier:F2} ({text})", val);
GUI.Label(new Rect(20f, 222f, 700f, 30f), $"Cost: {component.lastCostPerSec:F2}/sec Vy: {lastVerticalVelocity:F2} |V|: {lastSpeed:F2}", val);
GUI.Label(new Rect(20f, 244f, 700f, 30f), $"Climb: {component.isClimbing} Rope: {component.isRopeClimbing} Vine: {component.isVineClimbing} Ground: {component.isGrounded} ({component.groundTimer:F1}s) sinceClimbJump: {component.sinceClimbJump:F2}", val);
GUI.Label(new Rect(20f, 266f, 700f, 30f), string.Format("Drowsy: {0:F3} Hang: {1} Campfire: {2} Bugle: {3}", currentStatus, component.lastIsHang, component.nearCampfire ? "YES (x4)" : "no", (component.bugledUntil > Time.time) ? $"{component.bugledUntil - Time.time:F1}s" : "no"), val);
}
}
}
}
public class FatigueTracker : MonoBehaviour
{
public Character character;
public float energy = 6.5f;
public string lastState = "idle";
public float lastCostPerSec;
public float lastVerticalVelocity;
public float lastSpeed;
public bool isGrounded;
public bool isClimbing;
public bool isRopeClimbing;
public bool isVineClimbing;
public float sinceClimbJump = 999f;
public bool nearCampfire;
public bool lastIsHang;
public float bugledUntil = -1f;
public float groundTimer;
private const float VERTICAL_SPEED_THRESHOLD = 0.5f;
private const float HANG_SPEED_THRESHOLD = 0.3f;
private const float GROUND_REST_DELAY = 1.5f;
private const float CLIMBJUMP_WINDOW = 0.3f;
private const float DROWSY_GAIN_ACTIVE = 0.05f;
private const float DROWSY_GAIN_HANG = 0.025f;
private float _lastProcessedClimbJump = -1f;
private Rigidbody _cachedRb;
private static FieldInfo _isGroundedField;
private static FieldInfo _isClimbingField;
private static FieldInfo _isRopeClimbingField;
private static FieldInfo _isVineClimbingField;
private static FieldInfo _sinceClimbJumpField;
private static FieldInfo _drowsyReductionPerSecondField;
private static bool _fieldsSearched;
private Rigidbody GetRb()
{
if ((Object)(object)_cachedRb != (Object)null)
{
return _cachedRb;
}
if ((Object)(object)character == (Object)null)
{
return null;
}
_cachedRb = ((Component)character).GetComponentInChildren<Rigidbody>();
return _cachedRb;
}
private static void EnsureFields(Character c)
{
if (_fieldsSearched)
{
return;
}
_fieldsSearched = true;
if (!((Object)(object)c == (Object)null) && !((Object)(object)c.data == (Object)null))
{
Type type = ((object)c.data).GetType();
BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public;
_isGroundedField = type.GetField("isGrounded", bindingAttr);
_isClimbingField = type.GetField("isClimbing", bindingAttr);
_isRopeClimbingField = type.GetField("isRopeClimbing", bindingAttr);
_isVineClimbingField = type.GetField("isVineClimbing", bindingAttr);
_sinceClimbJumpField = type.GetField("sinceClimbJump", bindingAttr);
if (c.refs != null && (Object)(object)c.refs.afflictions != (Object)null)
{
Type type2 = ((object)c.refs.afflictions).GetType();
_drowsyReductionPerSecondField = type2.GetField("drowsyReductionPerSecond", bindingAttr) ?? type2.GetField("drowsyReductionPerSecond", BindingFlags.Instance | BindingFlags.NonPublic);
}
FatiguePlugin.Logger.LogInfo((object)($"Fields: grounded={_isGroundedField != null} climb={_isClimbingField != null} " + $"rope={_isRopeClimbingField != null} vine={_isVineClimbingField != null} " + $"sinceClimbJump={_sinceClimbJumpField != null} " + $"drowsyReduction={_drowsyReductionPerSecondField != null}"));
}
}
private static bool GetBool(FieldInfo f, object obj)
{
if (f == null || obj == null)
{
return false;
}
try
{
return (bool)f.GetValue(obj);
}
catch
{
return false;
}
}
private static float GetFloat(FieldInfo f, object obj, float fallback = 0f)
{
if (f == null || obj == null)
{
return fallback;
}
try
{
return (float)f.GetValue(obj);
}
catch
{
return fallback;
}
}
private void Awake()
{
character = ((Component)this).GetComponent<Character>();
}
private void Update()
{
//IL_02df: Unknown result type (might be due to invalid IL or missing references)
//IL_02f0: Unknown result type (might be due to invalid IL or missing references)
//IL_02f5: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)character == (Object)null || !character.IsLocal || (Object)(object)character.data == (Object)null)
{
return;
}
EnsureFields(character);
isGrounded = GetBool(_isGroundedField, character.data);
isClimbing = GetBool(_isClimbingField, character.data);
isRopeClimbing = GetBool(_isRopeClimbingField, character.data);
isVineClimbing = GetBool(_isVineClimbingField, character.data);
sinceClimbJump = GetFloat(_sinceClimbJumpField, character.data, 999f);
nearCampfire = false;
if (character.refs != null && (Object)(object)character.refs.afflictions != (Object)null)
{
try
{
nearCampfire = !character.refs.afflictions.canGetHungry;
}
catch
{
nearCampfire = false;
}
}
float num = ((FatiguePlugin.cfgEnergyMax != null) ? FatiguePlugin.cfgEnergyMax.Value : 6.5f);
int num2;
int num3;
if (FatiguePlugin.cfgEnableBleedSynergy != null)
{
num2 = (FatiguePlugin.cfgEnableBleedSynergy.Value ? 1 : 0);
if (num2 == 0)
{
num3 = 0;
goto IL_0154;
}
}
else
{
num2 = 1;
}
num3 = BleedingBridge.GetBleedLevel();
goto IL_0154;
IL_0154:
int num4 = num3;
float num5 = 1f;
if (num2 != 0 && num4 >= 3)
{
num5 = ((FatiguePlugin.cfgBleedSynergyMult != null) ? FatiguePlugin.cfgBleedSynergyMult.Value : 1.5f);
}
if (nearCampfire && character.refs != null && (Object)(object)character.refs.afflictions != (Object)null)
{
float num6 = GetFloat(_drowsyReductionPerSecondField, character.refs.afflictions, 0.01f) * 3f;
if (num6 > 0f && character.refs.afflictions.GetCurrentStatus((STATUSTYPE)6) > 0f)
{
character.refs.afflictions.SubtractStatus((STATUSTYPE)6, num6 * Time.deltaTime, false, false);
}
float num7 = ((FatiguePlugin.cfgCampfireEnergyRegen != null) ? FatiguePlugin.cfgCampfireEnergyRegen.Value : 1.5f);
if (num7 > 0.001f)
{
energy = Mathf.Min(num, energy + num7 * Time.deltaTime);
}
}
if (Time.time < bugledUntil && character.refs != null && (Object)(object)character.refs.afflictions != (Object)null && character.refs.afflictions.GetCurrentStatus((STATUSTYPE)6) > 0f)
{
character.refs.afflictions.SubtractStatus((STATUSTYPE)6, 0.05f * Time.deltaTime, false, false);
}
Rigidbody rb = GetRb();
if ((Object)(object)rb != (Object)null)
{
lastVerticalVelocity = rb.linearVelocity.y;
Vector3 linearVelocity = rb.linearVelocity;
lastSpeed = ((Vector3)(ref linearVelocity)).magnitude;
}
if (FatiguePlugin.IsFatigueDisabled())
{
lastState = "disabled";
lastCostPerSec = 0f;
energy = num;
return;
}
if (FatiguePlugin.IsInLobby())
{
lastState = "lobby";
lastCostPerSec = 0f;
energy = num;
return;
}
if (SpiderCheck.IsGrabbedBySpider(character))
{
lastState = "grabbed";
lastCostPerSec = 0f;
return;
}
if (isGrounded)
{
groundTimer += Time.deltaTime;
lastCostPerSec = 0f;
if (groundTimer >= 1.5f)
{
float num8 = ((FatiguePlugin.cfgEnergyRegenGround != null) ? FatiguePlugin.cfgEnergyRegenGround.Value : 1f);
energy = Mathf.Min(num, energy + num8 * Time.deltaTime);
}
lastState = ((energy >= num - 0.001f) ? "ground" : $"resting ({groundTimer:F1}s)");
return;
}
groundTimer = 0f;
float num9 = CalculateCost(num);
lastCostPerSec = num9 * num5;
if (num9 > 0f)
{
float costMultiplier = FatiguePlugin.GetCostMultiplier();
energy = Mathf.Max(0f, energy - num9 * costMultiplier * num5 * Time.deltaTime);
}
if (isClimbing && sinceClimbJump < 0.3f)
{
if (_lastProcessedClimbJump < 0f || sinceClimbJump < _lastProcessedClimbJump)
{
float num10 = ((FatiguePlugin.cfgClimbJumpCost != null) ? FatiguePlugin.cfgClimbJumpCost.Value : 1.5f);
energy = Mathf.Max(0f, energy - num10);
lastState = "CLIMBJUMP!";
FatiguePlugin.Logger.LogInfo((object)$"ClimbJump detected: -{num10} energy");
}
_lastProcessedClimbJump = sinceClimbJump;
}
else
{
_lastProcessedClimbJump = -1f;
}
if (energy <= 0.001f)
{
float num11 = (lastIsHang ? 0.025f : 0.05f) * Time.deltaTime;
if (num11 > 0f)
{
character.refs.afflictions.AddStatus((STATUSTYPE)6, num11, false, true, true, false);
}
}
}
private float CalculateCost(float energyMax)
{
if (isClimbing)
{
if (lastSpeed < 0.3f)
{
lastIsHang = true;
lastState = "climb-hang";
if (FatiguePlugin.cfgCostClimbHang == null)
{
return 0.1f;
}
return FatiguePlugin.cfgCostClimbHang.Value;
}
if (lastVerticalVelocity > 0.5f)
{
lastIsHang = false;
lastState = "climb-up";
if (FatiguePlugin.cfgCostClimbUp == null)
{
return 1f;
}
return FatiguePlugin.cfgCostClimbUp.Value;
}
if (lastVerticalVelocity < -0.5f)
{
lastIsHang = false;
lastState = "climb-down";
if (FatiguePlugin.cfgCostClimbDown == null)
{
return 0.5f;
}
return FatiguePlugin.cfgCostClimbDown.Value;
}
lastIsHang = false;
lastState = "climb-side";
if (FatiguePlugin.cfgCostClimbSide == null)
{
return 1.3f;
}
return FatiguePlugin.cfgCostClimbSide.Value;
}
if (isRopeClimbing)
{
if (lastSpeed < 0.3f)
{
lastIsHang = true;
lastState = "rope-hang";
if (FatiguePlugin.cfgCostRopeHang == null)
{
return 0.1f;
}
return FatiguePlugin.cfgCostRopeHang.Value;
}
lastIsHang = false;
lastState = "rope-move";
if (FatiguePlugin.cfgCostRopeMove == null)
{
return 0.3f;
}
return FatiguePlugin.cfgCostRopeMove.Value;
}
if (isVineClimbing)
{
if (lastSpeed < 0.3f)
{
lastIsHang = true;
lastState = "vine-hang";
if (FatiguePlugin.cfgCostVineHang == null)
{
return 0.1f;
}
return FatiguePlugin.cfgCostVineHang.Value;
}
lastIsHang = false;
lastState = "vine-move";
if (FatiguePlugin.cfgCostVineMove == null)
{
return 0.9f;
}
return FatiguePlugin.cfgCostVineMove.Value;
}
lastIsHang = false;
lastState = "air";
float num = ((FatiguePlugin.cfgEnergyRegenAir != null) ? FatiguePlugin.cfgEnergyRegenAir.Value : 0.4f);
energy = Mathf.Min(energyMax, energy + num * Time.deltaTime);
return 0f;
}
}
internal static class SpiderCheck
{
private const float WEB_THRESHOLD = 0.025f;
public static bool IsGrabbedBySpider(Character c)
{
if ((Object)(object)c == (Object)null || c.refs == null || (Object)(object)c.refs.afflictions == (Object)null)
{
return false;
}
try
{
return c.refs.afflictions.GetCurrentStatus((STATUSTYPE)11) > 0.025f;
}
catch
{
return false;
}
}
}
public class TambiAfflictionOption : CustomOptionBase
{
private static readonly Dictionary<string, int> _values = new Dictionary<string, int>();
public string modName;
public string[] labels = new string[4] { "OFF", "LOW", "NORM", "HIGH" };
public int defaultValue = 2;
public Button button;
public LocalizedText buttonText;
public LocalizedText label;
public Image buttonImage;
public Color offColor;
public Color defaultColor;
public Color adjustedColor;
public static int GetValue(string mod)
{
if (!_values.TryGetValue(mod, out var value))
{
return 2;
}
return value;
}
public static void SetValue(string mod, int value)
{
_values[mod] = value;
}
private void OnEnable()
{
if (!_values.ContainsKey(modName))
{
_values[modName] = defaultValue;
}
Refresh();
}
public override void OnClick()
{
((CustomOptionBase)this).OnClick();
int value = GetValue(modName);
value = (value + 1) % labels.Length;
_values[modName] = value;
Refresh();
}
public override void RestoreDefault()
{
_values[modName] = defaultValue;
Refresh();
}
private void Refresh()
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
int value = GetValue(modName);
if ((Object)(object)buttonText != (Object)null)
{
buttonText.autoSet = true;
buttonText.SetIndex(labels[Mathf.Clamp(value, 0, labels.Length - 1)]);
}
if ((Object)(object)buttonImage != (Object)null)
{
((Graphic)buttonImage).color = ((value == defaultValue) ? defaultColor : adjustedColor);
}
if ((Object)(object)label != (Object)null)
{
label.SetText(modName);
}
}
}
[HarmonyPatch(typeof(CustomOptionsWindow), "Initialize")]
internal static class TambiOptionInjector
{
private const string MOD_NAME = "Fatigue";
private static bool _injected;
[HarmonyPostfix]
private static void Postfix(CustomOptionsWindow __instance)
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Invalid comparison between Unknown and I4
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Invalid comparison between Unknown and I4
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_0173: Unknown result type (might be due to invalid IL or missing references)
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: 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_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_0187: Unknown result type (might be due to invalid IL or missing references)
//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
//IL_01d3: Expected O, but got Unknown
if (_injected)
{
return;
}
try
{
CustomOptionMulti[] componentsInChildren = ((Component)__instance).GetComponentsInChildren<CustomOptionMulti>(true);
CustomOptionMulti val = null;
CustomOptionMulti[] array = componentsInChildren;
foreach (CustomOptionMulti val2 in array)
{
if ((int)val2.settingType == 300 || (int)val2.settingType == 400)
{
val = val2;
break;
}
}
if ((Object)(object)val == (Object)null)
{
return;
}
GameObject val3 = Object.Instantiate<GameObject>(((Component)val).gameObject, ((Component)val).transform.parent);
((Object)val3).name = "TambiOption_Fatigue";
CustomOptionMulti component = val3.GetComponent<CustomOptionMulti>();
if ((Object)(object)component == (Object)null)
{
Object.Destroy((Object)(object)val3);
return;
}
Button button = component.button;
LocalizedText buttonText = component.buttonText;
LocalizedText label = component.label;
Image buttonImage = component.buttonImage;
Color offColor = component.offColor;
Color defaultColor = component.defaultColor;
Color adjustedColor = component.adjustedColor;
string[] labels = component.labels;
MonoBehaviour[] componentsInChildren2 = val3.GetComponentsInChildren<MonoBehaviour>(true);
foreach (MonoBehaviour val4 in componentsInChildren2)
{
if (!((Object)(object)val4 == (Object)null))
{
if (val4 is EventTrigger)
{
Object.DestroyImmediate((Object)(object)val4);
}
else if (val4 is CustomOptionBase)
{
Object.DestroyImmediate((Object)(object)val4);
}
else if (val4 is CustomOptionTooltip)
{
Object.DestroyImmediate((Object)(object)val4);
}
}
}
TambiAfflictionOption tambiAfflictionOption = val3.AddComponent<TambiAfflictionOption>();
tambiAfflictionOption.modName = "Fatigue";
tambiAfflictionOption.button = button;
tambiAfflictionOption.buttonText = buttonText;
tambiAfflictionOption.label = label;
tambiAfflictionOption.buttonImage = buttonImage;
tambiAfflictionOption.offColor = offColor;
tambiAfflictionOption.defaultColor = defaultColor;
tambiAfflictionOption.adjustedColor = adjustedColor;
tambiAfflictionOption.defaultValue = 2;
if (labels != null && labels.Length != 0)
{
tambiAfflictionOption.labels = labels;
}
if ((Object)(object)button != (Object)null)
{
((UnityEventBase)button.onClick).RemoveAllListeners();
((UnityEvent)button.onClick).AddListener(new UnityAction(((CustomOptionBase)tambiAfflictionOption).OnClick));
}
if ((Object)(object)label != (Object)null)
{
label.autoSet = false;
label.index = "";
label.SetText("Fatigue");
}
val3.SetActive(true);
((Component)tambiAfflictionOption).SendMessage("Refresh", (SendMessageOptions)1);
_injected = true;
ManualLogSource logger = FatiguePlugin.Logger;
if (logger != null)
{
logger.LogInfo((object)"[TambiOption] Fatigue option injected into Custom Expedition menu.");
}
}
catch (Exception ex)
{
ManualLogSource logger2 = FatiguePlugin.Logger;
if (logger2 != null)
{
logger2.LogWarning((object)("[TambiOption] Injection failed: " + ex.Message));
}
}
}
}
}