using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; 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 Eremite; using Eremite.Buildings; using Eremite.Buildings.UI; using Eremite.Buildings.UI.Trade; using Eremite.Characters; using Eremite.Characters.Behaviours; using Eremite.Characters.Villagers; using Eremite.Controller; using Eremite.MapObjects; using Eremite.Model; using Eremite.Services; using Eremite.View; using Eremite.View.HUD; using Eremite.View.HUD.Woodcutters; using Eremite.View.Popups; using Eremite.View.Popups.Consumption; using Eremite.View.Popups.Recipes; using Eremite.View.UI.Wiki; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using UnityEngine.UI; [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.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("MoreHotkeys")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyDescription("MoreHotkeys")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+d6ada77561ccfe85ca4c2c807fd24c8c3fc0d51c")] [assembly: AssemblyProduct("MoreHotkeys")] [assembly: AssemblyTitle("MoreHotkeys")] [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 MoreHotkeys { public class BuildingRecipeTooltip : MonoBehaviour { public static BuildingRecipeTooltip Instance; private const float ROW_WIDTH = 120f; private const float ROW_HEIGHT = 50f; private GameObject root; private RectTransform panel; private readonly List rows = new List(); private void Awake() { Instance = this; InitializeWhenCanvasExists(); } private void InitializeWhenCanvasExists() { Canvas val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { SceneManager.sceneLoaded += OnSceneLoaded; } else { InitializeTooltipCanvas(val); } } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { SceneManager.sceneLoaded -= OnSceneLoaded; Canvas val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null) { InitializeTooltipCanvas(val); } } private void InitializeTooltipCanvas(Canvas hudCanvas) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0151: 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_01ba: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BuildingRecipeTooltipCanvas", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(((Component)hudCanvas).transform, false); Canvas val2 = val.AddComponent(); val2.overrideSorting = true; val2.sortingOrder = 50000; CanvasScaler val3 = val.AddComponent(); val3.uiScaleMode = (ScaleMode)1; val3.referenceResolution = new Vector2(1920f, 1080f); val3.matchWidthOrHeight = 0.5f; val.AddComponent(); root = new GameObject("BuildingRecipeTooltipRoot", new Type[1] { typeof(RectTransform) }); root.transform.SetParent(val.transform, false); root.SetActive(false); CanvasGroup val4 = root.AddComponent(); val4.blocksRaycasts = false; panel = new GameObject("Panel", new Type[1] { typeof(RectTransform) }).GetComponent(); ((Component)panel).transform.SetParent(root.transform, false); panel.anchorMin = new Vector2(0f, 1f); panel.anchorMax = new Vector2(0f, 1f); panel.pivot = new Vector2(0f, 1f); CanvasGroup val5 = ((Component)panel).gameObject.AddComponent(); val5.blocksRaycasts = false; Image val6 = ((Component)panel).gameObject.AddComponent(); ((Graphic)val6).color = new Color(0.02f, 0.02f, 0.02f, 0.85f); ((Graphic)val6).raycastTarget = false; panel.SetSizeWithCurrentAnchors((Axis)0, 120f); } public void Show(BuildingModel building) { Hide(); InternalShow(building); } private void Update() { if ((Object)(object)root != (Object)null && root.activeSelf) { UpdatePosition(); } } private void InternalShow(BuildingModel building) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown //IL_012a: Unknown result type (might be due to invalid IL or missing references) foreach (Transform item in ((Component)panel).transform) { Transform val = item; Object.Destroy((Object)(object)((Component)val).gameObject); } rows.Clear(); if ((Object)(object)panel == (Object)null) { return; } WorkshopModel val2 = (WorkshopModel)(object)((building is WorkshopModel) ? building : null); if ((Object)(object)val2 == (Object)null || val2.recipes == null) { return; } List list = (from g in val2.recipes.GroupBy(delegate(WorkshopRecipeModel r) { GoodRef producedGood = r.producedGood; object result; if (producedGood == null) { result = null; } else { GoodModel good = producedGood.good; result = ((good != null) ? ((Object)good).name : null); } return (string)result; }) select g.First()).ToList(); float num = 0f; int num2 = 0; foreach (WorkshopRecipeModel item2 in list) { GameObject val3 = CreateRow(item2, num2); RectTransform component = val3.GetComponent(); component.anchoredPosition = new Vector2(0f, 0f - num); num += 50f; rows.Add(val3); num2++; } panel.SetSizeWithCurrentAnchors((Axis)1, num + 6f); root.SetActive(true); UpdatePosition(); } private GameObject CreateRow(WorkshopRecipeModel recipe, int rowIndex) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_004f: 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_007b: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_012a: 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_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Expected O, but got Unknown //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0239: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_02c4: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Expected O, but got Unknown //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Unknown result type (might be due to invalid IL or missing references) //IL_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0339: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_03b3: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject($"RecipeRow_{rowIndex}", new Type[1] { typeof(RectTransform) }); val.transform.SetParent((Transform)(object)panel, false); RectTransform component = val.GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(0f, 1f); component.pivot = new Vector2(0f, 1f); component.SetSizeWithCurrentAnchors((Axis)0, 120f); component.SetSizeWithCurrentAnchors((Axis)1, 50f); Image val2 = val.AddComponent(); ((Graphic)val2).color = new Color(0.05f, 0.05f, 0.05f, 0.95f); ((Graphic)val2).raycastTarget = false; Outline val3 = val.AddComponent(); ((Shadow)val3).effectColor = new Color(0.55f, 0.45f, 0.2f, 1f); ((Shadow)val3).effectDistance = new Vector2(1f, -1f); Outline val4 = val.AddComponent(); ((Shadow)val4).effectColor = new Color(0.12f, 0.12f, 0.1f, 1f); ((Shadow)val4).effectDistance = new Vector2(-1f, 1f); Shadow val5 = val.AddComponent(); val5.effectColor = new Color(0f, 0f, 0f, 0.7f); val5.effectDistance = new Vector2(2f, -2f); Sprite sprite = recipe.producedGood?.good?.icon; GameObject val6 = new GameObject("Icon", new Type[1] { typeof(RectTransform) }); val6.transform.SetParent(val.transform, false); RectTransform component2 = val6.GetComponent(); component2.anchorMin = new Vector2(0f, 0.5f); component2.anchorMax = new Vector2(0f, 0.5f); component2.pivot = new Vector2(0f, 0.5f); component2.anchoredPosition = new Vector2(8f, 0f); component2.SetSizeWithCurrentAnchors((Axis)0, 48f); component2.SetSizeWithCurrentAnchors((Axis)1, 48f); Image val7 = val6.AddComponent(); val7.sprite = sprite; ((Graphic)val7).color = Color.white; if ((Object)(object)((RecipeModel)recipe).grade != (Object)null && (Object)(object)((RecipeModel)recipe).grade.icon != (Object)null) { GameObject val8 = new GameObject("GradeBar", new Type[1] { typeof(RectTransform) }); val8.transform.SetParent(val.transform, false); RectTransform component3 = val8.GetComponent(); component3.anchorMin = new Vector2(0f, 0.5f); component3.anchorMax = new Vector2(0f, 0.5f); component3.pivot = new Vector2(0f, 0.5f); component3.anchoredPosition = new Vector2(60f, 0f); float num = 1f; Rect rect = ((RecipeModel)recipe).grade.icon.rect; component3.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width * num); rect = ((RecipeModel)recipe).grade.icon.rect; component3.SetSizeWithCurrentAnchors((Axis)1, ((Rect)(ref rect)).height * num); Image val9 = val8.AddComponent(); val9.sprite = ((RecipeModel)recipe).grade.icon; ((Graphic)val9).color = Color.white; } return val; } public void Hide() { if ((Object)(object)root == (Object)null) { return; } foreach (GameObject row in rows) { if ((Object)(object)row != (Object)null) { Object.Destroy((Object)(object)row); } } rows.Clear(); root.SetActive(false); } private void UpdatePosition() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_004a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)panel == (Object)null)) { Vector2 val = ((InputControl)(object)((Pointer)Mouse.current).position).ReadValue(); val.x += 40f; val.y += 40f; ((Transform)panel).position = Vector2.op_Implicit(val); } } } public class BuildingRecipeTooltipTrigger : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler { public BuildingModel BuildingModel; public void OnPointerEnter(PointerEventData eventData) { if ((Object)(object)BuildingModel != (Object)null) { BuildingRecipeTooltip.Instance?.Show(BuildingModel); } } public void OnPointerExit(PointerEventData eventData) { BuildingRecipeTooltip.Instance?.Hide(); } } [HarmonyPatch] public static class BuildingRecipeTooltipSystem { [HarmonyPatch(typeof(RecipesPopupWorkshopPreviewSlot), "SetUp")] [HarmonyPostfix] private static void PreviewSlot_SetUp_Postfix(RecipesPopupWorkshopPreviewSlot __instance, BuildingModel workshop, WorkshopRecipeModel recipe, Action interactionCallback) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if ((Object)(object)workshop == (Object)null) { return; } if ((Object)(object)BuildingRecipeTooltip.Instance == (Object)null) { GameObject val = new GameObject("BuildingRecipeTooltip"); val.AddComponent(); } object? obj = typeof(RecipesPopupWorkshopPreviewSlot).GetField("buildingIcon", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(__instance); Image val2 = (Image)((obj is Image) ? obj : null); if ((Object)(object)val2 == (Object)null) { return; } GameObject gameObject = ((Component)val2).gameObject; BuildingRecipeTooltipTrigger buildingRecipeTooltipTrigger = gameObject.GetComponent(); if ((Object)(object)buildingRecipeTooltipTrigger == (Object)null) { buildingRecipeTooltipTrigger = gameObject.AddComponent(); } buildingRecipeTooltipTrigger.BuildingModel = workshop; ((Graphic)val2).raycastTarget = true; Image[] componentsInChildren = ((Component)__instance).GetComponentsInChildren(); foreach (Image val3 in componentsInChildren) { if ((Object)(object)val3 != (Object)(object)val2) { ((Graphic)val3).raycastTarget = false; } } } } public class ConditionsHUDSync : MonoBehaviour { private class PopupInfo { public GameObject Blend; public GameObject Content; } private static GameObject gmBlend; private static GameObject gmContent; private static GameObject main; private static PopupInfo[] popups; private static bool hudReady; private static bool lastPopupOpen; public static ConfigEntry ConditionsHUD; public static void Init(ConfigFile config, Harmony harmony, GameObject host) { ConditionsHUD = config.Bind("ConditionsHUD", "ConditionsHUD", true, "ConditionsHUD and DeedsHUD pops up alongside every popup from Orders to Trends."); host.AddComponent(); } private void Update() { if (ConditionsHUD != null && !ConditionsHUD.Value) { return; } if (!hudReady) { TryResolveHUD(); } if (hudReady && !((Object)(object)gmContent == (Object)null) && !((Object)(object)gmBlend == (Object)null)) { bool flag = IsAnyPopupVisible(); bool flag2 = gmBlend.activeSelf && !flag; if (flag && !lastPopupOpen) { gmContent.SetActive(true); main.SetActive(false); } else if (!flag && lastPopupOpen) { gmContent.SetActive(false); main.SetActive(true); } lastPopupOpen = flag; if (!flag2) { } } } private static void TryResolveHUD() { GameObject val = GameObject.Find("HUD"); if ((Object)(object)val == (Object)null) { return; } FixHierarchy(val); Transform val2 = val.transform.Find("GameMenuPopup"); if ((Object)(object)val2 == (Object)null) { return; } Transform obj = val2.Find("Blend"); gmBlend = ((obj != null) ? ((Component)obj).gameObject : null); Transform obj2 = val2.Find("Content"); gmContent = ((obj2 != null) ? ((Component)obj2).gameObject : null); if (!((Object)(object)gmBlend == (Object)null) && !((Object)(object)gmContent == (Object)null)) { Transform obj3 = gmContent.transform.Find("Main"); main = ((obj3 != null) ? ((Component)obj3).gameObject : null); if (!((Object)(object)main == (Object)null)) { popups = new PopupInfo[6] { ResolvePopup(val, "OrdersPopup"), ResolvePopup(val, "TraderPanel"), ResolvePopup(val, "TradeRoutesPopup"), ResolvePopup(val, "RecipesPopup"), ResolvePopup(val, "ConsumptionPopup"), ResolvePopup(val, "TrendsPopup") }; hudReady = true; } } } private static void FixHierarchy(GameObject hud) { Transform val = hud.transform.Find("RecipesPopup"); Transform val2 = hud.transform.Find("ConsumptionPopup"); if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null) { val2.SetSiblingIndex(val.GetSiblingIndex() + 1); } Transform val3 = hud.transform.Find("GameMenuPopup"); Transform val4 = hud.transform.Find("OrderPickPopup"); if ((Object)(object)val3 != (Object)null && (Object)(object)val4 != (Object)null) { val4.SetSiblingIndex(val3.GetSiblingIndex()); } } private static PopupInfo ResolvePopup(GameObject hud, string name) { Transform val = hud.transform.Find(name); if ((Object)(object)val == (Object)null) { return null; } Transform val2 = val.Find("Blend"); Transform val3 = val.Find("Content"); return new PopupInfo { Blend = (((Object)(object)val2 != (Object)null) ? ((Component)val2).gameObject : null), Content = (((Object)(object)val3 != (Object)null) ? ((Component)val3).gameObject : null) }; } private static bool IsAnyPopupVisible() { if (popups == null) { return false; } PopupInfo[] array = popups; foreach (PopupInfo popupInfo in array) { if (popupInfo != null && !((Object)(object)popupInfo.Blend == (Object)null) && !((Object)(object)popupInfo.Content == (Object)null) && popupInfo.Blend.activeSelf && popupInfo.Content.activeSelf) { return true; } } return false; } } public static class ConsumptionControl { private static bool _active = false; internal static ConsumptionPopup ActivePopup; private static readonly HashSet OptimizedFoodNeeds = new HashSet(); internal static GameObject _needsControlRow; internal static GameObject _needsControlColumn; internal static MasterToggle _needsToggle; private static float toggleShiftX = 717f; private static float toggleShiftY = 45f; private static float headerLocalShiftY = 0f; private static float toggleLocalShiftY = 45f; internal static void InjectNeedsControlUI(ConsumptionPopup popup) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_0100: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0145: 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_01af: Expected O, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Expected O, but got Unknown //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02f8: Unknown result type (might be due to invalid IL or missing references) //IL_030f: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Unknown result type (might be due to invalid IL or missing references) //IL_0345: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_03e4: Unknown result type (might be due to invalid IL or missing references) //IL_0401: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_0418: Unknown result type (might be due to invalid IL or missing references) //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0431: Unknown result type (might be due to invalid IL or missing references) //IL_04c7: Unknown result type (might be due to invalid IL or missing references) //IL_04cc: Unknown result type (might be due to invalid IL or missing references) //IL_04ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)popup == (Object)null || (Object)(object)((Component)popup).gameObject == (Object)null) { return; } Transform val = ((Component)popup).transform.Find("Content"); if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.Find("SlotsHeader"); Transform val3 = val.Find("RawFood"); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { return; } if ((Object)(object)_needsControlRow != (Object)null) { RefreshNeedsToggleVisual(); return; } _needsControlRow = new GameObject("NeedsControlRow", new Type[1] { typeof(RectTransform) }); _needsControlRow.transform.SetParent(val, false); int siblingIndex = val2.GetSiblingIndex() + 1; _needsControlRow.transform.SetSiblingIndex(siblingIndex); RectTransform component = _needsControlRow.GetComponent(); component.anchorMin = new Vector2(0f, 1f); component.anchorMax = new Vector2(1f, 1f); component.pivot = new Vector2(0.5f, 1f); component.sizeDelta = new Vector2(0f, 0f); HorizontalLayoutGroup val4 = _needsControlRow.AddComponent(); ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)val4).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val4).spacing = 0f; ((LayoutGroup)val4).padding.top = 250; _needsControlColumn = new GameObject("NeedsControlColumn", new Type[1] { typeof(RectTransform) }); _needsControlColumn.transform.SetParent(_needsControlRow.transform, false); RectTransform component2 = _needsControlColumn.GetComponent(); component2.anchorMin = new Vector2(0.5f, 1f); component2.anchorMax = new Vector2(0.5f, 1f); component2.pivot = new Vector2(0.5f, 1f); component2.sizeDelta = new Vector2(0f, 0f); VerticalLayoutGroup val5 = _needsControlColumn.AddComponent(); ((HorizontalOrVerticalLayoutGroup)val5).childControlWidth = false; ((HorizontalOrVerticalLayoutGroup)val5).childControlHeight = false; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val5).spacing = 2f; LayoutElement val6 = _needsControlColumn.AddComponent(); val6.preferredWidth = 200f; val6.minWidth = 200f; GameObject val7 = new GameObject("NeedsControlContainer", new Type[1] { typeof(RectTransform) }); val7.transform.SetParent(_needsControlColumn.transform, false); RectTransform component3 = val7.GetComponent(); component3.anchorMin = new Vector2(0.5f, 1f); component3.anchorMax = new Vector2(0.5f, 1f); component3.pivot = new Vector2(0.5f, 1f); component3.sizeDelta = new Vector2(200f, 0f); LayoutElement val8 = val7.AddComponent(); val8.ignoreLayout = true; Vector2 anchoredPosition = component3.anchoredPosition; anchoredPosition.x += toggleShiftX; anchoredPosition.y += toggleShiftY; component3.anchoredPosition = anchoredPosition; Transform val9 = val3.Find("Header Text"); if ((Object)(object)val9 == (Object)null) { return; } GameObject val10 = Object.Instantiate(((Component)val9).gameObject, val7.transform); ((Object)val10).name = "NeedsControlHeader"; TMP_Text component4 = val10.GetComponent(); component4.text = "Needs Control"; ((Graphic)component4).color = new Color(0.9137f, 0.7961f, 0.4863f, 1f); RectTransform component5 = val10.GetComponent(); component5.sizeDelta = new Vector2(200f, component5.sizeDelta.y); Vector2 anchoredPosition2 = component5.anchoredPosition; anchoredPosition2.y += headerLocalShiftY; component5.anchoredPosition = anchoredPosition2; Transform val11 = val.Find("SlotsHeader/NeedCategorySlot"); if ((Object)(object)val11 == (Object)null) { Debug.LogError((object)"[MoreHotkeys] ComplexFood NeedCategorySlot not found."); return; } MasterToggle componentInChildren = ((Component)val11).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { Debug.LogError((object)"[MoreHotkeys] No MasterToggle found under ComplexFood."); return; } GameObject val12 = Object.Instantiate(((Component)componentInChildren).gameObject, val7.transform); ((Object)val12).name = "NeedsControlToggle"; _needsToggle = val12.GetComponent(); RectTransform component6 = val12.GetComponent(); Vector2 anchoredPosition3 = component6.anchoredPosition; anchoredPosition3.y += toggleLocalShiftY; anchoredPosition3.x = 0f; component6.anchoredPosition = anchoredPosition3; _needsToggle.SetUp((MasterToggleState)(_active ? 2 : 0), true, (Action)delegate(bool isOn) { _active = isOn; if (_active) { ApplyOptimized(); } else { ApplyDefault(); } RefreshPopup(); }); } private static void RefreshNeedsToggleVisual() { if ((Object)(object)_needsToggle == (Object)null) { return; } _needsToggle.SetUp((MasterToggleState)(_active ? 2 : 0), true, (Action)delegate(bool isOn) { _active = isOn; if (_active) { ApplyOptimized(); } else { ApplyDefault(); } RefreshPopup(); }); } private static void RefreshPopup() { if ((Object)(object)ActivePopup != (Object)null && ((Popup)ActivePopup).IsShown()) { ActivePopup.Show(false); } } private static bool IsFoodNeed(NeedModel need) { return (Object)(object)need != (Object)null && need.canBeProhibited && (Object)(object)need.referenceGood != (Object)null && need.referenceGood.eatable && (!((Object)(object)need.category != (Object)null) || !need.category.isHouseBased); } private static void ApplyOptimized() { OptimizedFoodNeeds.Clear(); Dictionary rawFoodConsumptionPermits = GameMB.StateService.Actors.rawFoodConsumptionPermits; foreach (string item in new List(rawFoodConsumptionPermits.Keys)) { GameMB.NeedsService.SetPermision(item, false); } RaceModel[] races = GameMB.RacesService.Races; HashSet hashSet = new HashSet(); NeedModel[] needs = MB.Settings.Needs; foreach (NeedModel val in needs) { if (IsFoodNeed(val)) { hashSet.Add(val); } } foreach (NeedModel item2 in hashSet) { bool flag = false; RaceModel[] array = races; foreach (RaceModel val2 in array) { if ((Object)(object)val2 != (Object)null && GameMB.RacesService.IsRevealed(val2) && val2.HasNeed(item2)) { flag = true; break; } } RaceModel[] array2 = races; foreach (RaceModel val3 in array2) { if (!((Object)(object)val3 == (Object)null) && GameMB.RacesService.IsRevealed(val3)) { bool flag2 = !flag || val3.HasNeed(item2); OptimizedFoodNeeds.Add(item2); GameMB.NeedsService.SetPermision(val3, item2, flag2); } } } } private static void ApplyDefault() { Dictionary rawFoodConsumptionPermits = GameMB.StateService.Actors.rawFoodConsumptionPermits; foreach (string item in new List(rawFoodConsumptionPermits.Keys)) { GameMB.NeedsService.SetPermision(item, true); } RaceModel[] races = GameMB.RacesService.Races; RaceModel[] array = races; foreach (RaceModel val in array) { if ((Object)(object)val == (Object)null || !GameMB.RacesService.IsRevealed(val)) { continue; } foreach (NeedModel optimizedFoodNeed in OptimizedFoodNeeds) { if ((Object)(object)optimizedFoodNeed != (Object)null) { GameMB.NeedsService.SetPermision(val, optimizedFoodNeed, true); } } } } } [HarmonyPatch(typeof(ConsumptionPopup), "Show", new Type[] { typeof(bool) })] public static class ConsumptionControl_ConsumptionPopup_Show_Patch { private static void Postfix(ConsumptionPopup __instance) { ConsumptionControl.ActivePopup = __instance; ConsumptionControl.InjectNeedsControlUI(__instance); } } public static class CtrlClickResourceToIngredientPanel { [HarmonyPatch(typeof(GameInputService), "PickTarget")] public static class PickTargetPatch { private static bool Prefix(GameInputService __instance) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) IInputService inputService = MB.InputService; DefaultActions inputConfig = MB.InputConfig; if (!inputService.IsTriggering(((DefaultActions)(ref inputConfig)).InputModifierControl)) { return true; } IMapObject value = __instance.MouseoverObject.Value; if (value == null) { return true; } if (TryOpenIngredientPanel(value)) { return false; } return true; } } [HarmonyPatch(typeof(RecipesPopup), "Show")] public static class ForceIngredientModePatch { private static void Postfix(RecipesPopup __instance, RecipesPopupRequest request) { if (!((Object)(object)lastRequestedGood == (Object)null)) { __instance.Search(lastRequestedGood, (SearchType)1); lastRequestedGood = null; } } } private static GoodModel lastRequestedGood; private static bool TryOpenIngredientPanel(IMapObject obj) { //IL_00a5: Unknown result type (might be due to invalid IL or missing references) GoodModel val = null; NaturalResource val2 = (NaturalResource)(object)((obj is NaturalResource) ? obj : null); if (val2 != null) { val = val2.Model.refGood; } else { ResourceDeposit val3 = (ResourceDeposit)(object)((obj is ResourceDeposit) ? obj : null); if (val3 != null) { val = MB.Settings.GetGood(val3.GetProducedGood()); } else { Lake val4 = (Lake)(object)((obj is Lake) ? obj : null); if (val4 == null) { return false; } val = ((ResourceModel)val4.Model).production.good; } } if ((Object)(object)val == (Object)null) { return false; } lastRequestedGood = val; RecipesPopupRequest val5 = default(RecipesPopupRequest); ((RecipesPopupRequest)(ref val5))..ctor(val, true); GameMB.GameBlackboardService.RecipesPopupRequested.OnNext(val5); return true; } } public static class CycleUnbuiltBuildingsHotkey { private static bool cyclingMode; private static List unbuilt; private static int index; public static void OnUpdate(KeyboardShortcut forwardKey, KeyboardShortcut backwardKey) { //IL_0087: 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) if (!GameController.IsGameActive || MB.InputService.IsLocked()) { return; } if (((KeyboardShortcut)(ref forwardKey)).IsDown()) { if (!cyclingMode) { EnterMode(); } else { CycleNext(); } } else if (((KeyboardShortcut)(ref backwardKey)).IsDown()) { if (!cyclingMode) { EnterMode(); } else { CyclePrev(); } } else if (cyclingMode) { IInputService inputService = MB.InputService; DefaultActions inputConfig = MB.InputConfig; if (inputService.WasTriggered(((DefaultActions)(ref inputConfig)).Cancel, false)) { ExitMode(); } } } private static void EnterMode() { unbuilt = GetUnbuiltBuildings(); if (unbuilt.Count != 0) { cyclingMode = true; index = 0; ShowBuilding(unbuilt[index]); } } private static void ExitMode() { cyclingMode = false; unbuilt = null; index = 0; } public static void OnBlueprintUnlocked(BuildingModel model) { if (cyclingMode) { RefreshList(); } } private static void RefreshList() { List unbuiltBuildings = GetUnbuiltBuildings(); if (unbuilt == null || unbuiltBuildings.Count != unbuilt.Count) { unbuilt = unbuiltBuildings; if (unbuilt.Count == 0) { ExitMode(); } else { index = Mathf.Clamp(index, 0, unbuilt.Count - 1); } } } private static void CycleNext() { RefreshList(); if (cyclingMode && unbuilt != null && unbuilt.Count != 0) { index = (index + 1) % unbuilt.Count; ShowBuilding(unbuilt[index]); } } private static void CyclePrev() { RefreshList(); if (cyclingMode && unbuilt != null && unbuilt.Count != 0) { index = (index - 1 + unbuilt.Count) % unbuilt.Count; ShowBuilding(unbuilt[index]); } } private static void ShowBuilding(BuildingModel model) { if (GameMB.GameContentService.IsUnlocked(model) && GameMB.ConstructionService.CanConstruct(model)) { GameMB.GameBlackboardService.BuildingConstructionRequested.OnNext(model); } } private static List GetUnbuiltBuildings() { List value = GameMB.GameContentService.Buildings.Value; HashSet builtNames = new HashSet(GameMB.BuildingsService.Buildings.Values.Select((Building b) => ((Object)b.BuildingModel).name)); BuildingCategoryModel[] buildingCategories = MB.Settings.BuildingCategories; BuildingCategoryModel item = ((IEnumerable)buildingCategories).FirstOrDefault((Func)((BuildingCategoryModel c) => ((SO)c).Name == "Food Production")); BuildingCategoryModel item2 = ((IEnumerable)buildingCategories).FirstOrDefault((Func)((BuildingCategoryModel c) => ((SO)c).Name == "Industry")); BuildingCategoryModel item3 = ((IEnumerable)buildingCategories).FirstOrDefault((Func)((BuildingCategoryModel c) => ((SO)c).Name == "City Buildings")); HashSet allowedCategories = new HashSet { item, item2, item3 }; HashSet excludedNames = new HashSet { "Temporary Hearth (buildable)", "Storage (buildable)", "Hydrant" }; IEnumerable source = value.Where((BuildingModel model) => (Object)(object)model != (Object)null && (Object)(object)model.category != (Object)null && allowedCategories.Contains(model.category) && !excludedNames.Contains(((SO)model).Name) && GameMB.ConstructionService.ShouldShowInShop(model) && GameMB.GameContentService.IsUnlocked(model) && GameMB.ConstructionService.CanConstruct(model) && !builtNames.Contains(((Object)model).name) && (model.tags == null || !model.tags.Any((BuildingTagModel t) => t.iconTag == "Pipe" || t.iconTag == "Resource"))); return (from m in source orderby m.category.order, m.Order, ((SO)m).Name select m).ToList(); } } [HarmonyPatch(typeof(GameContentService), "Unlock")] public static class Patch_GameContentService_Unlock { public static void Postfix(BuildingModel building) { CycleUnbuiltBuildingsHotkey.OnBlueprintUnlocked(building); } } [HarmonyPatch(typeof(RecipesOverlaysManager), "OnHighlightStarted")] public static class DisableRecipeOverlayWhenWorkplaceOverlayOpen { private static bool Prefix() { BuildingWorkersOverlay val = Object.FindObjectOfType(); if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy) { return false; } return true; } } [HarmonyPatch] public static class HotkeyManager { public static ConfigEntry KeyGeneral; public static ConfigEntry KeyBuildings; public static ConfigEntry KeyCornerstones; public static ConfigEntry KeyTraders; public static ConfigEntry KeyEvents; public static ConfigEntry KeySpecies; public static ConfigEntry KeyTradingPost; public static ConfigEntry KeyCycleUnbuiltForward; public static ConfigEntry KeyCycleUnbuiltBackward; public static ConfigEntry KeyConsumptionControl; private static WikiPopup wikiPopup; private static WikiBasicPanel panelGeneral; private static WikiBuildingsPanel panelBuildings; private static WikiEffectsPanel panelCornerstones; private static WikiTradersPanel panelTraders; private static WikiRelicsPanel panelEvents; private static WikiRacesPanel panelSpecies; public static ConfigEntry KeyToggleConditionsHUD; static HotkeyManager() { //IL_0019: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) ConfigFile configFile = MoreHotkeysPlugin.ConfigFile; KeyToggleConditionsHUD = configFile.Bind("Hotkeys", "ToggleConditionsHUD", new KeyboardShortcut((KeyCode)108, Array.Empty()), "Toggle the Conditions HUD sync on/off"); KeyGeneral = configFile.Bind("Hotkeys", "EncyclopediaGeneral", new KeyboardShortcut((KeyCode)282, Array.Empty()), "Open Encyclopedia → General"); KeyBuildings = configFile.Bind("Hotkeys", "EncyclopediaBuildings", new KeyboardShortcut((KeyCode)283, Array.Empty()), "Open Encyclopedia → Buildings"); KeyCornerstones = configFile.Bind("Hotkeys", "EncyclopediaCornerstones", new KeyboardShortcut((KeyCode)284, Array.Empty()), "Open Encyclopedia → Cornerstones"); KeyTraders = configFile.Bind("Hotkeys", "EncyclopediaTraders", new KeyboardShortcut((KeyCode)285, Array.Empty()), "Open Encyclopedia → Traders"); KeyEvents = configFile.Bind("Hotkeys", "EncyclopediaEvents", new KeyboardShortcut((KeyCode)286, Array.Empty()), "Open Encyclopedia → Events"); KeySpecies = configFile.Bind("Hotkeys", "EncyclopediaSpecies", new KeyboardShortcut((KeyCode)287, Array.Empty()), "Open Encyclopedia → Species"); KeyTradingPost = configFile.Bind("Hotkeys", "OpenTradingPost", new KeyboardShortcut((KeyCode)106, Array.Empty()), "Toggle the Trading Post window"); KeyCycleUnbuiltBackward = configFile.Bind("Hotkeys", "CycleUnbuiltBackward", new KeyboardShortcut((KeyCode)120, Array.Empty()), "Cycle backward through unbuilt buildings"); KeyCycleUnbuiltForward = configFile.Bind("Hotkeys", "CycleUnbuiltForward", new KeyboardShortcut((KeyCode)99, Array.Empty()), "Cycle forward through unbuilt buildings"); } private static void ToggleConditionsHUD() { if (ConditionsHUDSync.ConditionsHUD == null) { return; } bool flag = !ConditionsHUDSync.ConditionsHUD.Value; ConditionsHUDSync.ConditionsHUD.Value = flag; GameObject val = GameObject.Find("HUD"); if ((Object)(object)val == (Object)null) { return; } Transform val2 = val.transform.Find("GameMenuPopup"); if ((Object)(object)val2 == (Object)null) { return; } Transform obj = val2.Find("Content"); GameObject val3 = ((obj != null) ? ((Component)obj).gameObject : null); object obj2; if (val3 == null) { obj2 = null; } else { Transform obj3 = val3.transform.Find("Main"); obj2 = ((obj3 != null) ? ((Component)obj3).gameObject : null); } GameObject val4 = (GameObject)obj2; if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val4 == (Object)null)) { if (!flag) { val3.SetActive(false); val4.SetActive(true); } else if (IsAnyPopupVisible()) { val3.SetActive(true); val4.SetActive(false); } } } private static bool IsAnyPopupVisible() { return ConditionsHUDSync.ConditionsHUD != null && ConditionsHUDSync.ConditionsHUD.Value && (bool)typeof(ConditionsHUDSync).GetMethod("IsAnyPopupVisible", BindingFlags.Static | BindingFlags.NonPublic).Invoke(null, null); } [HarmonyPatch(typeof(WikiPopup), "SetUp")] [HarmonyPostfix] private static void WikiPopup_SetUp(WikiPopup __instance) { wikiPopup = __instance; WikiCategoryPanel[] panels = __instance.panels; foreach (WikiCategoryPanel val in panels) { WikiBasicPanel val2 = (WikiBasicPanel)(object)((val is WikiBasicPanel) ? val : null); if (val2 != null) { panelGeneral = val2; continue; } WikiBuildingsPanel val3 = (WikiBuildingsPanel)(object)((val is WikiBuildingsPanel) ? val : null); if (val3 != null) { panelBuildings = val3; continue; } WikiEffectsPanel val4 = (WikiEffectsPanel)(object)((val is WikiEffectsPanel) ? val : null); if (val4 != null) { panelCornerstones = val4; continue; } WikiTradersPanel val5 = (WikiTradersPanel)(object)((val is WikiTradersPanel) ? val : null); if (val5 != null) { panelTraders = val5; continue; } WikiRelicsPanel val6 = (WikiRelicsPanel)(object)((val is WikiRelicsPanel) ? val : null); if (val6 != null) { panelEvents = val6; continue; } WikiRacesPanel val7 = (WikiRacesPanel)(object)((val is WikiRacesPanel) ? val : null); if (val7 != null) { panelSpecies = val7; } } } public static void OnUpdate() { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: 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_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value; if (ConditionsHUDSync.ConditionsHUD != null) { value = KeyToggleConditionsHUD.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleConditionsHUD(); } } if (GameController.IsGameActive && !MB.InputService.IsLocked()) { SuperSpeedHotkey.OnUpdate(); value = KeyGeneral.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleWiki((WikiCategoryPanel)(object)panelGeneral); } value = KeyBuildings.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleWiki((WikiCategoryPanel)(object)panelBuildings); } value = KeyCornerstones.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleWiki((WikiCategoryPanel)(object)panelCornerstones); } value = KeyTraders.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleWiki((WikiCategoryPanel)(object)panelTraders); } value = KeyEvents.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleWiki((WikiCategoryPanel)(object)panelEvents); } value = KeySpecies.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleWiki((WikiCategoryPanel)(object)panelSpecies); } value = KeyTradingPost.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { TryOpenTradingPost(); } ShiftCopyBuilding.OnUpdate(); CycleUnbuiltBuildingsHotkey.OnUpdate(KeyCycleUnbuiltForward.Value, KeyCycleUnbuiltBackward.Value); } } private static void ToggleWiki(WikiCategoryPanel panel) { if (!((Object)(object)panel == (Object)null) && !((Object)(object)wikiPopup == (Object)null)) { if (((Popup)wikiPopup).IsShown() && (Object)(object)wikiPopup.current == (Object)(object)panel) { ((Popup)wikiPopup).Hide(); } else { wikiPopup.OnCategoryRequested(panel); } } } private static void TryOpenTradingPost() { if ((Object)(object)SimplePanel.Instance != (Object)null && ((PreviewPanel)SimplePanel.Instance).IsActive()) { ((PreviewPanel)SimplePanel.Instance).Hide(); return; } if ((Object)(object)TraderPanel.Instance != (Object)null && ((Popup)TraderPanel.Instance).IsShown()) { ((Popup)TraderPanel.Instance).Hide(); return; } IBuildingsService buildingsService = GameMB.BuildingsService; Dictionary dictionary = ((buildingsService != null) ? buildingsService.Buildings : null); if (dictionary == null) { return; } foreach (KeyValuePair item in dictionary) { Building value = item.Value; TradingPost val = (TradingPost)(object)((value is TradingPost) ? value : null); if (val != null) { GameMB.GameInputService.Pick((IMapObject)(object)val); break; } } } } [HarmonyPatch] public static class LeaveManager { private static readonly string MARKER_NAME = "WorkerLeaveMarker"; private static Sprite markerSprite; private static readonly Dictionary leaveMode = new Dictionary(); private static readonly HashSet markedVillagers = new HashSet(); private static readonly Dictionary> userForcedDelivery = new Dictionary>(); private static readonly MethodInfo GetActiveTaskMI = typeof(ActorBrain).GetMethod("GetActiveTask", BindingFlags.Instance | BindingFlags.NonPublic); private static readonly HashSet FdPendingWorkers = new HashSet(); private static int GetMode(int id) { int value; return leaveMode.TryGetValue(id, out value) ? value : 0; } private static void SetMode(int id, int mode) { if (mode == 0) { leaveMode.Remove(id); markedVillagers.Remove(id); } else { leaveMode[id] = mode; markedVillagers.Add(id); } } private static Actor GetActorFromTask(object task) { return (task == null) ? null : Traverse.Create(task).Field("actor").GetValue(); } private static bool IsFarmer(Villager v) { return ((v != null) ? ((Actor)v).GetWorkplace() : null) is Farm; } private static bool IsGatherer(Villager v) { return ((v != null) ? ((Actor)v).GetWorkplace() : null) is GathererHut; } private static bool IsWoodcutter(Villager v) { return ((v != null) ? ((Actor)v).GetWorkplace() : null) is Camp; } private static void MarkForLeave(Villager v, Building b) { if (!((Object)(object)v == (Object)null)) { int id = ((Actor)v).Id; SetMode(id, (GetMode(id) + 1) % 2); ActorBrain brain = ((Actor)v).brain; if (brain != null) { object? obj = GetActiveTaskMI.Invoke(brain, null); ActorTask val = (ActorTask)((obj is ActorTask) ? obj : null); string arg = ((val != null) ? ((object)val).GetType().Name : "None"); Debug.Log((object)$"[LeaveMark] Marked villager {id} at building {((b != null) ? new int?(b.Id) : null)} | CurrentBehavior={arg}"); } } } private static void TryUnassign(int id, string seam) { if (GetMode(id) == 0) { return; } IVillagersService villagersService = GameMB.VillagersService; if (villagersService != null) { Villager villager = villagersService.GetVillager(id); if (!((Object)(object)villager == (Object)null)) { villagersService.ReleaseFromProfession(villager, false); leaveMode.Remove(id); markedVillagers.Remove(id); } } } private static void Remove(Villager v) { if (!((Object)(object)v == (Object)null)) { int id = ((Actor)v).Id; leaveMode.Remove(id); markedVillagers.Remove(id); } } private static bool HasAnyUserForcedDelivery(ProductionBuilding pb) { if (!userForcedDelivery.TryGetValue(((Building)pb).Id, out var value)) { return false; } foreach (KeyValuePair item in value) { if (item.Value) { return true; } } return false; } private static void PutMarkerIn(BuildingWorkerSlot slot) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Expected O, but got Unknown Transform val = ((Component)slot).transform.Find("StatusIcon"); if ((Object)(object)val == (Object)null || (Object)(object)val.Find(MARKER_NAME) != (Object)null) { return; } GameObject val2 = new GameObject(MARKER_NAME); val2.transform.SetParent(val, false); val2.SetActive(false); val2.transform.localPosition = new Vector3(-28f, 0f, 0f); TransformExtensions.SetScale(val2.transform, 0.4f); Image val3 = val2.AddComponent(); ((Graphic)val3).material = new Material(Shader.Find("UI/Default")); if ((Object)(object)markerSprite == (Object)null) { GameObject val4 = GameObject.Find("/HUD/RacesHUD/Slots/RaceHUDSlot (1)/BuildersIcon/Icon"); if ((Object)(object)val4 != (Object)null) { Image component = val4.GetComponent(); markerSprite = ((component != null) ? component.sprite : null); } } val3.sprite = markerSprite; } private static void UpdateMarkerStatus(WorkerStatusSlot slot) { Transform val = ((Component)slot).transform.Find("StatusIcon/" + MARKER_NAME); if (!((Object)(object)val == (Object)null) && !((Object)(object)slot.actor == (Object)null)) { ComponentExtensions.SetActive((Component)(object)val, GetMode(slot.actor.Id) > 0); } } [HarmonyPatch(typeof(BuildingWorkerSlot), "OnRightClick")] [HarmonyPrefix] public static bool BuildingWorkerSlot_OnRightClick_Prefix(BuildingWorkerSlot __instance) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) Actor actor = __instance.actor; Villager val = (Villager)(object)((actor is Villager) ? actor : null); if ((Object)(object)val == (Object)null) { return true; } IInputService inputService = MB.InputService; DefaultActions inputConfig = MB.InputConfig; if (inputService != null && inputService.IsTriggering(((DefaultActions)(ref inputConfig)).InputModifierControl)) { PutMarkerIn(__instance); MarkForLeave(val, (Building)(object)__instance.building); return false; } return true; } [HarmonyPatch(typeof(BuildingWorkerSlot), "SetUpActor")] [HarmonyPrefix] public static void BuildingWorkerSlot_SetUpActor_Prefix(BuildingWorkerSlot __instance) { PutMarkerIn(__instance); } [HarmonyPatch(typeof(WorkerStatusSlot), "SetUpActor")] [HarmonyPrefix] public static void WorkerStatusSlot_SetUpActor_Prefix(WorkerStatusSlot __instance) { UpdateMarkerStatus(__instance); } [HarmonyPatch(typeof(VillagersService), "RemoveFromProfession")] [HarmonyPostfix] public static void VillagersService_RemoveFromProfession_Postfix(Villager villager) { if ((Object)(object)villager != (Object)null) { Remove(villager); } } [HarmonyPatch(typeof(VillagersService), "ReleaseFromProfession")] [HarmonyPostfix] public static void VillagersService_ReleaseFromProfession_Postfix(Villager villager) { if ((Object)(object)villager != (Object)null) { Remove(villager); } } [HarmonyPatch(typeof(ActorTask), "Start")] [HarmonyPostfix] public static void ActorTask_Start_Postfix(ActorTask __instance) { if (__instance != null && __instance.GetState() != null) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (val != null && GetMode(((Actor)val).Id) == 1 && ((object)__instance).GetType() == typeof(IdleWalk) && !(((Actor)val).GetWorkplace() is FishingHut) && ((Actor)val).GetWorkplace() is ProductionBuilding) { TryUnassign(((Actor)val).Id, "IdleWalk"); } } } private static bool AnyDeliveryForced(Building b) { if ((Object)(object)b == (Object)null) { return false; } BuildingStorage component = ((Component)b).GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (component.Goods == null) { return false; } if (component.Goods.delivery == null) { return false; } foreach (KeyValuePair item in component.Goods.delivery) { if (item.Value != null && item.Value.deliveryForced) { return true; } } return false; } [HarmonyPatch(typeof(GoToActiveHearth), "OnStart")] [HarmonyPostfix] public static void GoToActiveHearth_OnStart_UniversalExit(GoToActiveHearth __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (!((Object)(object)val == (Object)null) && GetMode(((Actor)val).Id) == 1) { Building workplace = ((Actor)val).GetWorkplace(); if (!((Object)(object)workplace == (Object)null) && !AnyDeliveryForced(workplace) && !FdPendingWorkers.Contains(((Actor)val).Id)) { TryUnassign(((Actor)val).Id, "GoToActiveHearth"); } } } [HarmonyPatch(typeof(Rest), "OnSetUp")] [HarmonyPostfix] public static void Rest_OnSetUp_UniversalExit(Rest __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (!((Object)(object)val == (Object)null) && GetMode(((Actor)val).Id) == 1) { Building workplace = ((Actor)val).GetWorkplace(); if (!((Object)(object)workplace == (Object)null) && !AnyDeliveryForced(workplace) && !FdPendingWorkers.Contains(((Actor)val).Id)) { TryUnassign(((Actor)val).Id, "Rest"); } } } [HarmonyPatch(typeof(ActorTask), "OnComplete")] [HarmonyPostfix] public static void ActorTask_OnComplete_ReturnToStore_Postfix(ActorTask __instance) { if (!(__instance is ReturnToStore)) { return; } Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (val == null) { return; } int id = ((Actor)val).Id; if (GetMode(id) != 1) { return; } Building workplace = ((Actor)val).GetWorkplace(); if (!((Object)(object)workplace == (Object)null)) { if (AnyDeliveryForced(workplace)) { FdPendingWorkers.Add(id); } else if (!IsFarmer(val)) { TryUnassign(id, "ReturnToStore"); } } } private static void FarmerExit(Villager v, string seam) { if (GetMode(((Actor)v).Id) == 1) { TryUnassign(((Actor)v).Id, seam); } } [HarmonyPatch(typeof(Plow), "OnComplete")] [HarmonyPostfix] public static void Plow_OnComplete_Postfix(Plow __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if ((Object)(object)val != (Object)null && IsFarmer(val)) { FarmerExit(val, "Plow"); } } [HarmonyPatch(typeof(Plant), "OnComplete")] [HarmonyPostfix] public static void Plant_OnComplete_Postfix(Plant __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if ((Object)(object)val != (Object)null && IsFarmer(val)) { FarmerExit(val, "Plant"); } } [HarmonyPatch(typeof(Harvest), "OnComplete")] [HarmonyPostfix] public static void Harvest_OnComplete_Postfix(Harvest __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (!((Object)(object)val == (Object)null) && IsFarmer(val) && GetMode(((Actor)val).Id) != 0) { Building workplace = ((Actor)val).GetWorkplace(); ProductionBuilding val2 = (ProductionBuilding)(object)((workplace is ProductionBuilding) ? workplace : null); if (!((Object)(object)val2 == (Object)null) && !AnyDeliveryForced((Building)(object)val2)) { TryUnassign(((Actor)val).Id, "Harvest"); } } } [HarmonyPatch(typeof(EmptyLakeStorage), "OnComplete")] [HarmonyPostfix] public static void EmptyLakeStorage_OnComplete_FishermanUnassign(EmptyLakeStorage __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (!((Object)(object)val == (Object)null) && GetMode(((Actor)val).Id) == 1) { Building workplace = ((Actor)val).GetWorkplace(); FishingHut val2 = (FishingHut)(object)((workplace is FishingHut) ? workplace : null); if (!((Object)(object)val2 == (Object)null) && !AnyDeliveryForced((Building)(object)val2) && !FdPendingWorkers.Contains(((Actor)val).Id)) { TryUnassign(((Actor)val).Id, "Fisherman"); } } } [HarmonyPatch(typeof(EmptyBuildingStorage), "OnComplete")] [HarmonyPostfix] public static void EmptyBuildingStorage_OnComplete_FDUnassign(EmptyBuildingStorage __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if ((Object)(object)val == (Object)null) { return; } int id = ((Actor)val).Id; if (GetMode(id) == 1 && FdPendingWorkers.Contains(id)) { Building workplace = ((Actor)val).GetWorkplace(); if (!((Object)(object)workplace == (Object)null) && !AnyDeliveryForced(workplace)) { FdPendingWorkers.Remove(id); TryUnassign(id, "FD.Final"); } } } private static void ProductionBuildingExit(ActorTask task, string seam) { Actor actorFromTask = GetActorFromTask(task); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if ((Object)(object)val == (Object)null || GetMode(((Actor)val).Id) != 1) { return; } Building workplace = ((Actor)val).GetWorkplace(); ProductionBuilding val2 = (ProductionBuilding)(object)((workplace is ProductionBuilding) ? workplace : null); if (!((Object)(object)val2 == (Object)null) && (val2 is Workshop || val2 is FishingHut || val2 is RainCatcher || val2 is Extractor || val2 is BlightPost || val2 is Mine)) { if (val2 is BlightPost) { TryUnassign(((Actor)val).Id, seam); } else if (!AnyDeliveryForced((Building)(object)val2) && !FdPendingWorkers.Contains(((Actor)val).Id) && !HasAnyUserForcedDelivery(val2)) { TryUnassign(((Actor)val).Id, seam); } } } [HarmonyPatch(typeof(BaseMoveTask), "OnStart")] [HarmonyPostfix] public static void BaseMoveTask_OnStart_ProductionBuildingExit(BaseMoveTask __instance) { if (__instance is GoToWorkplace) { ProductionBuildingExit((ActorTask)(object)__instance, "GoToWorkplace"); } } [HarmonyPatch(typeof(CollectIngredients), "OnStart")] [HarmonyPostfix] public static void CollectIngredients_OnStart_ProductionBuildingExit(CollectIngredients __instance) { ProductionBuildingExit((ActorTask)(object)__instance, "CollectIngredients"); } [HarmonyPatch(typeof(EmptyBuildingStorage), "OnComplete")] [HarmonyPostfix] public static void EmptyBuildingStorage_OnComplete_Unassign(EmptyBuildingStorage __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if ((Object)(object)val == (Object)null) { return; } int id = ((Actor)val).Id; if (GetMode(id) == 1) { Building workplace = ((Actor)val).GetWorkplace(); if (!((Object)(object)workplace == (Object)null) && !AnyDeliveryForced(workplace) && !FdPendingWorkers.Contains(id) && (IsFarmer(val) || IsGatherer(val) || IsWoodcutter(val))) { TryUnassign(id, "EmptyBuildingStorage"); } } } [HarmonyPatch(typeof(ExecuteWorkingOnRelic), "OnStart")] [HarmonyPostfix] public static void ExecuteWorkingOnRelic_OnStart_Postfix(ExecuteWorkingOnRelic __instance) { Actor actorFromTask = GetActorFromTask(__instance); Villager val = (Villager)(object)((actorFromTask is Villager) ? actorFromTask : null); if (!((Object)(object)val == (Object)null) && GetMode(((Actor)val).Id) == 1) { Building workplace = ((Actor)val).GetWorkplace(); if (!((Object)(object)workplace == (Object)null) && !AnyDeliveryForced(workplace)) { TryUnassign(((Actor)val).Id, "Scout"); } } } } [BepInPlugin("MoreHotkeys", "More Hotkeys", "1.0.3")] public class MoreHotkeysPlugin : BaseUnityPlugin { public static ManualLogSource Log; public static ConfigFile ConfigFile; private void Awake() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; ConfigFile = ((BaseUnityPlugin)this).Config; Harmony val = new Harmony("MoreHotkeys"); ConditionsHUDSync.Init(ConfigFile, val, ((Component)this).gameObject); val.PatchAll(); Log.LogInfo((object)"MoreHotkeys loaded successfully."); } private void Update() { HotkeyManager.OnUpdate(); } } [HarmonyPatch(typeof(RaceNeedSlot))] [HarmonyPatch("UnityEngine.EventSystems.IPointerClickHandler.OnPointerClick")] public static class RaceNeedSlot_HousingClick_Patch { private static bool Prefix(RaceNeedSlot __instance, PointerEventData eventData) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown FieldInfo fieldInfo = AccessTools.Field(typeof(RaceNeedSlot), "race"); FieldInfo fieldInfo2 = AccessTools.Field(typeof(RaceNeedSlot), "need"); RaceModel val = (RaceModel)fieldInfo.GetValue(__instance); NeedModel val2 = (NeedModel)fieldInfo2.GetValue(__instance); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return true; } Debug.Log((object)("[MoreHotkeys] CLICK: race=" + ((SO)val).Name + ", need=" + ((SO)val2).Name)); if ((Object)(object)val2.referenceGood != (Object)null) { Debug.Log((object)"[MoreHotkeys] Food need → letting vanilla handle it"); return true; } if (IsHousingNeed(val2)) { Debug.Log((object)("[MoreHotkeys] Housing need clicked: " + ((SO)val2).Name)); BuildingModel houseForNeed = GetHouseForNeed(val, val2); if ((Object)(object)houseForNeed == (Object)null) { Debug.Log((object)"[MoreHotkeys] No house found for this need"); return false; } TryBuild(houseForNeed); return false; } return true; } private static bool IsHousingNeed(NeedModel need) { string name = ((SO)need).Name; return name == "Any Housing" || name.EndsWith("Housing"); } private static BuildingModel GetHouseForNeed(RaceModel race, NeedModel need) { if (((SO)need).Name == "Any Housing") { return MB.Settings.GetBuilding("Shelter"); } return (BuildingModel)(((SO)race).Name switch { "Human" => MB.Settings.GetBuilding("Human House"), "Beaver" => MB.Settings.GetBuilding("Beaver House"), "Lizard" => MB.Settings.GetBuilding("Lizard House"), "Harpy" => MB.Settings.GetBuilding("Harpy House"), "Foxes" => MB.Settings.GetBuilding("Fox House"), "Frog" => MB.Settings.GetBuilding("Frog House"), "Bat" => MB.Settings.GetBuilding("Bat House"), _ => null, }); } private static void TryBuild(BuildingModel building) { if (!((Object)(object)building == (Object)null)) { if (!GameMB.GameContentService.IsUnlocked(building)) { Debug.Log((object)("[MoreHotkeys] House locked: " + ((SO)building).Name)); return; } if (!GameMB.ConstructionService.CanConstruct(building)) { Debug.Log((object)("[MoreHotkeys] Cannot construct: " + ((SO)building).Name)); return; } Debug.Log((object)("[MoreHotkeys] Requesting construction: " + ((SO)building).Name)); GameMB.GameBlackboardService.BuildingConstructionRequested.OnNext(building); } } } public static class ShiftCopyBuilding { public static void OnUpdate() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!GameController.IsGameActive || ShouldIgnoreInput()) { return; } IInputService inputService = MB.InputService; DefaultActions inputConfig = MB.InputConfig; if (!inputService.WasTriggered(((DefaultActions)(ref inputConfig)).CopyBuilding, false)) { return; } IMapObject value = GameMB.GameInputService.MouseoverObject.Value; if (value != null) { Building val = (Building)(object)((value is Building) ? value : null); if (val != null) { TryCopyMainBuilding(val); } else { TryCopyResourceBuilding(value); } } } private static bool ShouldIgnoreInput() { return (Object)(object)BuildingPanel.currentBuilding != (Object)null || !GameMB.ModeService.Idle.Value || MB.InputService.IsOverUI(); } private static void TryCopyMainBuilding(Building building) { switch (((SO)building.BuildingModel).Name) { case "Small Hearth": BuildConditional(MB.Settings.GetBuilding("Temporary Hearth (buildable)")); break; case "Main Storage (not-buildable)": BuildConditional(MB.Settings.GetBuilding("Storage (buildable)")); break; case "Path": BuildConditional(MB.Settings.GetBuilding("Path")); break; case "Paved Road": BuildConditional(MB.Settings.GetBuilding("Paved Road")); break; case "Reinforced Road": BuildConditional(MB.Settings.GetBuilding("Reinforced Road")); break; } } private static void TryCopyResourceBuilding(IMapObject obj) { //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) ResourceDeposit val = (ResourceDeposit)(object)((obj is ResourceDeposit) ? obj : null); if (val != null) { if (!val.State.isAvailable || !GameMB.DepositsService.HutsMatrix.ContainsKey(val.Model)) { return; } foreach (GathererHutModel item in GameMB.DepositsService.HutsMatrix[val.Model]) { if (BuildConditional((BuildingModel)(object)item)) { return; } } } NaturalResource val2 = (NaturalResource)(object)((obj is NaturalResource) ? obj : null); if (val2 != null && val2.State.isAvailable) { BuildConditional(MB.Settings.GetBuilding("Woodcutters Camp")); return; } Spring val3 = (Spring)(object)((obj is Spring) ? obj : null); if (val3 != null && val3.State.isAvailable) { BuildConditional((BuildingModel)(object)MB.Settings.rainpunkConfig.extractor); return; } Field val4 = (Field)(object)((obj is Field) ? obj : null); if (val4 != null) { if (!GameMB.OreService.HasAvailableOre(val4.Pos)) { return; } Ore ore = GameMB.OreService.GetOre(val4.Pos); foreach (MineModel item2 in GameMB.OreService.MinesMatrix[ore.Model.refGood.Name]) { if (BuildConditional((BuildingModel)(object)item2)) { return; } } } Lake val5 = (Lake)(object)((obj is Lake) ? obj : null); if (val5 != null) { if (val5.State.isAvailable && !BuildConditional(MB.Settings.GetBuilding("Fishing Hut"))) { BuildConditional(MB.Settings.GetBuilding("Primitive Fishing Hut")); } } else if (obj is Ore) { BuildConditional(MB.Settings.GetBuilding("Mine")); } } private static bool BuildConditional(BuildingModel building) { if ((Object)(object)building == (Object)null) { return false; } if (GameMB.GameContentService.IsUnlocked(building) && GameMB.ConstructionService.CanConstruct(building)) { GameMB.GameBlackboardService.BuildingConstructionRequested.OnNext(building); return true; } return false; } } [HarmonyPatch] internal static class SuperSpeedHotkey { public const float SUPER_SPEED_SCALE = 5f; public static ConfigEntry KeyFiveX; static SuperSpeedHotkey() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) KeyFiveX = MoreHotkeysPlugin.ConfigFile.Bind("Hotkeys", "5XSpeed", new KeyboardShortcut((KeyCode)53, Array.Empty()), "Instantly set game speed to 5×"); } public static void OnUpdate() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) KeyboardShortcut value = KeyFiveX.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { GameMB.TimeScaleService.Change(5f, true, false); } } [HarmonyPatch(typeof(TimeScalePanel), "SetUp")] [HarmonyPostfix] private static void TimeScalePanel_SetUp(TimeScalePanel __instance) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)__instance).transform; Transform val = transform.Find("Slot (5)"); if (!((Object)(object)val == (Object)null)) { Transform val2 = Object.Instantiate(val, transform); ((Object)val2).name = "Slot (6)"; val2.localPosition = new Vector3(90f, 90f, 0f); TimeScaleSlot component = ((Component)val2).GetComponent(); component.timeScale = 5f; TextMeshProUGUI component2 = ((Component)val2.Find("Desc")).GetComponent(); ((TMP_Text)component2).text = "x5"; } } [HarmonyPatch(typeof(TimeScaleService), "SpeedUp")] [HarmonyPrefix] private static bool TimeScaleService_SpeedUp(TimeScaleService __instance) { float value = __instance.Scale.Value; if (value == 5f) { Serviceable.SoundsManager.PlayFailedSound(); return false; } if (value == TimeScaleService.Speeds.Last()) { __instance.Change(5f, true, false); return false; } return true; } [HarmonyPatch(typeof(TimeScaleService), "SlowDown")] [HarmonyPrefix] private static bool TimeScaleService_SlowDown(TimeScaleService __instance) { float value = __instance.Scale.Value; if (value == 5f) { __instance.Change(TimeScaleService.Speeds.Last(), true, false); return false; } return true; } [HarmonyPatch(typeof(WoodcuttersHUD), "SetUp")] [HarmonyPostfix] private static void MoveWoodcuttersHUD(WoodcuttersHUD __instance) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) ((Component)__instance).transform.localPosition = new Vector3(120f, -71f, 0f); } } public static class PluginInfo { public const string PLUGIN_GUID = "MoreHotkeys"; public const string PLUGIN_NAME = "MoreHotkeys"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }