Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ComfortHelper v1.0.0
ComfortHelper.dll
Decompiled 2 days agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Koendertjh.Shared; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ComfortHelper")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a45c570d17c512d77d75166ff42bc1dee72ef243")] [assembly: AssemblyProduct("ComfortHelper")] [assembly: AssemblyTitle("ComfortHelper")] [assembly: AssemblyVersion("1.0.0.0")] [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 Koendertjh.Shared { internal static class AchievementStats { private static readonly Dictionary<object, KeyValuePair<int, HashSet<string>>> s_keys = new Dictionary<object, KeyValuePair<int, HashSet<string>>>(); internal static Achievement Find(string id) { if ((Object)(object)Achievements.m_instance == (Object)null) { return null; } foreach (AchievementList achievementList in Achievements.m_instance.m_achievementLists) { foreach (Achievement achievement in achievementList.m_achievements) { if ((Object)(object)achievement != (Object)null && achievement.m_id == id) { return achievement; } } } return null; } internal static PlayerStats StatsFor(Achievement achievement) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) Game instance = Game.instance; PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null); if (val == null || (Object)(object)achievement == (Object)null) { return null; } return val.m_playerStats[achievement.m_difficultyRequirement]; } internal static HashSet<string> Keys(List<DictStatRequirement> triggers) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) if (triggers == null) { return new HashSet<string>(); } if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count) { return value.Value; } HashSet<string> hashSet = new HashSet<string>(); foreach (DictStatRequirement trigger in triggers) { hashSet.Add(trigger.m_stat); } s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet); return hashSet; } internal static HashSet<string> Keys(List<EnemyStatRequirement> triggers) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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) if (triggers == null) { return new HashSet<string>(); } if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count) { return value.Value; } HashSet<string> hashSet = new HashSet<string>(); foreach (EnemyStatRequirement trigger in triggers) { hashSet.Add(trigger.m_stat); } s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet); return hashSet; } internal static bool Has(Dictionary<string, float> stats, string key) { if (stats != null && stats.TryGetValue(key, out var value)) { return value >= 1f; } return false; } internal static int CountDone(HashSet<string> keys, Dictionary<string, float> stats) { int num = 0; foreach (string key in keys) { if (Has(stats, key)) { num++; } } return num; } } } namespace ComfortHelper { internal class Suggestion { public Piece Piece; public int Gain; public Piece Replaces; } internal class ComfortReport { public bool InShelter; public int Current; public int BestKnown; public int Locked; public float MaxReached; public readonly List<Suggestion> Suggestions = new List<Suggestion>(); } internal static class Comfort { private const float Radius = 10f; private static readonly List<Piece> s_nearby = new List<Piece>(); private static List<Piece> s_comfortPrefabs; private static ZNetScene s_scene; private static readonly string[] GroupNames = Enum.GetNames(typeof(ComfortGroup)); internal static string GroupOf(Piece piece) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if ((int)piece.m_comfortGroup == 0) { return piece.m_name; } return GroupNames[piece.m_comfortGroup]; } internal static Dictionary<string, Piece> BestNearby(Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) Dictionary<string, Piece> dictionary = new Dictionary<string, Piece>(); Nearby(position, dictionary, null); return dictionary; } internal static void Nearby(Vector3 position, Dictionary<string, Piece> best, HashSet<string> names) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) s_nearby.Clear(); Piece.GetAllComfortPiecesInRadius(position, 10f, s_nearby); foreach (Piece item in s_nearby) { names?.Add(item.m_name); if (best != null) { string key = GroupOf(item); if (!best.TryGetValue(key, out var value) || item.GetComfort() > value.GetComfort()) { best[key] = item; } } } } internal static ComfortReport Build(Player player) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) ComfortReport comfortReport = new ComfortReport { InShelter = player.InShelter(), Current = SE_Rested.CalculateComfortLevel(player), MaxReached = MaxComfort() }; Dictionary<string, Piece> dictionary = BestNearby(((Component)player).transform.position); Dictionary<string, Piece> dictionary2 = new Dictionary<string, Piece>(); Dictionary<string, int> dictionary3 = new Dictionary<string, int>(); foreach (Piece item in ComfortPrefabs()) { string key = GroupOf(item); if (!dictionary3.TryGetValue(key, out var value) || item.m_comfort > value) { dictionary3[key] = item.m_comfort; } if (player.IsRecipeKnown(item.m_name) && (!dictionary2.TryGetValue(key, out var value2) || item.m_comfort > value2.m_comfort)) { dictionary2[key] = item; } } int num = 0; foreach (KeyValuePair<string, Piece> item2 in dictionary2) { num += item2.Value.m_comfort; dictionary.TryGetValue(item2.Key, out var value3); int num2 = item2.Value.m_comfort - (((Object)(object)value3 != (Object)null) ? value3.GetComfort() : 0); if (num2 > 0) { comfortReport.Suggestions.Add(new Suggestion { Piece = item2.Value, Gain = num2, Replaces = value3 }); } } comfortReport.BestKnown = 2 + num; comfortReport.Locked = dictionary3.Sum((KeyValuePair<string, int> p) => p.Value) - num; comfortReport.Suggestions.Sort((Suggestion a, Suggestion b) => b.Gain.CompareTo(a.Gain)); return comfortReport; } private static float MaxComfort() { PlayerStats val = AchievementStats.StatsFor(AchievementStats.Find("GrindComfort")); if (val == null || !val.m_stats.TryGetValue((PlayerStatType)132, out var value)) { return 0f; } return value; } private static List<Piece> ComfortPrefabs() { if (s_comfortPrefabs != null && (Object)(object)s_scene == (Object)(object)ZNetScene.instance) { return s_comfortPrefabs; } s_scene = ZNetScene.instance; s_comfortPrefabs = new List<Piece>(); if ((Object)(object)s_scene == (Object)null || (Object)(object)ObjectDB.instance == (Object)null) { return s_comfortPrefabs; } HashSet<string> hashSet = new HashSet<string>(); foreach (GameObject item in ObjectDB.instance.m_items) { PieceTable val = ((!((Object)(object)item != (Object)null)) ? null : item.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces); if ((Object)(object)val == (Object)null) { continue; } foreach (GameObject piece in val.m_pieces) { Piece val2 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null); if ((Object)(object)val2 != (Object)null && val2.m_comfort > 0 && hashSet.Add(val2.m_name)) { s_comfortPrefabs.Add(val2); } } } return s_comfortPrefabs; } internal static string Describe(Suggestion suggestion) { string arg = Localization.instance.Localize(suggestion.Piece.m_name); if (!((Object)(object)suggestion.Replaces == (Object)null)) { return $"+{suggestion.Gain} {arg} (instead of {Localization.instance.Localize(suggestion.Replaces.m_name)})"; } return $"+{suggestion.Gain} {arg}"; } } internal static class ComfortGroups { internal unsafe static string Name(ComfortGroup group) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected I4, but got Unknown return (int)group switch { 1 => "Fires", 2 => "Beds", 3 => "Banners", 4 => "Seats", 5 => "Tables", 6 => "Rugs", 7 => "Displays", 8 => "Decorations", 9 => "Garlands", 10 => "Lanterns", 11 => "Leisure", 0 => "Each counts", _ => ((object)(*(ComfortGroup*)(&group))/*cast due to .constrained prefix*/).ToString(), }; } } internal sealed class ComfortPieceList : IPieceList { private readonly ComfortGroup[] _groups = (ComfortGroup[])Enum.GetValues(typeof(ComfortGroup)); private readonly List<int> _availableTags = new List<int>(); public string DisplayName { get; } public bool ShowTags => true; public bool CanCustomizeTags => false; public int TagCount => _availableTags.Count; public int TagSeparatorIndex => -1; public ComfortPieceList(string displayName) { DisplayName = displayName; } public string GetTagDisplayName(int index) { int num = (int)_groups[_availableTags[index]]; string text = ComfortGroups.Name((ComfortGroup)num); int num2 = NearbyState.GroupComfort((ComfortGroup)num); if (num2 <= 0) { return text; } return $"<color=#7CFC7C>{text} +{num2}</color>"; } public int GetTagIdByIndex(int index) { return _availableTags[index]; } public void UpdateAvailableTags(PieceTable pieceTable) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) HashSet<ComfortGroup> hashSet = new HashSet<ComfortGroup>(); foreach (Piece availablePiece in pieceTable.m_availablePieces) { if (availablePiece.m_comfort > 0) { hashSet.Add(availablePiece.m_comfortGroup); } } _availableTags.Clear(); for (int i = 0; i < _groups.Length; i++) { if (_groups[i] && hashSet.Contains(_groups[i])) { _availableTags.Add(i); } } int item = Array.IndexOf(_groups, (ComfortGroup)0); if (hashSet.Contains((ComfortGroup)0)) { _availableTags.Add(item); } } public void GetAvailablePiecesWithTag(int tagId, PieceTable pieceTable, IList<Piece> resultOut) { foreach (Piece item in from p in pieceTable.m_availablePieces where p.m_comfort > 0 && (tagId < 0 || tagId >= _groups.Length || (int)p.m_comfortGroup == (int)_groups[tagId]) orderby p.m_comfort descending select p) { resultOut.Add(item); } } } internal static class NearbyState { private static Dictionary<string, Piece> s_best = new Dictionary<string, Piece>(); private static HashSet<string> s_names = new HashSet<string>(); private static Dictionary<string, Piece> s_nextBest = new Dictionary<string, Piece>(); private static HashSet<string> s_nextNames = new HashSet<string>(); private static float s_nextUpdate; internal static int Version { get; private set; } internal static bool Update(Player player, bool force = false) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!force && Time.time < s_nextUpdate) { return false; } s_nextUpdate = Time.time + 1f; s_nextBest.Clear(); s_nextNames.Clear(); Comfort.Nearby(((Component)player).transform.position, s_nextBest, s_nextNames); bool num = !s_nextNames.SetEquals(s_names) || !SameCounting(s_nextBest, s_best); Dictionary<string, Piece> dictionary = s_nextBest; Dictionary<string, Piece> dictionary2 = s_best; s_best = dictionary; s_nextBest = dictionary2; HashSet<string> hashSet = s_nextNames; HashSet<string> hashSet2 = s_names; s_names = hashSet; s_nextNames = hashSet2; if (num) { Version++; } return num; } private static bool SameCounting(Dictionary<string, Piece> a, Dictionary<string, Piece> b) { if (a.Count != b.Count) { return false; } foreach (KeyValuePair<string, Piece> item in a) { if (!b.TryGetValue(item.Key, out var value) || value.m_name != item.Value.m_name) { return false; } } return true; } internal static bool IsHere(Piece piece) { return s_names.Contains(piece.m_name); } internal static bool Counts(Piece piece) { if (s_best.TryGetValue(Comfort.GroupOf(piece), out var value)) { return value.m_name == piece.m_name; } return false; } internal static Piece Counting(Piece piece) { if (!s_best.TryGetValue(Comfort.GroupOf(piece), out var value)) { return null; } return value; } internal unsafe static int GroupComfort(ComfortGroup group) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) if ((int)group == 0) { return s_best.Values.Where((Piece p) => (int)p.m_comfortGroup == 0).Sum((Piece p) => p.GetComfort()); } if (!s_best.TryGetValue(((object)(*(ComfortGroup*)(&group))/*cast due to .constrained prefix*/).ToString(), out var value)) { return 0; } return value.GetComfort(); } } [HarmonyPatch] internal static class ComfortTabPatches { private const string CheckName = "ComfortHelperCheck"; private static readonly Color Green = new Color(0.45f, 0.95f, 0.45f); private static readonly Color Grey = new Color(0.62f, 0.62f, 0.62f); private static readonly FieldRef<BuildUi, RectTransform> TabContainerRef = AccessTools.FieldRefAccess<BuildUi, RectTransform>("m_tabContainer"); private static readonly FieldRef<BuildUi, TabHandler> TabHandlerRef = AccessTools.FieldRefAccess<BuildUi, TabHandler>("m_tabHandler"); private static readonly FieldRef<BuildUi, List<IPieceList>> PieceListsRef = AccessTools.FieldRefAccess<BuildUi, List<IPieceList>>("m_pieceLists"); private static readonly FieldRef<BuildUi, int> AvailablePieceCountRef = AccessTools.FieldRefAccess<BuildUi, int>("m_availablePieceCount"); private static readonly FieldRef<BuildUi, int> CurrentPieceListRef = AccessTools.FieldRefAccess<BuildUi, int>("m_currentPieceList"); private static readonly FieldRef<BuildUi, List<BuildUiPieceButton>> PieceButtonsRef = AccessTools.FieldRefAccess<BuildUi, List<BuildUiPieceButton>>("m_pieceButtons"); private static readonly Dictionary<string, string> s_hoverTexts = new Dictionary<string, string>(); private static int s_hoverVersion = -1; [HarmonyPrefix] [HarmonyPatch(typeof(BuildUi), "Awake")] private static void BeforeAwake(BuildUi __instance, out bool __state) { //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00cc: 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_011c: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown __state = false; if (!ComfortHelperPlugin.ComfortTab.Value) { return; } RectTransform val = TabContainerRef.Invoke(__instance); TabHandler val2 = TabHandlerRef.Invoke(__instance); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || ((Transform)val).childCount < 2 || val2.m_tabs.Count != ((Transform)val).childCount) { ComfortHelperPlugin.Log.LogWarning((object)"Build menu tabs have an unexpected layout; the Comfort tab is disabled."); return; } RectTransform val3 = (RectTransform)((Transform)val).GetChild(((Transform)val).childCount - 1); RectTransform val4 = (RectTransform)((Transform)val).GetChild(((Transform)val).childCount - 2); RectTransform val5 = Object.Instantiate<RectTransform>(val3, (Transform)(object)val); ((Object)val5).name = "ComfortHelper_ComfortTab"; if ((Object)(object)((Component)val).GetComponent<LayoutGroup>() == (Object)null) { val5.anchoredPosition = val3.anchoredPosition + (val3.anchoredPosition - val4.anchoredPosition); } TMP_Text[] componentsInChildren = ((Component)val5).GetComponentsInChildren<TMP_Text>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].text = ComfortHelperPlugin.TabName.Value; } Button component = ((Component)val5).GetComponent<Button>(); component.onClick = new ButtonClickedEvent(); val2.m_tabs.Add(new Tab { m_button = component }); __state = true; } [HarmonyPostfix] [HarmonyPatch(typeof(BuildUi), "Awake")] private static void AfterAwake(BuildUi __instance, bool __state) { if (__state) { PieceListsRef.Invoke(__instance).Add((IPieceList)(object)new ComfortPieceList(ComfortHelperPlugin.TabName.Value)); } } private static bool ComfortTabShown(BuildUi buildUi) { List<IPieceList> list = PieceListsRef.Invoke(buildUi); int num = CurrentPieceListRef.Invoke(buildUi); if (num >= 0 && num < list.Count) { return list[num] is ComfortPieceList; } return false; } [HarmonyPostfix] [HarmonyPatch(typeof(BuildUi), "UpdatePieceButtons")] private static void AfterUpdatePieceButtons(BuildUi __instance) { //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) Player localPlayer = Player.m_localPlayer; bool flag = (Object)(object)localPlayer != (Object)null && (ComfortTabShown(__instance) || ComfortHelperPlugin.ChecksInAllTabs.Value); if (flag) { NearbyState.Update(localPlayer, force: true); } foreach (BuildUiPieceButton item in PieceButtonsRef.Invoke(__instance)) { Piece piece = item.Piece; bool flag2 = flag && (Object)(object)piece != (Object)null && piece.m_comfort > 0 && NearbyState.IsHere(piece); Transform val = ((Component)item).transform.Find("ComfortHelperCheck"); if ((Object)(object)val == (Object)null) { if (!flag2) { continue; } val = CreateCheck(((Component)item).transform); } ((Component)val).gameObject.SetActive(flag2); if (flag2) { Color color = (NearbyState.Counts(piece) ? Green : Grey); Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true); for (int i = 0; i < componentsInChildren.Length; i++) { ((Graphic)componentsInChildren[i]).color = color; } } } } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "Update")] private static void AfterHudUpdate() { BuildUi val = (((Object)(object)Hud.instance != (Object)null) ? Hud.instance.m_buildUi : null); Player localPlayer = Player.m_localPlayer; if (!((Object)(object)val == (Object)null) && !((Object)(object)localPlayer == (Object)null) && ((Behaviour)val).isActiveAndEnabled && (ComfortTabShown(val) || ComfortHelperPlugin.ChecksInAllTabs.Value) && NearbyState.Update(localPlayer)) { AvailablePieceCountRef.Invoke(val) = -1; } } private static Transform CreateCheck(Transform button) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Expected O, but got Unknown //IL_00ef: Expected O, but got Unknown GameObject val = new GameObject("ComfortHelperCheck", new Type[1] { typeof(RectTransform) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent(button, false); Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(1f, 1f); val2.anchorMax = val3; val2.anchorMin = val3; val2.pivot = new Vector2(1f, 1f); val2.anchoredPosition = new Vector2(-3f, -3f); val2.sizeDelta = new Vector2(18f, 16f); ((Transform)val2).SetAsLastSibling(); Bar(val2, new Vector2(5f, 6f), new Vector2(9f, 4f), -45f); Bar(val2, new Vector2(11f, 8f), new Vector2(15f, 4f), 50f); val.SetActive(false); return (Transform)val2; } private static void Bar(RectTransform parent, Vector2 center, Vector2 size, float angle) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("bar", new Type[3] { typeof(RectTransform), typeof(Image), typeof(Outline) }); RectTransform val2 = (RectTransform)val.transform; ((Transform)val2).SetParent((Transform)(object)parent, false); Vector2 anchorMin = (val2.anchorMax = Vector2.zero); val2.anchorMin = anchorMin; val2.pivot = new Vector2(0.5f, 0.5f); val2.anchoredPosition = center; val2.sizeDelta = size; ((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, angle); ((Graphic)val.GetComponent<Image>()).raycastTarget = false; Outline component = val.GetComponent<Outline>(); ((Shadow)component).effectColor = new Color(0f, 0f, 0f, 0.85f); ((Shadow)component).effectDistance = new Vector2(1f, -1f); } [HarmonyPostfix] [HarmonyPatch(typeof(Hud), "SetupPieceInfo")] private static void AfterSetupPieceInfo(Hud __instance, Piece piece) { Player localPlayer = Player.m_localPlayer; if (ComfortHelperPlugin.HoverInfo.Value && !((Object)(object)piece == (Object)null) && piece.m_comfort > 0 && !((Object)(object)localPlayer == (Object)null)) { NearbyState.Update(localPlayer); if (s_hoverVersion != NearbyState.Version) { s_hoverTexts.Clear(); s_hoverVersion = NearbyState.Version; } if (!s_hoverTexts.TryGetValue(piece.m_name, out var value)) { value = (s_hoverTexts[piece.m_name] = HoverText(piece)); } TMP_Text pieceDescription = __instance.m_pieceDescription; pieceDescription.text += value; } } private static string HoverText(Piece piece) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) Localization instance = Localization.instance; string text = $"\n\n<color=#ffb347>Comfort +{piece.m_comfort}</color> "; text += (((int)piece.m_comfortGroup == 0) ? "(counts once, next to everything else)" : ("(" + ComfortGroups.Name(piece.m_comfortGroup) + ": only the best one nearby counts)")); Piece val = NearbyState.Counting(piece); if ((Object)(object)val == (Object)null) { return text + $"\nNothing like it within 10 m: <color=#7CFC7C>+{piece.m_comfort} here</color>."; } if (val.m_name == piece.m_name) { return text + "\n<color=#7CFC7C>Already counts here.</color>"; } if (piece.m_comfort > val.GetComfort()) { return text + $"\n{instance.Localize(val.m_name)} counts here now: <color=#7CFC7C>+{piece.m_comfort - val.GetComfort()} more</color> with this one."; } return text + "\n" + instance.Localize(val.m_name) + " already counts here; this one adds nothing."; } } internal static class Commands { [CompilerGenerated] private static class <>O { public static ConsoleEvent <0>__Run; } public static void Register() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown try { object obj = <>O.<0>__Run; if (obj == null) { ConsoleEvent val = Run; <>O.<0>__Run = val; obj = (object)val; } new ConsoleCommand("comfort", "ComfortHelper: your comfort here and the pieces that would raise it", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false); } catch (Exception ex) { ComfortHelperPlugin.Log.LogWarning((object)("Couldn't add console commands: " + ex.Message)); } } private static void Run(ConsoleEventArgs args) { Player localPlayer = Player.m_localPlayer; if ((Object)(object)localPlayer == (Object)null) { Say(args, "ComfortHelper: load into a world with a character first."); return; } ComfortReport comfortReport = Comfort.Build(localPlayer); Say(args, $"ComfortHelper: comfort here {comfortReport.Current}, best so far {comfortReport.MaxReached:0} " + "(Comfort is King needs 20)."); if (!comfortReport.InShelter) { Say(args, " You are not under a roof: pieces only count in a shelter."); } Say(args, $" With the pieces you know, the most you can reach is {comfortReport.BestKnown}." + ((comfortReport.Locked > 0) ? $" Pieces you haven't unlocked yet add up to {comfortReport.Locked} more." : "")); if (comfortReport.Suggestions.Count == 0) { Say(args, " Nothing you know would raise it here."); return; } Say(args, " Within 10 m, add:"); foreach (Suggestion suggestion in comfortReport.Suggestions) { Say(args, " " + Comfort.Describe(suggestion)); } } private static void Say(ConsoleEventArgs args, string text) { if ((Object)(object)args?.Context != (Object)null) { args.Context.AddString(text); } else { ComfortHelperPlugin.Log.LogInfo((object)text); } } } [BepInPlugin("com.koendertjh.comforthelper", "ComfortHelper", "1.0.0")] public class ComfortHelperPlugin : BaseUnityPlugin { public const string ModGuid = "com.koendertjh.comforthelper"; public const string ModName = "ComfortHelper"; public const string ModVersion = "1.0.0"; internal static ManualLogSource Log; internal static ConfigEntry<bool> RestingMessage; internal static ConfigEntry<float> MessageCooldown; internal static ConfigEntry<int> MaxSuggestions; internal static ConfigEntry<bool> ComfortTab; internal static ConfigEntry<string> TabName; internal static ConfigEntry<bool> ChecksInAllTabs; internal static ConfigEntry<bool> HoverInfo; private Harmony _harmony; private void Awake() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; RestingMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "RestingMessage", true, "When you start resting, show which known pieces would raise your comfort here."); MessageCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "MessageCooldown", 600f, new ConfigDescription("Seconds before the resting message shows again.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3600f), Array.Empty<object>())); MaxSuggestions = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "MaxSuggestions", 4, new ConfigDescription("Pieces listed in the resting message (the /comfort command lists all).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>())); ComfortTab = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Build menu", "ComfortTab", true, "A Comfort tab in the build menu with every comfort piece, one category per comfort group. Needs a restart."); TabName = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Build menu", "TabName", "Comfort", "Name of the tab. Needs a restart."); ChecksInAllTabs = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Build menu", "ChecksInAllTabs", false, "Also show the check marks on comfort pieces in the other build menu tabs."); HoverInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Build menu", "HoverInfo", true, "The description of a comfort piece shows its comfort, its group and what it would add where you stand."); _harmony = new Harmony("com.koendertjh.comforthelper"); _harmony.PatchAll(typeof(ComfortHelperPlugin).Assembly); Commands.Register(); } private void OnDestroy() { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } [HarmonyPatch(typeof(Player), "UpdateEnvStatusEffects")] internal static class RestingMessage { private static bool s_wasResting; private static float s_lastShown = -10000f; private static void Postfix(Player __instance) { if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer) { return; } bool flag = ((Character)__instance).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectResting); bool num = flag && !s_wasResting; s_wasResting = flag; if (!num || !ComfortHelperPlugin.RestingMessage.Value || Time.time - s_lastShown < ComfortHelperPlugin.MessageCooldown.Value) { return; } s_lastShown = Time.time; ComfortReport comfortReport = Comfort.Build(__instance); string text = $"Comfort {comfortReport.Current} (best so far {comfortReport.MaxReached:0}, Comfort is King needs 20)"; if (comfortReport.Suggestions.Count > 0) { text = text + "\nTo raise it: " + string.Join(", ", comfortReport.Suggestions.Take(ComfortHelperPlugin.MaxSuggestions.Value).Select(Comfort.Describe)); if (comfortReport.Suggestions.Count > ComfortHelperPlugin.MaxSuggestions.Value) { text += ", ... (/comfort lists all)"; } } ((Character)__instance).Message((MessageType)1, text, 0, (Sprite)null, false); } } internal static class PluginInfo { public const string Version = "1.0.0"; } }