using System; using System.Collections; 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 Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("HuddleUp")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+32c891598c8d63aa827b48670b46b3dd6bc44eb0")] [assembly: AssemblyProduct("HuddleUp")] [assembly: AssemblyTitle("HuddleUp")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 HuddleUp { [HarmonyPatch(typeof(CharacterHeatEmission), "Update")] internal static class CharacterHeatEmission_Patch { [CompilerGenerated] private sealed class d__3 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CharacterHeatEmission heatSource; public Character target; public float coldBefore; public int sourceId; public Character giver; private float 5__1; private float 5__2; private int 5__3; private float 5__4; private float 5__5; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; 5__1 = target.refs.afflictions.GetCurrentStatus((STATUSTYPE)2); 5__2 = coldBefore - 5__1; if (5__2 <= 0.001f) { return false; } if (!HuddleUpPlugin.IsRewardActive()) { if (HuddleUpPlugin.debugMode.Value) { HuddleUpPlugin.Logger.LogInfo((object)$"[Huddle] Cold reduction detected ({5__2:F3}) but rewards not active - skipping"); } return false; } 5__3 = ((MonoBehaviourPun)target).photonView.ViewID; if (!HuddleUpPlugin.coldReductionTracker.ContainsKey(5__3)) { HuddleUpPlugin.coldReductionTracker[5__3] = new Dictionary(); } if (!HuddleUpPlugin.coldReductionTracker[5__3].ContainsKey(sourceId)) { HuddleUpPlugin.coldReductionTracker[5__3][sourceId] = 0f; } HuddleUpPlugin.coldReductionTracker[5__3][sourceId] += 5__2; 5__4 = HuddleUpPlugin.coldReductionTracker[5__3][sourceId]; if (HuddleUpPlugin.debugMode.Value) { HuddleUpPlugin.Logger.LogInfo((object)("[Huddle] " + giver.characterName + " -> " + target.characterName + ": " + $"reduced cold by {5__2:F3} (total: {5__4:F3}/{HuddleUpPlugin.requiredColdReduction.Value:F2})")); } if (5__4 >= HuddleUpPlugin.requiredColdReduction.Value) { HuddleUpPlugin.coldReductionTracker[5__3][sourceId] = 0f; 5__5 = HuddleUpPlugin.staminaReward.Value; target.AddExtraStamina(5__5); HuddleUpPlugin.Logger.LogInfo((object)($"[Huddle] {target.characterName} gained {5__5:F2} bonus stamina " + "from huddling with " + giver.characterName + "!")); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static FieldInfo _characterField; private static FieldInfo GetCharacterField() { if (_characterField == null) { _characterField = typeof(CharacterHeatEmission).GetField("character", BindingFlags.Instance | BindingFlags.NonPublic); } return _characterField; } [HarmonyPostfix] private static void Postfix(CharacterHeatEmission __instance) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) FieldInfo characterField = GetCharacterField(); if (characterField == null) { return; } object? value = characterField.GetValue(__instance); Character val = (Character)((value is Character) ? value : null); if ((Object)(object)val == (Object)null) { return; } Character localCharacter = Character.localCharacter; if ((Object)(object)localCharacter == (Object)null || (Object)(object)val == (Object)(object)localCharacter) { return; } int instanceID = ((Object)__instance).GetInstanceID(); HuddleUpPlugin.UpdateHeatSourceActivity(instanceID); float num = Vector3.Distance(((Component)__instance).transform.position, localCharacter.Center); if (num >= __instance.radius) { return; } if (!HuddleUpPlugin.IsRewardActive()) { if (HuddleUpPlugin.debugMode.Value) { HuddleUpPlugin.Logger.LogInfo((object)"[Huddle] Skipping tracking - rewards not active (daytime or night-only mode enabled)"); } } else { float currentStatus = localCharacter.refs.afflictions.GetCurrentStatus((STATUSTYPE)2); ((MonoBehaviour)HuddleUpPlugin.Instance).StartCoroutine(CheckReductionNextFrame(__instance, localCharacter, currentStatus, instanceID, val)); } } [IteratorStateMachine(typeof(d__3))] private static IEnumerator CheckReductionNextFrame(CharacterHeatEmission heatSource, Character target, float coldBefore, int sourceId, Character giver) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(0) { heatSource = heatSource, target = target, coldBefore = coldBefore, sourceId = sourceId, giver = giver }; } } [BepInPlugin("jill920.huddleup", "Huddle Up", "1.0.1")] public class HuddleUpPlugin : BaseUnityPlugin { public const string MOD_GUID = "jill920.huddleup"; public const string MOD_NAME = "Huddle Up"; public const string MOD_VERSION = "1.0.1"; public static HuddleUpPlugin Instance; public static ManualLogSource Logger; public static ConfigEntry debugMode; public static ConfigEntry requiredColdReduction; public static ConfigEntry staminaReward; public static ConfigEntry nightOnly; public static Dictionary> coldReductionTracker = new Dictionary>(); private static Dictionary _heatSourceLastActiveTime = new Dictionary(); private void Awake() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Expected O, but got Unknown Instance = this; Logger = ((BaseUnityPlugin)this).Logger; debugMode = ((BaseUnityPlugin)this).Config.Bind("Debug", "EnableDebug", false, "Enable debug logging to console"); requiredColdReduction = ((BaseUnityPlugin)this).Config.Bind("Balance", "RequiredColdReduction", 0.025f, new ConfigDescription("Amount of cold that must be removed before rewarding stamina", (AcceptableValueBase)(object)new AcceptableValueRange(0.025f, 0.1f), Array.Empty())); staminaReward = ((BaseUnityPlugin)this).Config.Bind("Balance", "StaminaReward", 0.01f, new ConfigDescription("Amount of bonus stamina to give when threshold is reached", (AcceptableValueBase)(object)new AcceptableValueRange(0.01f, 0.025f), Array.Empty())); nightOnly = ((BaseUnityPlugin)this).Config.Bind("Balance", "NightOnly", true, new ConfigDescription("Only grant stamina rewards from huddling at night (when cold is actually dangerous)", (AcceptableValueBase)(object)new AcceptableValueList(new bool[2] { true, false }), Array.Empty())); try { Harmony val = new Harmony("jill920.huddleup"); val.PatchAll(Assembly.GetExecutingAssembly()); Logger.LogInfo((object)"[Huddle Up 1.0.1] Loaded successfully!"); } catch (Exception ex) { Logger.LogError((object)("Harmony patch failed: " + ex.Message)); } } public static bool IsRewardActive() { if (!nightOnly.Value) { return true; } if ((Object)(object)DayNightManager.instance == (Object)null) { return false; } return DayNightManager.instance.isDay < 0.5f; } private void Update() { if (Time.frameCount % 3600 == 0) { CleanupInactiveSources(); } } private void CleanupInactiveSources() { float time = Time.time; List list = new List(); foreach (KeyValuePair item in _heatSourceLastActiveTime) { if (time - item.Value > 30f) { list.Add(item.Key); } } foreach (int item2 in list) { _heatSourceLastActiveTime.Remove(item2); foreach (Dictionary value in coldReductionTracker.Values) { value.Remove(item2); } } if (debugMode.Value && list.Count > 0) { Logger.LogInfo((object)$"Cleaned up {list.Count} inactive heat sources"); } } public static void UpdateHeatSourceActivity(int sourceId) { _heatSourceLastActiveTime[sourceId] = Time.time; } } }