Decompiled source of ForestCreator v1.0.7
ForestCreator.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using ATS_API.Buildings; using ATS_API.Effects; using ATS_API.Helpers; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Cysharp.Threading.Tasks; using Eremite; using Eremite.Buildings; using Eremite.Buildings.UI; using Eremite.Buildings.UI.Rainpunk; using Eremite.Characters; using Eremite.Characters.Automatons; using Eremite.Characters.Behaviours; using Eremite.Characters.Villagers; using Eremite.Controller; using Eremite.Model; using Eremite.Model.Effects; using Eremite.Model.Sound; using Eremite.Model.State; using Eremite.Services; using Eremite.View; using Eremite.View.HUD; using Eremite.View.HUD.Construction; using Eremite.View.Menu.Pick; using Eremite.View.UI; using Eremite.WorldMap; using HarmonyLib; using Microsoft.CodeAnalysis; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("ForestCreator")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.7.0")] [assembly: AssemblyInformationalVersion("1.0.7+068852371e0e48e0e5714faded8aa51c616de3ab")] [assembly: AssemblyProduct("ForestCreator")] [assembly: AssemblyTitle("ForestCreator")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.7.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } } namespace ForestCreator { [BepInPlugin("ForestCreator", "ForestCreator", "1.0.7")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { internal sealed class SpawnerGroupRequest : GroupRequest { private readonly SpawnerModel _model; public override BuildingModel Model => (BuildingModel)(object)_model; public SpawnerGroupRequest(SpawnerModel model, IConstructionPlanner planner, Action onFinished) : base(planner, onFinished) { _model = model; } public override void Spawn(List<Vector2Int> positions) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) int num = 0; if (positions != null) { foreach (Vector2Int position in positions) { if (num >= 400) { break; } Spawner val = null; try { if (GameMB.MapService.IsFieldEmpty(position)) { val = ((Serviceable)this).Instantiate<Spawner>(_model.prefab); if (!((Object)(object)val == (Object)null)) { val.SetUp(_model, new SpawnerState(_model, GameMB.StateService.GetUniqueId(), 0, GameMB.ConstructionService.GetConstructionCostFor((BuildingModel)(object)_model))); ((Building)val).SetPosition(VectorExtensions.ToWorld(position)); ((Building)val).ManualPlacingFinished(); num++; } } } catch (Exception) { try { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)val).gameObject); } } catch { } } } } if (num > 0) { try { Serviceable.SoundsManager.PlaySoundEffect(Serviceable.Sounds.BuildingPlaced); } catch { } } } } private const string LayoutLogPath = "C:\\Users\\WenQuan\\Doubao\\chats\\2026-11-07\\new-chat\\fc_diag.txt"; private static bool _fcNativePanelDumped; private static FieldInfo _brainStackField; internal const string FC_WorshipBuilderName = "Forest Creator Fervent Worship"; internal const string FC_ProtectionBuilderName = "Forest Creator Divine Protection"; private static string _fcWorshipEffectName; private static string _fcProtectionEffectName; private static HookedEffectModel _fcWorshipModel; private static HookedEffectModel _fcProtectionModel; private static bool _fcCornerstonesRegistered; private static bool _fcCornerstonesFailed; private static bool _fcWorshipActive; private static bool _fcProtectionActive; private const string PathGameContentServiceIsUnlocked = "IsUnlocked"; private static readonly string[] PlantingDisplayKeywords = new string[5] { "温室", "护林", "greenhouse", "forester", "grove" }; private static readonly string[] NonShopBuildingNames = new string[1] { "Homestead" }; private static readonly string[] QueryOnlyUnlockNames = new string[1] { "Homestead" }; private static int _hearthProductionLogBudget = 24; private static readonly string[] LowTierCampNames = new string[4] { "Primitive Forager's Camp", "Primitive Herbalist's Camp", "Primitive Trapper's Camp", "Primitive Fishing Hut" }; private static bool _metaCampsCleaned; private const float SlotRadius = 125f; private static bool _suppressCycleYears; private static readonly string[] DragPlacingSpawnerNames = new string[1] { "Biome Grass Spawner" }; private static readonly string[] DragPlacingSpawnerDisplayKeywords = new string[5] { "沃土", "肥沃", "Fertile Soil", "FertileSoil", "Fertile" }; private static SpawnerModel ActiveDragSpawner; private const int DragPlacingMaxTilesPerDrag = 400; private const bool VerboseSpawnerDragDiagnostics = true; private static readonly string[] FC_StartingCornerstoneNames = new string[7] { "Hauling Cart in All Warehouses", "2 Hauling Carts in Main Warehouse", "Accidental Barrels", "Amber for Wood", "Woodcutting speed for water", "Lumber Speed +50", "[Altar] Villager for glade" }; private static bool _steamDlcVerifyFailed; internal const string FC_TownHallBuilderName = "Forest Creator Town Hall"; internal const string FC_TownHallCurrency = "[Valuable] Amber"; internal const string FC_TownHallCostGood = "[Mat Raw] Wood"; internal const int FC_TownHallPrice = 2; private const string FC_LookTemplateName = "Holy Temple"; internal static InstitutionBuildingBuilder _fcTownHallBuilder; internal static string _fcTownHallName; private static bool _fcTownHallRegistered; private static bool _fcTownHallFailed; private static bool _fcTownHallPoolDone; private static GameContentService _fcContentSvc; private static bool _fcLookApplied; public static Plugin Instance; private Harmony harmony; internal static void LogInfo(string msg) { try { Plugin instance = Instance; if (instance != null) { ManualLogSource logger = ((BaseUnityPlugin)instance).Logger; if (logger != null) { logger.LogInfo((object)msg); } } } catch { } } internal static void LogError(string msg) { try { Plugin instance = Instance; if (instance != null) { ManualLogSource logger = ((BaseUnityPlugin)instance).Logger; if (logger != null) { logger.LogError((object)msg); } } } catch { } } [Conditional("DEBUG")] internal static void FileLog(string msg) { try { string directoryName = Path.GetDirectoryName("C:\\Users\\WenQuan\\Doubao\\chats\\2026-11-07\\new-chat\\fc_diag.txt"); if (!Directory.Exists(directoryName)) { Directory.CreateDirectory(directoryName); } File.AppendAllText("C:\\Users\\WenQuan\\Doubao\\chats\\2026-11-07\\new-chat\\fc_diag.txt", msg + "\n"); } catch { } try { Plugin instance = Instance; if (instance != null) { ManualLogSource logger = ((BaseUnityPlugin)instance).Logger; if (logger != null) { logger.LogInfo((object)("[DIAG] " + msg)); } } } catch { } } internal static void DumpNativePanelOnce(Transform root) { if (_fcNativePanelDumped || (Object)(object)root == (Object)null) { return; } _fcNativePanelDumped = true; try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("==== NATIVE PANEL DUMP (TownHall reference) ===="); WalkUI(root, 0, stringBuilder); } catch (Exception) { } } private static void WalkUI(Transform t, int depth, StringBuilder sb) { //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)t == (Object)null || depth > 5 || sb.Length > 150000) { return; } try { sb.Append(' ', depth * 2).Append('[').Append(((Object)((Component)t).gameObject).name) .Append(']'); if (!((Component)t).gameObject.activeSelf) { sb.Append(" inactive"); } Image component = ((Component)t).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { sb.Append(" img(spr=").Append(((Object)(object)component.sprite != (Object)null) ? ((Object)component.sprite).name : "null").Append(", type=") .Append(component.type) .Append(", c=") .Append(((Graphic)component).color) .Append(')'); } TMP_Text component2 = ((Component)t).GetComponent<TMP_Text>(); if ((Object)(object)component2 != (Object)null) { sb.Append(" tmp(\"").Append((component2.text ?? "").Replace("\n", "\\n")).Append("\" font=") .Append(((Object)(object)component2.font != (Object)null) ? ((Object)component2.font).name : "null") .Append(" size=") .Append(component2.fontSize) .Append(" c=") .Append(((Graphic)component2).color) .Append(')'); } if ((Object)(object)((Component)t).GetComponent<Button>() != (Object)null) { sb.Append(" <BUTTON>"); } if ((Object)(object)((Component)t).GetComponent<ScrollRect>() != (Object)null) { sb.Append(" <SCROLL>"); } sb.AppendLine(); for (int i = 0; i < t.childCount; i++) { WalkUI(t.GetChild(i), depth + 1, sb); } } catch { } } private static void DumpImages(GameObject go, string tag) { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("IMAGES[" + tag + "] go=" + ((Object)go).name); Image[] componentsInChildren = go.GetComponentsInChildren<Image>(true); foreach (Image val in componentsInChildren) { object[] obj = new object[4] { ((Object)((Component)val).gameObject).name, null, null, null }; Sprite sprite = val.sprite; obj[1] = ((sprite != null) ? ((Object)sprite).name : null); obj[2] = ((Component)val).gameObject.activeSelf; obj[3] = (Object)(object)((Graphic)val).material != (Object)null; stringBuilder.Append(string.Format(" |[{0} spr={1} act={2} mat={3}]", obj)); } } catch (Exception) { } } private static void DumpTree(BuildingsPickScreen __instance, string tag) { try { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("TREE[" + tag + "] root=" + ((Object)__instance).name); Transform transform = ((Component)__instance).transform; DumpNode(stringBuilder, (RectTransform)(object)((transform is RectTransform) ? transform : null), 0, 3); } catch (Exception) { } } private static void DumpNode(StringBuilder sb, RectTransform rt, int depth, int maxDepth) { //IL_0031: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown if ((Object)(object)rt == (Object)null || depth > maxDepth) { return; } object[] obj = new object[5] { new string('.', depth), ((Object)rt).name, rt.anchoredPosition.y, null, null }; Rect rect = rt.rect; obj[3] = ((Rect)(ref rect)).height; obj[4] = ((Transform)rt).position.y; sb.Append(string.Format(" |{0}[{1} apY={2:F0} h={3:F0} worldY={4:F0}]", obj)); foreach (Transform item in (Transform)rt) { Transform val = item; DumpNode(sb, (RectTransform)(object)((val is RectTransform) ? val : null), depth + 1, maxDepth); } } [HarmonyPatch(typeof(BuildingsPanel), "Start")] [HarmonyPostfix] private static void MakeRainCatchersRepeatable() { try { Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null); if ((Object)(object)val == (Object)null || val.Buildings == null) { return; } int num = 0; BuildingModel[] buildings = val.Buildings; foreach (BuildingModel val2 in buildings) { if (!((Object)(object)val2 == (Object)null) && val2 is RainCatcherModel && !val2.repeatable) { val2.repeatable = true; num++; } } _ = 0; } catch (Exception) { } } [HarmonyPatch(typeof(BuildingsPanel), "Start")] [HarmonyPostfix] private static void MakeTradingPostMovable() { try { Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null); if ((Object)(object)val == (Object)null || val.Buildings == null) { return; } int num = 0; BuildingModel[] buildings = val.Buildings; foreach (BuildingModel val2 in buildings) { if (!((Object)(object)val2 == (Object)null) && val2 is TradingPostModel && !val2.movable) { val2.movable = true; num++; } } _ = 0; } catch (Exception) { } } [HarmonyPatch(typeof(GameController), "StartGame")] [HarmonyPostfix] private static void ApplyCheatsAtStart() { try { if (!GameController.IsGameActive) { return; } try { SO.HostilityService.AddEffectHostility(FCConfig.StartHostility.Value); } catch { } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR ApplyCheatsAtStart: " + ex.Message)); } } [HarmonyPatch(typeof(ReputationService), "GetReputationPenaltySpeed")] [HarmonyPostfix] private static void PatchImpatienceRate(ref float __result) { __result *= FCConfig.ImpatienceMultiplier.Value; } [HarmonyPatch(typeof(EffectsService), "GetProfessionBonusSpeed")] [HarmonyPostfix] private static void PatchWoodcutterWalk(string profession, ref float __result) { if (profession != null && profession.IndexOf("wood", StringComparison.OrdinalIgnoreCase) >= 0) { __result += FCConfig.WoodcutterWalkBonus.Value; } } [HarmonyPatch(typeof(EffectsService), "GetInternalProductionRate")] [HarmonyPostfix] private static void PatchWoodcutterWork(Building building, ref float __result) { try { if (!((Object)(object)building == (Object)null)) { BuildingModel buildingModel = building.BuildingModel; ProfessionModel val = (((Object)(object)buildingModel != (Object)null) ? buildingModel.Profession : null); string text = (((Object)(object)val != (Object)null) ? ((Object)val).name : null); if (text != null && text.IndexOf("wood", StringComparison.OrdinalIgnoreCase) >= 0) { __result *= FCConfig.WoodcutterWorkMultiplier.Value; } } } catch { } } [HarmonyPatch(typeof(DailyService), "GetRewardsFor")] [HarmonyPostfix] private static void PatchDailyRewards(ref List<MetaCurrency> __result) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) try { if (__result != null) { float value = FCConfig.DailyRewardMultiplier.Value; for (int i = 0; i < __result.Count; i++) { __result[i] *= value; } } } catch { } } [HarmonyPatch(typeof(MetaEconomyService), "GetCurrenciesFor")] [HarmonyPostfix] private static void PatchRegularRewards(ref List<MetaCurrency> __result) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) try { if (__result != null) { float value = FCConfig.RegularRewardMultiplier.Value; for (int i = 0; i < __result.Count; i++) { __result[i] *= value; } } } catch { } } [HarmonyPatch(typeof(PerksService), "Sort")] [HarmonyPrefix] private static void CleanBrokenPerks(PerksService __instance) { try { FieldInfo field = ((object)__instance).GetType().GetField("<SortedPerks>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (field == null || !(field.GetValue(__instance) is IList list)) { return; } List<object> list2 = new List<object>(); foreach (object item in list) { FieldInfo fieldInfo = item.GetType().GetField("name") ?? item.GetType().GetField("perkName"); if (string.IsNullOrEmpty((fieldInfo != null) ? (fieldInfo.GetValue(item) as string) : null)) { list2.Add(item); } } foreach (object item2 in list2) { list.Remove(item2); ((BaseUnityPlugin)Instance).Logger.LogInfo((object)"FC: removed broken empty-name PerkState from SortedPerks"); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC CLEAN perks: " + ex.Message)); } } [HarmonyPatch(typeof(MainController), "OnServicesReady")] [HarmonyPostfix] private static void DoubleCoverageRange() { try { Settings settings = MainController.Instance.Settings; if ((Object)(object)settings == (Object)null || settings.Buildings == null) { return; } int num = 0; int num2 = 0; BuildingModel[] buildings = settings.Buildings; foreach (BuildingModel val in buildings) { HearthModel val2 = (HearthModel)(object)((val is HearthModel) ? val : null); if (val2 != null) { val2.hubRange *= FCConfig.HearthRangeMultiplier.Value; num++; continue; } CampModel val3 = (CampModel)(object)((val is CampModel) ? val : null); if (val3 != null) { val3.maxDistance *= FCConfig.CampRangeMultiplier.Value; num2++; } } ((BaseUnityPlugin)Instance).Logger.LogInfo((object)$"FC: doubled coverage for {num} hearths and {num2} camps"); } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC COVERAGE: " + ex.Message)); } } [HarmonyPatch(typeof(ProductionCalculator), "GetProductionMultiplier")] [HarmonyPostfix] private static void Robot_ProductionMultiplier(Building __0, RecipeModel __1, Actor __2, float __3, ref int __result) { try { if (__2 is Automaton) { __result *= FCConfig.RobotProductionMultiplier.Value; } } catch { } } [HarmonyPatch(typeof(EffectsService), "GetProductionRate")] [HarmonyPostfix] private static void Robot_ProductionRate(Building __0, Actor __1, RecipeModel __2, ref float __result) { try { if (__1 is Automaton) { __result *= FCConfig.RobotProductionRateMultiplier.Value; } } catch { } } [HarmonyPatch(typeof(MB), "GetText", new Type[] { typeof(string) })] [HarmonyPostfix] private static void MB_GetText(string key, ref string __result) { try { if (key == "GameUI_WorkerSlot_AutomatonTooltip_Desc") { __result = "使用先进的机器人技术代替工人工作,生产时间大幅缩短,产出倍率大幅提升。"; } } catch { } } private static bool ActorBrain_StackEmpty(ActorBrain brain) { try { if (_brainStackField == null) { _brainStackField = AccessTools.Field(typeof(ActorBrain), "stack"); } if (_brainStackField == null) { return false; } return !(_brainStackField.GetValue(brain) is Stack<ActorTask> stack) || stack.Count == 0; } catch { return false; } } [HarmonyPatch(typeof(ActorBrain), "GetCurrentIcon")] [HarmonyPrefix] private static bool ActorBrain_GetCurrentIcon_Prefix(ActorBrain __instance, ref Sprite __result) { if (ActorBrain_StackEmpty(__instance)) { __result = null; return false; } return true; } [HarmonyPatch(typeof(ActorBrain), "GetCurrentDescription")] [HarmonyPrefix] private static bool ActorBrain_GetCurrentDescription_Prefix(ActorBrain __instance, ref string __result) { if (ActorBrain_StackEmpty(__instance)) { __result = ""; return false; } return true; } [HarmonyPatch(typeof(ActorBrain), "GetCurrentProgress")] [HarmonyPrefix] private static bool ActorBrain_GetCurrentProgress_Prefix(ActorBrain __instance, ref float __result) { if (ActorBrain_StackEmpty(__instance)) { __result = 0f; return false; } return true; } [HarmonyPatch(typeof(ActorBrain), "GetCurrentGood")] [HarmonyPrefix] private static bool ActorBrain_GetCurrentGood_Prefix(ActorBrain __instance, ref Good __result) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (ActorBrain_StackEmpty(__instance)) { __result = Good.None; return false; } return true; } [HarmonyPatch(typeof(ActorTasksList), "OnStart")] [HarmonyPostfix] private static void ActorTasksList_OnStart_Postfix(ActorTasksList __instance) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Expected O, but got Unknown try { object? obj = AccessTools.Field(typeof(ActorTask), "brain")?.GetValue(__instance); ActorBrain val = (ActorBrain)((obj is ActorBrain) ? obj : null); object? obj2 = AccessTools.Field(typeof(ActorTask), "actor")?.GetValue(__instance); Actor val2 = (Actor)((obj2 is Actor) ? obj2 : null); if (val != null && !((Object)(object)val2 == (Object)null)) { FieldInfo fieldInfo = AccessTools.Field(typeof(ActorBrain), "stack"); if (!(fieldInfo == null) && (!(fieldInfo.GetValue(val) is Stack<ActorTask> { Count: >0 } stack) || (object)stack.Peek() == __instance)) { IdleWait val3 = new IdleWait(); ((ActorTask)val3).SetUp(val2, val, new ActorTaskState((ActorTaskType)204)); val.PushTask((ActorTask)(object)val3); } } } catch { } } [HarmonyPatch(typeof(FulfillNeeds), "CanStart")] [HarmonyPrefix] private static bool FulfillNeeds_CanStart_Prefix(FulfillNeeds __instance, ref bool __result) { if (AccessTools.Field(typeof(FulfillNeeds), "villager")?.GetValue(__instance) == null) { __result = false; return false; } return true; } [HarmonyPatch(typeof(BaseInstantTask), "GetIcon")] [HarmonyPrefix] private static bool BaseInstantTask_GetIcon_Prefix(ref Sprite __result) { __result = null; return false; } [HarmonyPatch(typeof(BaseInstantTask), "GetDescription")] [HarmonyPrefix] private static bool BaseInstantTask_GetDescription_Prefix(ref string __result) { __result = ""; return false; } internal static void CreateCustomCornerstones() { if (_fcCornerstonesRegistered || _fcCornerstonesFailed) { return; } try { HookedEffectBuilder obj = CreateFerventWorship(); HookedEffectBuilder val = CreateDivineProtection(); _fcWorshipModel = ((EffectBuilder<HookedEffectModel>)(object)obj).EffectModel; _fcProtectionModel = ((EffectBuilder<HookedEffectModel>)(object)val).EffectModel; _fcWorshipEffectName = (((Object)(object)_fcWorshipModel != (Object)null) ? ((Object)_fcWorshipModel).name : null); _fcProtectionEffectName = (((Object)(object)_fcProtectionModel != (Object)null) ? ((Object)_fcProtectionModel).name : null); _fcCornerstonesRegistered = true; ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("FC CORNERSTONE registered: " + _fcWorshipEffectName + " / " + _fcProtectionEffectName)); } catch (Exception ex) { _fcCornerstonesFailed = true; ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateCustomCornerstones: " + ex)); } } private static HookedEffectBuilder CreateFerventWorship() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown HookedEffectBuilder val = new HookedEffectBuilder("ForestCreator", "Forest Creator Fervent Worship", FC_IconPath("fc_blue_dragon.png")); ((EffectBuilder<HookedEffectModel>)val).SetPositive(true); ((EffectBuilder<HookedEffectModel>)val).SetRarity((EffectRarity)5); ((EffectBuilder<HookedEffectModel>)val).SetObtainedAsCornerstone(100); ((EffectBuilder<HookedEffectModel>)val).SetAvailableInAllBiomesAndSeasons(); ((EffectBuilder<HookedEffectModel>)val).SetDrawLimit(1); ((EffectBuilder<HookedEffectModel>)val).SetLabel("ForestCreator", (SystemLanguage)10); ((EffectBuilder<HookedEffectModel>)val).SetLabel("森林造物主", (SystemLanguage)40); ((EffectBuilder<HookedEffectModel>)val).SetDisplayName("Forest Creator's Fervent Worship", (SystemLanguage)10); ((EffectBuilder<HookedEffectModel>)val).SetDescription("The settlers of this town worship the Forest Creator with such fervor that they no longer wish to leave. Villagers never leave the settlement.", (SystemLanguage)10); ((EffectBuilder<HookedEffectModel>)val).SetDisplayName("森林造物主的狂热崇拜", (SystemLanguage)40); ((EffectBuilder<HookedEffectModel>)val).SetDescription("定居点的居民对森林造物主狂热崇拜,因此不会想要离开。", (SystemLanguage)40); return val; } private static HookedEffectBuilder CreateDivineProtection() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008b: Expected O, but got Unknown HookedEffectBuilder val = new HookedEffectBuilder("ForestCreator", "Forest Creator Divine Protection", FC_IconPath("fc_gold_dragon.png")); ((EffectBuilder<HookedEffectModel>)val).SetPositive(true); ((EffectBuilder<HookedEffectModel>)val).SetRarity((EffectRarity)5); ((EffectBuilder<HookedEffectModel>)val).SetObtainedAsCornerstone(100); ((EffectBuilder<HookedEffectModel>)val).SetAvailableInAllBiomesAndSeasons(); ((EffectBuilder<HookedEffectModel>)val).SetDrawLimit(1); ((EffectBuilder<HookedEffectModel>)val).SetLabel("ForestCreator", (SystemLanguage)10); ((EffectBuilder<HookedEffectModel>)val).SetLabel("森林造物主", (SystemLanguage)40); ((EffectBuilder<HookedEffectModel>)val).SetDisplayName("Forest Creator's Divine Protection", (SystemLanguage)10); ((EffectBuilder<HookedEffectModel>)val).SetDescription("The Forest Creator watches over this town, so its settlers cannot die abnormally. Villagers never die from starvation, disease, events or assaults.", (SystemLanguage)10); ((EffectBuilder<HookedEffectModel>)val).SetDisplayName("森林造物主的神圣庇佑", (SystemLanguage)40); ((EffectBuilder<HookedEffectModel>)val).SetDescription("森林造物主庇护着定居点的居民,因此定居点的居民不会异常死去。", (SystemLanguage)40); return val; } private static string FC_IconPath(string fileName) { try { string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(Path.Combine(directoryName, "Assets"), fileName); if (File.Exists(text)) { return text; } } } catch { } ((BaseUnityPlugin)Instance).Logger.LogWarning((object)("FC CORNERSTONE icon not found next to plugin, falling back to plugins-wide search: " + fileName)); return fileName; } internal static void FC_InjectCustomCornerstones() { InjectCustomCornerstone(_fcWorshipModel, "worship"); InjectCustomCornerstone(_fcProtectionModel, "protection"); } private static void InjectCustomCornerstone(HookedEffectModel model, string tag) { if ((Object)(object)model == (Object)null || FC_IsAlreadyApplied(((Object)model).name)) { return; } try { ((EffectModel)model).Apply((EffectContextType)0, (string)null, 0); } catch (Exception arg) { ((BaseUnityPlugin)Instance).Logger.LogError((object)$"FC ERR inject cornerstone '{((Object)model).name}': {arg}"); } } internal static void SyncCustomCornerstoneFlags() { _fcWorshipActive = (Object)(object)_fcWorshipModel != (Object)null && FC_IsAlreadyApplied(((Object)_fcWorshipModel).name); _fcProtectionActive = (Object)(object)_fcProtectionModel != (Object)null && FC_IsAlreadyApplied(((Object)_fcProtectionModel).name); } internal static bool FC_IsAlreadyApplied(string effectName) { if (string.IsNullOrEmpty(effectName)) { return false; } try { IStateService stateService = Serviceable.StateService; if (stateService == null) { return false; } Dictionary<string, PerkState> dictionary = ((stateService.Effects != null) ? stateService.Effects.perks : null); if (dictionary != null && dictionary.ContainsKey(effectName)) { return true; } GameHookedEffectsState hookedEffects = stateService.HookedEffects; if (hookedEffects != null) { if (ContainsHooked(hookedEffects.activeEffects, effectName)) { return true; } if (ContainsHooked(hookedEffects.toAdd, effectName)) { return true; } } } catch { } return false; } private static bool ContainsHooked(List<HookedEffectState> states, string effectName) { if (states == null) { return false; } for (int i = 0; i < states.Count; i++) { HookedEffectState val = states[i]; if (val != null && val.model == effectName) { return true; } } return false; } [HarmonyPatch(typeof(Villager), "Die", new Type[] { typeof(VillagerLossType), typeof(string), typeof(bool), typeof(float), typeof(SoundModel) })] [HarmonyPrefix] private static bool FC_BlockVillagerLoss(VillagerLossType __0) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FC_ShouldAllowLoss(__0); } [HarmonyPatch(typeof(Villager), "DieAsync", new Type[] { typeof(VillagerLossType), typeof(string), typeof(bool), typeof(float), typeof(SoundModel) })] [HarmonyPrefix] private static bool FC_BlockVillagerLossAsync(VillagerLossType __0) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FC_ShouldAllowLoss(__0); } private static bool FC_ShouldAllowLoss(VillagerLossType lossType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Invalid comparison between Unknown and I4 try { if ((int)lossType == 1 && _fcProtectionActive) { return false; } if ((int)lossType == 2 && _fcWorshipActive) { return false; } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR FC_ShouldAllowLoss: " + ex.Message)); } return true; } [HarmonyPatch(typeof(MainController), "OnServicesReady")] [HarmonyPostfix] private static void SetStartingPreparationPoints() { try { Settings settings = MainController.Instance.Settings; if ((Object)(object)settings != (Object)null && (Object)(object)settings.embarkConfig != (Object)null) { _ = settings.embarkConfig.preparationPoints; int value = FCConfig.EmbarkPreparationPoints.Value; settings.embarkConfig.preparationPoints = value; } else { ((BaseUnityPlugin)Instance).Logger.LogError((object)"Could not find embarkConfig to change starting preparation points!"); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("Failed to change starting preparation points: " + ex.Message)); } } [HarmonyPatch(typeof(BuildingsPickScreen), "Show")] [HarmonyPrefix] private static void ExpandStartingPicks(BuildingsPickScreen __instance) { __instance.maxInOffer = FCConfig.EmbarkMaxPicks.Value; } [HarmonyPatch(typeof(BuildingsPickScreen), "Show")] [HarmonyPostfix] private static void AddExtraEmbarkOffers(BuildingsPickScreen __instance) { //IL_059a: Unknown result type (might be due to invalid IL or missing references) //IL_059f: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Unknown result type (might be due to invalid IL or missing references) //IL_05b8: Expected O, but got Unknown //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04c6: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Expected O, but got Unknown try { EmbarkBonusesState val = null; PropertyInfo property = typeof(BuildingsPickScreen).GetProperty("State", BindingFlags.Instance | BindingFlags.NonPublic); if (property != null) { object? value = property.GetValue(__instance); val = (EmbarkBonusesState)((value is EmbarkBonusesState) ? value : null); } if (val == null) { return; } try { Settings ss = MainController.Instance.Settings; List<string> list = new List<string>(); foreach (ConditionPickState buildingsOption in val.buildingsOptions) { if (buildingsOption == null) { list.Add("(null)"); continue; } string text = KindOf(buildingsOption.name); list.Add(buildingsOption.name + ((text != "") ? ("[" + text + "]") : "")); } List<string> list2 = new List<string>(); foreach (ConditionPickState effectsOption in val.effectsOptions) { if (effectsOption == null) { list2.Add("(null)"); continue; } string text2 = KindOf(effectsOption.name); list2.Add(effectsOption.name + ((text2 != "") ? ("[" + text2 + "]") : "") + "<" + EffTypeOf(effectsOption.name) + ">"); } List<string> list3 = new List<string>(); foreach (GoodPickState goodsOption in val.goodsOptions) { if (goodsOption == null) { list3.Add("(null)"); continue; } string text3 = KindOf(goodsOption.name); list3.Add(goodsOption.name + ((text3 != "") ? ("[" + text3 + "]") : "")); } string EffTypeOf(string n) { if ((Object)(object)ss == (Object)null) { return ""; } try { return ((object)ss.GetEffect(n))?.GetType().Name ?? "(no-effect)"; } catch { return "(eff-key?)"; } } string KindOf(string n) { if ((Object)(object)ss == (Object)null) { return ""; } try { BuildingModel building = ss.GetBuilding(n); if (building is CampModel) { return "Camp"; } if (building is GathererHutModel) { return "GathererHut"; } if (building is FishingHutModel) { return "FishingHut"; } if (building is FarmModel) { return "Farm"; } } catch { return "(bld-key?)"; } return ""; } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR EMBARK-STATE dump: " + ex.Message)); } Settings settings = MainController.Instance.Settings; if ((Object)(object)settings == (Object)null) { return; } if (true) { try { val.effectsOptions.RemoveAll((ConditionPickState o) => o != null && IsGatherOrFarmEffect(o.name)); _ = 0; } catch (Exception ex2) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("removing gather/farm effects: " + ex2.Message)); } } GoodModel[] goods = settings.Goods; foreach (GoodModel val2 in goods) { if (!((Object)(object)val2 == (Object)null)) { string text4 = null; try { text4 = ((val2.displayName != null) ? val2.displayName.Text : null); } catch { } string text5 = (text4 ?? "").ToLowerInvariant(); bool num2 = text5.Contains("晶露") || text5.Contains("露水") || text5.Contains("dew"); bool flag = text5.Contains("铜矿") || text5.Contains("copper ore") || text5.Contains("copper"); bool flag2 = text5.Contains("铜条") || text5.Contains("copper bar"); bool flag3 = text5.Contains("植物纤维") || text5.Contains("纤维") || text5.Contains("fiber") || text5.Contains("fibre"); bool flag4 = text5.Contains("香草") || text5.Contains("herb") || text5.Contains("vanilla"); bool flag5 = text5.Contains("海洋精华") || text5.Contains("ocean essence"); bool flag6 = text5.Contains("染料") || text5.Contains("dye"); bool flag7 = text5.Contains("管道") || text5.Contains("pipe"); bool flag8 = text5.Contains("肥料") || text5.Contains("fertilizer"); if ((num2 || flag || flag2 || flag3 || flag4 || flag5 || flag6 || flag7 || flag8) && !HasGoodOption(val, ((SO)val2).Name)) { val.goodsOptions.Add(new GoodPickState { name = ((SO)val2).Name, amount = 10, cost = 1 }); _ = flag7 || flag8; } } } EffectModel[] effects = settings.effects; foreach (EffectModel val3 in effects) { if (!((Object)(object)val3 == (Object)null)) { string text6 = null; try { text6 = ((val3.displayName != null) ? val3.displayName.Text : null); } catch { } string text7 = (text6 ?? "").ToLowerInvariant(); if ((text7.Contains("昆虫输送线") || text7.Contains("昆虫输送") || text7.Contains("insect supply") || text7.Contains("insect line")) && val3 is CompositeEffectModel && !HasEffectOption(val, ((SO)val3).Name)) { val.effectsOptions.Add(new ConditionPickState { name = ((SO)val3).Name, cost = 1 }); } if (!text7.Contains("染料")) { text7.Contains("dye"); } if (!text7.Contains("昆虫")) { text7.Contains("insect"); } } } Type type = ((object)__instance).GetType(); MethodInfo method = type.GetMethod("UpdateGoodsOfferSlots", BindingFlags.Instance | BindingFlags.NonPublic); MethodInfo method2 = type.GetMethod("UpdateRewardsOfferSlots", BindingFlags.Instance | BindingFlags.NonPublic); if (method != null) { method.Invoke(__instance, null); } if (method2 != null) { method2.Invoke(__instance, null); } } catch (Exception ex3) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("AddExtraEmbarkOffers failed: " + ex3.Message)); } } private static bool HasGoodOption(EmbarkBonusesState state, string name) { foreach (GoodPickState goodsOption in state.goodsOptions) { if (goodsOption != null && goodsOption.name == name) { return true; } } return false; } private static bool HasEffectOption(EmbarkBonusesState state, string name) { foreach (ConditionPickState effectsOption in state.effectsOptions) { if (effectsOption != null && effectsOption.name == name) { return true; } } return false; } private static bool HasRewardPicked(EmbarkBonusesState state, string name) { foreach (ConditionPickState item in state.rewardsPicked) { if (item != null && item.name == name) { return true; } } return false; } private static bool IsGatherOrFarmEffect(string effectName) { if (string.IsNullOrEmpty(effectName)) { return false; } Settings settings = MainController.Instance.Settings; if ((Object)(object)settings == (Object)null) { return false; } try { EffectModel effect = settings.GetEffect(effectName); BaseBuildingEffectModel val = (BaseBuildingEffectModel)(object)((effect is BaseBuildingEffectModel) ? effect : null); if (val != null && (Object)(object)val.building != (Object)null) { return IsGatherOrFarm(val.building); } } catch { } string[] array = new string[4] { " Blueprint", "Blueprint", " blueprint", " blueprint " }; foreach (string text in array) { if (!effectName.EndsWith(text, StringComparison.OrdinalIgnoreCase)) { continue; } string text2 = effectName.Substring(0, effectName.Length - text.Length).Trim(); if (text2.Length == 0) { continue; } try { BuildingModel building = settings.GetBuilding(text2); if ((Object)(object)building != (Object)null && IsGatherOrFarm(building)) { return true; } } catch { } } return false; } [HarmonyPatch(typeof(MetaStateService), "CreateEmbarkBonuses")] [HarmonyPostfix] private static void FilterEmbarkBuildingOptions(ref EmbarkBonusesState __result) { try { if (__result == null || __result.buildingsOptions == null) { return; } Settings settings = MainController.Instance.Settings; if ((Object)(object)settings == (Object)null) { return; } _ = __result.buildingsOptions.Count; List<string> removed = new List<string>(); __result.buildingsOptions.RemoveAll(delegate(ConditionPickState opt) { if (opt == null || string.IsNullOrEmpty(opt.name)) { return false; } BuildingModel building = settings.GetBuilding(opt.name); if ((Object)(object)building != (Object)null && IsAutoUnlockCandidate(building)) { removed.Add(opt.name); return true; } return false; }); } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR FilterEmbarkBuildingOptions: " + ex.Message)); } } private static bool IsGatherOrFarm(BuildingModel b) { if (!(b is CampModel) && !(b is GathererHutModel) && !(b is FishingHutModel)) { return b is FarmModel; } return true; } private static bool IsPlantingByDisplayName(BuildingModel b) { try { string text = ((b.displayName != null) ? b.displayName.Text : null); if (string.IsNullOrEmpty(text)) { return false; } string text2 = text.ToLowerInvariant(); string[] plantingDisplayKeywords = PlantingDisplayKeywords; foreach (string value in plantingDisplayKeywords) { if (text2.Contains(value)) { return true; } } } catch { } return false; } private static bool IsQueryOnlyUnlock(BuildingModel b) { if ((Object)(object)b == (Object)null) { return false; } string a = ((SO)b).Name ?? ""; string[] queryOnlyUnlockNames = QueryOnlyUnlockNames; foreach (string b2 in queryOnlyUnlockNames) { if (string.Equals(a, b2, StringComparison.Ordinal)) { return true; } } return false; } private static bool IsDeniedBuilding(BuildingModel b) { if ((Object)(object)b == (Object)null) { return true; } string text = ((SO)b).Name ?? ""; string[] nonShopBuildingNames = NonShopBuildingNames; foreach (string b2 in nonShopBuildingNames) { if (string.Equals(text, b2, StringComparison.Ordinal)) { return true; } } if (text.StartsWith("Ruined", StringComparison.Ordinal)) { return true; } if (text.EndsWith("(no reward)", StringComparison.Ordinal)) { return true; } return false; } private static bool IsAutoUnlockCandidate(BuildingModel b) { if ((Object)(object)b == (Object)null) { return false; } if (IsDeniedBuilding(b)) { return false; } if (((SO)b).Name == "Biome Grass Spawner") { return true; } if (!IsGatherOrFarm(b)) { return IsPlantingByDisplayName(b); } return true; } [HarmonyPatch(typeof(ConstructionService), "ShouldShowInShop")] [HarmonyPrefix] private static bool HideNonShopBuildings(BuildingModel __0, ref bool __result) { try { if ((Object)(object)__0 == (Object)null) { return true; } if (IsQueryOnlyUnlock(__0)) { return true; } if (IsDeniedBuilding(__0)) { __result = false; return false; } } catch { } return true; } [HarmonyPatch(typeof(GameContentService), "OnLoading")] [HarmonyPostfix] private static void InjectQueryOnlyBuildings(GameContentService __instance) { try { _fcContentSvc = __instance; if (!_fcTownHallRegistered && !_fcTownHallFailed) { CreateTownHall(); } Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null); ContentState val2 = ((__instance != null) ? __instance.State : null); if ((Object)(object)val == (Object)null || val2 == null || val2.buildings == null) { return; } bool flag = false; List<string> list = new List<string>(); string[] queryOnlyUnlockNames = QueryOnlyUnlockNames; foreach (string text in queryOnlyUnlockNames) { if (!((Object)(object)val.GetBuilding(text) == (Object)null) && !val2.buildings.Contains(text)) { val2.buildings.Add(text); list.Add(text); flag = true; } } if (flag) { __instance.CacheProperties(); } InjectTownHallIntoPool(__instance); } catch (Exception) { } } private static void DedupeNames(List<string> list) { if (list == null) { return; } HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal); int num = 0; for (int i = 0; i < list.Count; i++) { string text = list[i]; if (text != null && hashSet.Add(text)) { list[num++] = text; } } if (num < list.Count) { list.RemoveRange(num, list.Count - num); } } [HarmonyPatch(typeof(MetaPerksService), "GetBasePreparationPoints")] [HarmonyPrefix] private static void AddAutoUnlockedBuildings() { try { ContentState content = MB.MetaStateService.Content; if (content == null) { ((BaseUnityPlugin)Instance).Logger.LogError((object)"FC AUTOUNLOCK: Content is null, skip."); return; } Settings settings = MainController.Instance.Settings; List<string> list = new List<string>(); int num = 0; if (content.buildings != null) { int count = content.buildings.Count; DedupeNames(content.buildings); num += count - content.buildings.Count; } if (content.essentialBuildings != null) { int count2 = content.essentialBuildings.Count; DedupeNames(content.essentialBuildings); num += count2 - content.essentialBuildings.Count; } List<string> list2 = new List<string>(); if ((Object)(object)settings != (Object)null && settings.Buildings != null) { BuildingModel[] buildings = settings.Buildings; foreach (BuildingModel val in buildings) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((SO)val).Name) && IsAutoUnlockCandidate(val)) { list2.Add(((SO)val).Name); } } } foreach (string item in list2) { if (!content.buildings.Contains(item)) { content.buildings.Add(item); } if (!content.essentialBuildings.Contains(item)) { content.essentialBuildings.Add(item); list.Add(item); } } _ = list.Count; _ = 0; _ = 0; } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR AddAutoUnlockedBuildings: " + ex.Message)); } } [HarmonyPatch(typeof(GameContentService), "IsUnlocked")] [HarmonyPostfix] private static void AutoUnlockBuildings(GameContentService __instance, BuildingModel building, ref bool __result) { try { if (!__result && !((Object)(object)building == (Object)null) && IsAutoUnlocked(building)) { __result = true; } } catch (Exception) { } } private static bool IsAutoUnlocked(BuildingModel b) { if ((Object)(object)b == (Object)null) { return false; } if (FC_IsTownHall(b)) { return true; } if (IsQueryOnlyUnlock(b)) { return true; } if (IsDeniedBuilding(b)) { return false; } if (((SO)b).Name == "Biome Grass Spawner") { return true; } if (IsGatherOrFarm(b) || IsPlantingByDisplayName(b)) { return true; } string text = null; try { text = ((b.displayName != null) ? b.displayName.Text : null); } catch { } string text2 = (text ?? "").ToLowerInvariant(); if (text2.Contains("高级") || text2.Contains("advanced")) { return true; } return false; } [HarmonyPatch(typeof(UpgradableBuilding), "AllGoodsAvailableFor")] [HarmonyPrefix] private static bool FreeUpgrade_AllGoodsAvailableFor(UpgradableBuilding __instance, ref bool __result) { if (IsFreeUpgradeBuilding(__instance)) { __result = true; return false; } return true; } [HarmonyPatch(typeof(UpgradableBuilding), "RemoveGoods")] [HarmonyPrefix] private static bool FreeUpgrade_RemoveGoods(UpgradableBuilding __instance, int __0, Func<int, bool> __1) { if (IsFreeUpgradeBuilding(__instance)) { return false; } return true; } [HarmonyPatch(typeof(BuildingUpgradesPanel), "SetUpGoods")] [HarmonyPostfix] private static void FreeUpgrade_SetUpGoods(BuildingUpgradesPanel __instance) { try { object? obj = AccessTools.Field(typeof(BuildingUpgradesPanel), "building")?.GetValue(__instance); UpgradableBuilding val = (UpgradableBuilding)((obj is UpgradableBuilding) ? obj : null); if (!((Object)(object)val == (Object)null) && IsFreeUpgradeBuilding(val)) { HideGoodsArea(__instance); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC UPGRADE-PANEL: " + ex.Message)); } } [HarmonyPatch(typeof(UpgradableBuilding), "CanUpgrade")] [HarmonyPrefix] private static bool FreeUpgrade_CanUpgrade(UpgradableBuilding __instance, ref bool __result) { if (IsFreeUpgradeBuilding(__instance)) { __result = true; return false; } return true; } [HarmonyPatch(typeof(BuildingUpgradesPanel), "UpdateContent")] [HarmonyPostfix] private static void FreeUpgrade_UpdateContent(BuildingUpgradesPanel __instance) { try { object? obj = AccessTools.Field(typeof(BuildingUpgradesPanel), "building")?.GetValue(__instance); if (IsFreeUpgradeBuilding((UpgradableBuilding)((obj is UpgradableBuilding) ? obj : null))) { HideGoodsArea(__instance); } } catch { } } [HarmonyPatch(typeof(BuildingRainpunkPanel), "SetUpUnlockPrice")] [HarmonyPostfix] private static void StripRainpunkUnlockPrice(BuildingRainpunkPanel __instance) { try { TMP_Text unlockCounter = __instance.unlockCounter; if (!((Object)(object)unlockCounter == (Object)null)) { string text = unlockCounter.text ?? ""; int num = text.IndexOf('('); if (num < 0) { num = text.IndexOf('('); } if (num >= 0) { unlockCounter.text = text.Substring(0, num).TrimEnd(Array.Empty<char>()); } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC STRIP-RAINPUNK-PRICE: " + ex.Message)); } } private static void HideGoodsArea(BuildingUpgradesPanel panel) { object? obj = AccessTools.Field(typeof(BuildingUpgradesPanel), "goodsLayout")?.GetValue(panel); Component val = (Component)((obj is Component) ? obj : null); object? obj2 = AccessTools.Field(typeof(BuildingUpgradesPanel), "noGoodsText")?.GetValue(panel); GameObject val2 = (GameObject)((obj2 is GameObject) ? obj2 : null); if ((Object)(object)val != (Object)null && val.gameObject.activeSelf) { val.gameObject.SetActive(false); } if ((Object)(object)val2 != (Object)null && val2.activeSelf) { val2.SetActive(false); } } [HarmonyPatch(typeof(Workshop), "UnlockRainpunk")] [HarmonyPrefix] private static bool FreeRainpunkUnlock(Workshop __instance) { try { __instance.state.rainpunkUnlocked = true; IGameBlackboardService gameBlackboardService = GameMB.GameBlackboardService; if (gameBlackboardService != null) { object obj = AccessTools.Property(((object)gameBlackboardService).GetType(), "OnRainpunkUnlocked")?.GetValue(gameBlackboardService); if (obj != null) { AccessTools.Method(obj.GetType(), "OnNext", new Type[1] { typeof(Workshop) }, (Type[])null)?.Invoke(obj, new object[1] { __instance }); } } return false; } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC FREE-RAINPUNK: " + ex.Message)); return true; } } [HarmonyPatch(typeof(BuildingUpgradesPanel), "UpgradeClicked")] [HarmonyPrefix] private static void Diag_PipesBeforeUpgrade() { try { } catch { } } [HarmonyPatch(typeof(BuildingUpgradesPanel), "UpgradeClicked")] [HarmonyPostfix] private static void Diag_PipesAfterUpgrade() { try { } catch { } } private static string PipeAmount() { try { IStorageService storageService = GameMB.StorageService; if (storageService == null) { return "?"; } return storageService.GetAmount("Pipes").ToString(); } catch { return "?"; } } private static bool IsFreeUpgradeBuilding(UpgradableBuilding b) { return (Object)(object)b != (Object)null; } [HarmonyPatch(typeof(UpgradableBuilding), "Upgrade")] [HarmonyPostfix] private static void FreeUpgrade_SyncUpgrade(UpgradableBuilding __instance, int __0, int __1) { try { House val = (House)(object)((__instance is House) ? __instance : null); if (val == null) { return; } BuildingModel buildingModel = ((Building)val).BuildingModel; if ((Object)(object)buildingModel == (Object)null) { return; } Dictionary<int, House> houses = GameMB.BuildingsService.Houses; if (houses == null) { return; } MethodInfo methodInfo = AccessTools.Method(typeof(UpgradableBuilding), "GrantUpgrade", (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(UpgradableBuilding), "RiseLevel", (Type[])null, (Type[])null); int num = 0; foreach (KeyValuePair<int, House> item in houses) { House value = item.Value; if (!((Object)(object)value == (Object)null) && !((Object)(object)value == (Object)(object)val) && !((Object)(object)((Building)value).BuildingModel != (Object)(object)buildingModel) && !((UpgradableBuilding)value).IsMaxLevelReached()) { methodInfo?.Invoke(value, new object[2] { __0, __1 }); methodInfo2?.Invoke(value, null); num++; } } _ = 0; } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC SYNC-UPGRADE: " + ex.Message)); } } [HarmonyPatch(typeof(EffectsService), "GetHearthMaxHP")] [HarmonyPostfix] private static void ForestCreator_HearthMaxHP_X10(EffectsService __instance, ref int __result) { try { Settings settings = MainController.Instance.Settings; if ((Object)(object)settings == (Object)null) { return; } int hearthBaseHP = settings.blightConfig.hearthBaseHP; EffectsState effects = __instance.Effects; if (effects == null) { return; } int hearthBonusHP = effects.hearthBonusHP; int num = 0; if (FCConfig.EnableDecorationResistance.Value) { try { IBuildingsService buildingsService = GameMB.BuildingsService; if (buildingsService != null && buildingsService.Decorations != null) { foreach (KeyValuePair<int, Decoration> decoration in buildingsService.Decorations) { Decoration value = decoration.Value; if ((Object)(object)value == (Object)null) { continue; } BuildingModel buildingModel = ((Building)value).BuildingModel; DecorationModel val = (DecorationModel)(object)((buildingModel is DecorationModel) ? buildingModel : null); if (!((Object)(object)val == (Object)null)) { int num2 = Mathf.Max(1, ((Vector2Int)(ref ((BuildingModel)val).size)).x * ((Vector2Int)(ref ((BuildingModel)val).size)).y); int num3 = FCConfig.DecorationGreenPerTile.Value; if ((Object)(object)val.tier != (Object)null) { num3 = val.tier.order switch { 0 => FCConfig.DecorationGreenPerTile.Value, 1 => FCConfig.DecorationBluePerTile.Value, 2 => FCConfig.DecorationGoldPerTile.Value, _ => FCConfig.DecorationGreenPerTile.Value, }; } num += num2 * num3; } } } } catch (Exception) { } } __result = Mathf.Max(1, hearthBaseHP + hearthBonusHP * FCConfig.HearthUpgradeBonusMultiplier.Value + num); } catch (Exception) { } } [HarmonyPatch(typeof(ProductionCalculator), "GetProductionFactor")] [HarmonyPostfix] private static void HearthBoostPrimaryProduction(Building __0, ref float __result) { try { if (!(__result <= 0f) && IsPrimaryGoodProducer(__0)) { int hearthProductionMultiplier = GetHearthProductionMultiplier(); if (hearthProductionMultiplier > 1) { __result *= hearthProductionMultiplier; } } } catch (Exception) { } } [Conditional("DEBUG")] private static void DebugLogProduction(Building building, int multiplier) { if (_hearthProductionLogBudget > 0) { _hearthProductionLogBudget--; } } private static bool IsPrimaryGoodProducer(Building building) { if ((Object)(object)building == (Object)null) { return false; } if (!(building is Camp) && !(building is GathererHut) && !(building is FishingHut) && !(building is Farm)) { return building is RainCatcher; } return true; } private static int GetHearthProductionMultiplier() { int ancientHearthLevel = GetAncientHearthLevel(); if (ancientHearthLevel >= 3) { return FCConfig.HearthLevel3ProductionMultiplier.Value; } if (ancientHearthLevel == 2) { return FCConfig.HearthLevel2ProductionMultiplier.Value; } return FCConfig.HearthLevel1ProductionMultiplier.Value; } private static int GetAncientHearthLevel() { try { IBuildingsService buildingsService = GameMB.BuildingsService; if (buildingsService == null) { return 1; } Hearth mainHearth = buildingsService.GetMainHearth(); if ((Object)(object)mainHearth != (Object)null) { return Mathf.Max(1, ((UpgradableBuilding)mainHearth).GetCurrentLevel()); } int num = 0; if (buildingsService.Hearths != null) { foreach (KeyValuePair<int, Hearth> hearth in buildingsService.Hearths) { Hearth value = hearth.Value; if (!((Object)(object)value == (Object)null)) { num = Mathf.Max(num, ((UpgradableBuilding)value).GetCurrentLevel()); } } } return Mathf.Max(1, num); } catch { return 1; } } [HarmonyPatch(typeof(ResolveService), "GetResolveFor")] [HarmonyPostfix] private static void DecorationResolveBonus(ref float __result) { try { int decorationResolveBonus = GetDecorationResolveBonus(); if (decorationResolveBonus > 0) { __result += decorationResolveBonus; } } catch (Exception) { } } private static int GetDecorationResolveBonus() { try { IBuildingsService buildingsService = GameMB.BuildingsService; if (buildingsService == null || buildingsService.Decorations == null) { return 0; } int num = 0; foreach (KeyValuePair<int, Decoration> decoration in buildingsService.Decorations) { Decoration value = decoration.Value; if ((Object)(object)value == (Object)null) { continue; } BuildingModel buildingModel = ((Building)value).BuildingModel; DecorationModel val = (DecorationModel)(object)((buildingModel is DecorationModel) ? buildingModel : null); if (!((Object)(object)val == (Object)null)) { int num2 = Mathf.Max(1, ((Vector2Int)(ref ((BuildingModel)val).size)).x * ((Vector2Int)(ref ((BuildingModel)val).size)).y); int num3 = FCConfig.DecorationGreenResolvePerTile.Value; if ((Object)(object)val.tier != (Object)null) { num3 = val.tier.order switch { 1 => FCConfig.DecorationBlueResolvePerTile.Value, 2 => FCConfig.DecorationGoldResolvePerTile.Value, _ => FCConfig.DecorationGreenResolvePerTile.Value, }; } num += num2 * num3; } } return num; } catch { return 0; } } [HarmonyPatch(typeof(EffectsService), "GetHouseCapacity", new Type[] { typeof(House) })] [HarmonyPostfix] private static void GetHouseCapacity_House_Postfix(ref int __result) { __result *= FCConfig.HouseCapacityMultiplier.Value; } [HarmonyPatch(typeof(EffectsService), "GetHouseCapacity", new Type[] { typeof(HouseModel) })] [HarmonyPostfix] private static void GetHouseCapacity_HouseModel_Postfix(ref int __result) { __result *= FCConfig.HouseCapacityMultiplier.Value; } [HarmonyPatch(typeof(MetaPerksService), "GetBasePreparationPoints")] [HarmonyPrefix] private static void RemoveLowTierCampsFromMetaContent() { try { ContentState content = MB.MetaStateService.Content; if (content == null || content.buildings == null) { return; } int num = 0; string[] lowTierCampNames = LowTierCampNames; foreach (string item in lowTierCampNames) { if (content.essentialBuildings != null) { while (content.essentialBuildings.Contains(item)) { content.essentialBuildings.Remove(item); num++; } } } if (num > 0 || !_metaCampsCleaned) { _metaCampsCleaned = true; } } catch (Exception) { } } [HarmonyPatch(typeof(ConstructionService), "ShouldShowInShop")] [HarmonyPrefix] private static bool HideLowTierCampsFromShop(BuildingModel __0, ref bool __result) { try { if ((Object)(object)__0 != (Object)null && IsLowTierCamp(((SO)__0).Name)) { __result = false; return false; } } catch { } return true; } private static bool IsLowTierCamp(string name) { if (string.IsNullOrEmpty(name)) { return false; } string[] lowTierCampNames = LowTierCampNames; foreach (string text in lowTierCampNames) { if (name == text) { return true; } } return false; } [HarmonyPatch(typeof(BuildingsPickScreen), "Show")] [HarmonyPostfix] private static void ReservePickedRows(BuildingsPickScreen __instance) { try { if (!((Object)(object)__instance == (Object)null)) { ((MonoBehaviour)Instance).StartCoroutine(ReservePickedRowsDeferred(__instance)); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("ReservePickedRows failed: " + ex.Message)); } } private static IEnumerator ReservePickedRowsDeferred(BuildingsPickScreen __instance) { while ((Object)(object)__instance == (Object)null || !((Component)__instance).gameObject.activeInHierarchy) { yield return null; } yield return null; yield return null; try { Transform transform = ((Component)__instance).transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); Transform val2 = (((Object)(object)val != (Object)null) ? ((Transform)val).Find("Content") : null); Transform val3 = (((Object)(object)val2 != (Object)null) ? val2.Find("Picked") : null); RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null); if ((Object)(object)val4 == (Object)null) { DumpTree(__instance, "NOPICKED"); yield break; } Transform obj = ((Transform)val4).Find("Content"); RectTransform val5 = (RectTransform)(object)((obj is RectTransform) ? obj : null); GridLayoutGroup val6 = (((Object)(object)val5 != (Object)null) ? ((Component)val5).GetComponent<GridLayoutGroup>() : null); int num = 9; float num2 = 0f; if ((Object)(object)val6 != (Object)null) { if ((int)val6.constraint == 1) { num = val6.constraintCount; } num2 = val6.cellSize.y + val6.spacing.y; } if (num2 <= 0f) { val6 = ((Component)val3).GetComponent<GridLayoutGroup>(); if ((Object)(object)val6 != (Object)null) { if ((int)val6.constraint == 1) { num = val6.constraintCount; } num2 = val6.cellSize.y + val6.spacing.y; } } Rect rect; if (num2 <= 0f) { foreach (Transform item in (Transform)val4) { Transform val7 = item; if (((Component)val7).gameObject.activeSelf) { rect = ((RectTransform)val7).rect; num2 = ((Rect)(ref rect)).height; break; } } } Transform val8 = ((Transform)val4).Find("ConfirmButton"); if (num2 > 0f && (Object)(object)val8 != (Object)null) { RectTransform val9 = (RectTransform)(object)((val8 is RectTransform) ? val8 : null); int num3 = Mathf.Max(1, (FCConfig.EmbarkMaxPicks.Value + num - 1) / num); float num4 = (((Object)(object)val5 != (Object)null) ? (0f - ((Transform)val5).localPosition.y) : 0f) + (float)num3 * num2; float y = val9.anchoredPosition.y; rect = val9.rect; float height = ((Rect)(ref rect)).height; float num5 = 70f; rect = val4.rect; float num6 = ((Rect)(ref rect)).height - y - height / 2f; float num7 = num4 + num5 - num6; if (num7 > 0f) { float y2 = val4.pivot.y; float x = val4.sizeDelta.x; rect = val4.rect; val4.sizeDelta = new Vector2(x, ((Rect)(ref rect)).height + num7); val4.anchoredPosition = new Vector2(val4.anchoredPosition.x, val4.anchoredPosition.y - num7 * (1f - y2)); } } DumpTree(__instance, "LAYOUT"); DumpSlots(__instance, val4, val5); } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("ReservePickedRowsDeferred failed: " + ex.Message)); } } private static void DumpSlots(BuildingsPickScreen __instance, RectTransform picked, RectTransform gridContent) { //IL_0015: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02c3: Unknown result type (might be due to invalid IL or missing references) //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown //IL_014c: 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_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0199: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01d0: Unknown result type (might be due to invalid IL or missing references) try { StringBuilder stringBuilder = new StringBuilder(); object[] array = new object[4]; Rect rect = picked.rect; array[0] = ((Rect)(ref rect)).height; array[1] = picked.anchorMin; array[2] = picked.anchorMax; array[3] = picked.pivot; stringBuilder.Append(string.Format("SLOTS pickedH={0:F0} anchorMin={1} anchorMax={2} pivot={3}", array)); if ((Object)(object)gridContent != (Object)null) { object[] obj = new object[6] { ((Object)gridContent).name, null, null, null, null, null }; rect = gridContent.rect; obj[1] = ((Rect)(ref rect)).height; obj[2] = ((Transform)gridContent).localPosition.y; obj[3] = gridContent.anchorMin; obj[4] = gridContent.anchorMax; obj[5] = gridContent.pivot; stringBuilder.Append(string.Format(" | grid(name={0},h={1:F0},lp={2:F0},anchorMin={3},anchorMax={4},pivot={5})", obj)); int num = 0; foreach (Transform item in (Transform)gridContent) { Transform val = item; RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null); object[] obj2 = new object[8] { num++, ((Object)val).name, ((Component)val).gameObject.activeSelf, null, null, null, null, null }; float num2; if (!((Object)(object)val2 != (Object)null)) { num2 = 0f; } else { rect = val2.rect; num2 = ((Rect)(ref rect)).height; } obj2[3] = num2; obj2[4] = (((Object)(object)val2 != (Object)null) ? ((Transform)val2).localPosition.y : 0f); obj2[5] = (((Object)(object)val2 != (Object)null) ? val2.anchorMin : Vector2.zero); obj2[6] = (((Object)(object)val2 != (Object)null) ? val2.anchorMax : Vector2.zero); obj2[7] = (((Object)(object)val2 != (Object)null) ? val2.pivot : Vector2.zero); stringBuilder.Append(string.Format(" |slot{0}(name={1},active={2},h={3:F0},lp={4:F0},anchorMin={5},anchorMax={6},pivot={7})", obj2)); } } string[] array2 = new string[5] { "PointsLeft", "Plus", "BonusPointsLeft", "ConfirmButton", "EarlyEndMarker" }; foreach (string text in array2) { Transform val3 = ((Transform)picked).Find(text); if (!((Object)(object)val3 == (Object)null)) { RectTransform val4 = (RectTransform)(object)((val3 is RectTransform) ? val3 : null); object[] obj3 = new object[7] { text, val4.anchoredPosition.y, ((Transform)val4).localPosition.y, null, null, null, null }; rect = val4.rect; obj3[3] = ((Rect)(ref rect)).height; obj3[4] = val4.anchorMin; obj3[5] = val4.anchorMax; obj3[6] = val4.pivot; stringBuilder.Append(string.Format(" |{0}(apY={1:F0},lp={2:F0},h={3:F0},anchorMin={4},anchorMax={5},pivot={6})", obj3)); } } } catch (Exception) { } } [HarmonyPatch(typeof(ProductionCalculator), "GetProductionMultiplier")] [HarmonyPostfix] private static void RobotGetsEngineBonus(ProductionCalculator __instance, Building building, Actor actor, ref int __result) { try { if (!((Object)(object)actor == (Object)null) && !actor.CanCritProduction && __result == 1) { float num = 0f; UpgradableBuildingState val = (((Object)(object)building != (Object)null) ? building.UpgradableState : null); if (val != null) { num = val.chanceForExtraProductionBonus; } __result = 1 + (int)num; float num2 = num - (float)(int)num; if (num2 > 0f && Random.value < num2) { __result++; } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR RobotGetsEngineBonus: " + ex.Message)); } } private static Vector2 GetRadialPosition(int index, int maxSlots) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) float num = (float)index * MathF.PI * 2f / (float)maxSlots; return new Vector2(Mathf.Sin(num) * 125f, Mathf.Cos(num) * 125f); } private static bool BuildingSupportsRobot(RacesMenu menu) { //IL_0082: Unknown result type (might be due to invalid IL or missing references) try { FieldInfo field = typeof(RacesMenu).GetField("building", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); object obj = (object)((field != null) ? /*isinst with value type is only supported in some contexts*/: null); ProductionBuilding val = (ProductionBuilding)((obj is ProductionBuilding) ? obj : null); if (val == null) { return false; } if (val is ICollector) { return true; } if (val is IWorkshop || val is Institution) { BuildingModel buildingModel = ((Building)val).BuildingModel; ProfessionModel val2 = (((Object)(object)buildingModel != (Object)null) ? buildingModel.Profession : null); return (Object)(object)val2 != (Object)null && (int)val2.behaviour != 0; } return false; } catch { return false; } } [HarmonyPatch(typeof(RacesMenu), "SetUp")] [HarmonyPostfix] private static void AddRobotSlotToRacesMenu(RacesMenu __instance) { //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null) { return; } FieldInfo field = typeof(RacesMenu).GetField("slots", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || !(field.GetValue(__instance) is List<RacesMenuSlot> { Count: not 0 } list)) { return; } _ = (Building)(typeof(RacesMenu).GetField("building", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(__instance)); Transform[] componentsInChildren = ((Component)((Component)__instance).transform).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)val).name == "RobotSlot") { Object.DestroyImmediate((Object)(object)((Component)val).gameObject); } } try { FieldInfo field2 = typeof(RadialMenu).GetField("slotsRadius", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null) { field2.SetValue(__instance, 125f); } } catch (Exception) { } int count = list.Count; if (!BuildingSupportsRobot(__instance)) { int maxSlots = count; for (int j = 0; j < count; j++) { RectTransform component = ((Component)list[j]).GetComponent<RectTransform>(); if ((Object)(object)component != (Object)null) { component.anchoredPosition = GetRadialPosition(j, maxSlots); } } return; } int maxSlots2 = count + 1; for (int k = 0; k < count; k++) { RectTransform component2 = ((Component)list[k]).GetComponent<RectTransform>(); if ((Object)(object)component2 != (Object)null) { component2.anchoredPosition = GetRadialPosition(k, maxSlots2); } } RacesMenuSlot val2 = null; foreach (RacesMenuSlot item in list) { if (!((Object)(object)item == (Object)null)) { Transform val3 = ((Component)item).transform.Find("Content"); if ((Object)(object)val3 != (Object)null && ((Component)val3).gameObject.activeSelf) { val2 = item; break; } } } if ((Object)(object)val2 == (Object)null) { val2 = list[count - 1]; } GameObject val4 = Object.Instantiate<GameObject>(((Component)val2).gameObject, ((Component)val2).transform.parent); ((Object)val4).name = "RobotSlot"; Transform val5 = val4.transform.Find("Content"); if ((Object)(object)val5 != (Object)null) { ((Component)val5).gameObject.SetActive(true); } Transform val6 = val4.transform.Find("EmptyMarker"); if ((Object)(object)val6 != (Object)null) { ((Component)val6).gameObject.SetActive(false); } val4.SetActive(true); RacesMenuSlot component3 = val4.GetComponent<RacesMenuSlot>(); if ((Object)(object)component3 != (Object)null) { ((Behaviour)component3).enabled = false; Object.DestroyImmediate((Object)(object)component3); } Button componentInChildren = val4.GetComponentInChildren<Button>(); if ((Object)(object)componentInChildren != (Object)null) { ((UnityEventBase)componentInChildren.onClick).RemoveAllListeners(); } HideClonedTagIcon(val2, val4, "leftTagIcon"); HideClonedTagIcon(val2, val4, "rightTagIcon"); RectTransform component4 = val4.GetComponent<RectTransform>(); if ((Object)(object)component4 != (Object)null) { component4.anchoredPosition = GetRadialPosition(count, maxSlots2); } val4.AddComponent<RobotMenuSlot>().SetUp(__instance); DumpImages(val4, "after-robot-SetUp"); } catch (Exception ex2) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("AddRobotSlotToRacesMenu failed: " + ex2.Message)); } } private static void HideClonedTagIcon(RacesMenuSlot template, GameObject robotGo, string fieldName) { try { FieldInfo field = typeof(RacesMenuSlot).GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic); if (field == null) { return; } object? value = field.GetValue(template); Image val = (Image)((value is Image) ? value : null); if ((Object)(object)val == (Object)null) { return; } Transform transform = ((Component)val).transform; Transform transform2 = ((Component)template).transform; string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)transform2) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } Transform val2 = robotGo.transform.Find(text); if ((Object)(object)val2 != (Object)null) { ((Component)val2).gameObject.SetActive(false); Image component = ((Component)val2).GetComponent<Image>(); if ((Object)(object)component != (Object)null) { component.sprite = null; } } } catch (Exception) { } } [HarmonyPatch(typeof(GameHistoryCreator), "SaveHistory")] [HarmonyPrefix] private static bool SkipDefeatHistory(bool __0) { try { if (!__0) { return false; } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipDefeatHistory: " + ex.Message)); } return true; } [HarmonyPatch(typeof(StatsService), "GameFinished")] [HarmonyPrefix] private static bool SkipDefeatStats(bool __0) { try { if (!__0) { return false; } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipDefeatStats: " + ex.Message)); } return true; } [HarmonyPatch(typeof(CycleStateGameUpdater), "AddFailedCity")] [HarmonyPrefix] private static bool SkipFailedCity(bool __0) { try { if (!__0) { return false; } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipFailedCity: " + ex.Message)); } return true; } [HarmonyPatch(typeof(WorldStateService), "FixState")] [HarmonyPostfix] private static void ClearFailedCities(WorldState __result) { try { if (__result != null && __result.failedCities != null && __result.failedCities.Count > 0) { _ = __result.failedCities.Count; __result.failedCities.Clear(); } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR ClearFailedCities: " + ex.Message)); } } [HarmonyPatch(typeof(CycleStateGameUpdater), "GameFinished")] [HarmonyPrefix] private static bool SkipDefeatCycleProgress(bool __0) { try { if (!__0) { return false; } _suppressCycleYears = false; } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR SkipDefeatCycleProgress: " + ex.Message)); } return true; } [HarmonyPatch(typeof(CycleStateGameUpdater), "AddYears")] [HarmonyPrefix] private static bool GuardAddYears() { try { if (_suppressCycleYears) { return false; } return true; } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR GuardAddYears: " + ex.Message)); } return true; } private static void LogSpawnerCandidate(BuildingModel model) { if ((Object)(object)model == (Object)null) { return; } string text = ((SO)model).Name ?? string.Empty; _ = ((object)model).GetType().Name; if (!(model is SpawnerModel) && text.IndexOf("Spawner", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Biome", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Grass", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Soil", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Fertile", StringComparison.OrdinalIgnoreCase) < 0) { return; } _ = string.Empty; try { if (model.displayName == null) { _ = string.Empty; } else { _ = model.displayName.Text; } } catch { } } private static bool IsDragPlacingSpawner(BuildingModel model) { if ((Object)(object)model == (Object)null || !(model is SpawnerModel)) { return false; } string a = ((SO)model).Name ?? string.Empty; string[] dragPlacingSpawnerNames = DragPlacingSpawnerNames; foreach (string b in dragPlacingSpawnerNames) { if (string.Equals(a, b, StringComparison.OrdinalIgnoreCase)) { return true; } } try { string text = ((model.displayName != null) ? model.displayName.Text : null); if (!string.IsNullOrEmpty(text)) { dragPlacingSpawnerNames = DragPlacingSpawnerDisplayKeywords; foreach (string value in dragPlacingSpawnerNames) { if (text.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } } } catch { } return false; } [HarmonyPatch(typeof(BuildingsPanel), "CreateRequest")] [HarmonyPrefix] private static bool CreateRequest_DragPlacingSpawner(BuildingModel __0, BuildingsPanel __instance, ref IBuildingRequest __result) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown try { ActiveDragSpawner = null; LogSpawnerCandidate(__0); if (!IsDragPlacingSpawner(__0)) { return true; } IConstructionPlanner val = null; FieldInfo fieldInfo = AccessTools.Field(typeof(BuildingsPanel), "fieldsPlanner"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(__instance); val = (IConstructionPlanner)((value is IConstructionPlanner) ? value : null); } if (val == null) { return true; } MethodInfo methodInfo = AccessTools.Method(typeof(BuildingsPanel), "PlacingFinished", (Type[])null, (Type[])null); if (methodInfo == null) { return true; } Action onFinished = (Action)Delegate.CreateDelegate(typeof(Action), __instance, methodInfo); __result = (IBuildingRequest)(object)new SpawnerGroupRequest((SpawnerModel)__0, val, onFinished); ActiveDragSpawner = (SpawnerModel)__0; return false; } catch (Exception) { return true; } } [HarmonyPatch(typeof(GroupRequest), "Dispose")] [HarmonyPostfix] private static void Dispose_ClearDragSpawner(object __instance) { if (__instance is SpawnerGroupRequest) { ActiveDragSpawner = null; } } [HarmonyPatch(typeof(FieldsPlanner), "IsAvaiable")] [HarmonyPrefix] private static bool IsAvaiable_AllowAnyFreeTile(int __0, int __1, ref bool __result) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ActiveDragSpawner == (Object)null) { return true; } try { __result = GameMB.MapService.IsFieldEmpty(new Vector2Int(__0, __1)); } catch (Exception) { __result = false; } return false; } [HarmonyPatch(typeof(GameController), "StartGame")] [HarmonyPostfix] private static void InjectStartingCornerstones() { try { Settings settings = MainController.Instance.Settings; if ((Object)(object)settings == (Object)null) { return; } IStateService stateService = Serviceable.StateService; if (stateService == null) { return; } if (stateService.Effects != null) { _ = stateService.Effects.perks; } TopUpWarehouseTo200(); string[] fC_StartingCornerstoneNames = FC_StartingCornerstoneNames; foreach (string text in fC_StartingCornerstoneNames) { EffectModel val = null; try { val = settings.GetEffect(text); } catch { } if ((Object)(object)val == (Object)null) { continue; } try { if (val.displayName != null) { _ = val.displayName.Text; } } catch { } if (!FC_IsAlreadyApplied(((Object)val).name)) { try { val.Apply((EffectContextType)0, (string)null, 0); } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR apply cornerstone '" + ((Object)val).name + "': " + ex.Message)); } } } FC_InjectCustomCornerstones(); SyncCustomCornerstoneFlags(); } catch (Exception ex2) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR InjectStartingCornerstones: " + ex2.Message)); } } private static void TopUpWarehouseTo200() { try { if (!GameController.IsGameActive) { return; } IStorageService storageService = Serviceable.StorageService; if (storageService == null) { return; } Storage main = storageService.Main; if ((Object)(object)main == (Object)null) { return; } LockedGoodsCollection goods = main.Goods; if (goods == null) { return; } List<string> list = new List<string>(((GoodsCollection)goods).goods.Keys); int value = FCConfig.WarehouseTopUpTarget.Value; int num = 0; foreach (string item in list) { int amount = ((GoodsCollection)goods).GetAmount(item); if (amount < value) { ((GoodsCollection)goods).Add(item, value - amount); num++; } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR TopUpWarehouseTo200: " + ex.Message)); } } [HarmonyPatch(typeof(SteamService), "VerifyDLC")] [HarmonyFinalizer] private static Exception GuardVerifyDLC(Exception __exception, ref UniTask<bool> __result) { //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) if (__exception == null) { return null; } _steamDlcVerifyFailed = true; try { __result = UniTask.FromResult<bool>(true); } catch { } return null; } [HarmonyPatch(typeof(DLCsService), "IsDLCDowngrade")] [HarmonyPrefix] private static bool GuardIsDlcDowngrade(ref bool __result) { if (!_steamDlcVerifyFailed) { return true; } __result = false; return false; } [HarmonyPatch(typeof(DLCsService), "MarkSavesAsOld")] [HarmonyPrefix] private static bool GuardMarkSavesAsOld() { if (!_steamDlcVerifyFailed) { return true; } return false; } internal static void CreateTownHall() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if (_fcTownHallRegistered || _fcTownHallFailed) { return; } InstitutionBuildingBuilder val; try { val = new InstitutionBuildingBuilder("ForestCreator", "Forest Creator Town Hall", FC_IconPath("fc_town_hall.png")); } catch (Exception ex) { _fcTownHallFailed = true; ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(ctor): " + ex)); return; } try { InstitutionModel buildingModel = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel; if ((Object)(object)buildingModel != (Object)null) { if (buildingModel.recipes == null) { buildingModel.recipes = (InstitutionRecipeModel[])(object)new InstitutionRecipeModel[0]; } if (buildingModel.workplaces == null) { buildingModel.workplaces = (WorkplaceModel[])(object)new WorkplaceModel[0]; } if (buildingModel.activeEffects == null) { buildingModel.activeEffects = (InstitutionEffectModel[])(object)new InstitutionEffectModel[0]; } if (buildingModel.needsCache == null) { buildingModel.needsCache = new HashSet<NeedModel>(); } if (buildingModel.goodsCache == null) { buildingModel.goodsCache = new HashSet<GoodModel>(); } } } catch (Exception ex2) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(collections): " + ex2.Message)); } try { InstitutionModel val2 = FC_FindLookTemplate(); if ((Object)(object)val2 != (Object)null) { if ((Object)(object)val2.prefab != (Object)null && (Object)(object)((Component)val2.prefab).gameObject != (Object)null) { ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetCustomModel(((Component)val2.prefab).gameObject); } InstitutionModel buildingModel2 = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel; if ((Object)(object)buildingModel2 != (Object)null && (Object)(object)((BuildingModel)val2).icon != (Object)null) { ((BuildingModel)buildingModel2).icon = ((BuildingModel)val2).icon; } } else { FC_LogBuildingNames(); } } catch (Exception ex3) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(look): " + ex3)); } try { ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDisplayName("Town Hall", (SystemLanguage)10); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDisplayName("城镇大厅", (SystemLanguage)40); string text = "Pay 2 Amber to recruit one villager of any race."; string text2 = "花费 2 琥珀,招募一名任意种族的居民。"; ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDescription(text, (SystemLanguage)10); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetDescription(text2, (SystemLanguage)40); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetLabel("Town Hall", (SystemLanguage)10); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetLabel("城镇大厅", (SystemLanguage)40); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetCategory((BuildingCategoriesTypes)1); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetFootPrint(3, 3, (FieldType)40); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetOrder(0); ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).SetRequiredGoods((NameToAmount[])(object)new NameToAmount[1] { NameToAmount.op_Implicit((15, "[Mat Raw] Wood")) }); } catch (Exception ex4) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR CreateTownHall(texts): " + ex4.Message)); } _fcTownHallBuilder = val; _fcTownHallName = (((Object)(object)((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel != (Object)null) ? ((Object)((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel).name : null); _fcTownHallRegistered = true; ((BaseUnityPlugin)Instance).Logger.LogInfo((object)("FC TOWNHALL registered: " + _fcTownHallName)); try { InstitutionModel buildingModel3 = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel; GoodRef[] array = (GoodRef[])(((Object)(object)buildingModel3 != (Object)null && ((BuildingModel)buildingModel3).requiredGoods != null) ? ((Array)((BuildingModel)buildingModel3).requiredGoods) : ((Array)new GoodRef[0])); for (int i = 0; i < array.Length; i++) { _ = array[i]; } } catch (Exception) { } try { _ = ((BuildingBuilder<InstitutionModel, NewInstitutionBuildingData>)(object)val).BuildingModel; } catch (Exception) { } } private static InstitutionModel FC_FindLookTemplate() { try { Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null); if ((Object)(object)val == (Object)null || val.Buildings == null) { return null; } BuildingModel[] buildings = val.Buildings; foreach (BuildingModel obj in buildings) { InstitutionModel val2 = (InstitutionModel)(object)((obj is InstitutionModel) ? obj : null); if (!((Object)(object)val2 == (Object)null)) { string text = (((Object)val2).name ?? "").Replace(" ", "").ToLowerInvariant(); string text2 = ""; try { text2 = ((((BuildingModel)val2).displayName != null) ? ((BuildingModel)val2).displayName.Text : ""); } catch { } text2 = (text2 ?? "").ToLowerInvariant(); if (text.Contains("holytemple") || text.Contains("Holy Temple".Replace(" ", "").ToLowerInvariant()) || text2.Contains("holy temple") || text2.Contains("圣殿") || text2.Contains("神庙")) { return val2; } } } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR FC_FindLookTemplate: " + ex.Message)); } return null; } private static void FC_LogBuildingNames() { try { Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null); if ((Object)(object)val == (Object)null || val.Buildings == null) { return; } StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("FC BUILDINGS (institutions): "); BuildingModel[] buildings = val.Buildings; foreach (BuildingModel val2 in buildings) { if (val2 is InstitutionModel) { stringBuilder.Append('[').Append(((Object)val2).name).Append("] "); } } } catch { } } internal static void InjectTownHallIntoPool(GameContentService svc) { try { if (string.IsNullOrEmpty(_fcTownHallName) || svc == null) { return; } Settings val = ((MainController.Instance != null) ? MainController.Instance.Settings : null); if ((Object)(object)val == (Object)null || (Object)(object)val.GetBuilding(_fcTownHallName) == (Object)null) { return; } ContentState state = svc.State; if (state != null && state.buildings != null) { if (state.buildings.Contains(_fcTownHallName)) { _fcTownHallPoolDone = true; return; } state.buildings.Add(_fcTownHallName); svc.CacheProperties(); _fcTownHallPoolDone = true; } } catch (Exception ex) { ((BaseUnityPlugin)Instance).Logger.LogError((object)("FC ERR InjectTownHallIntoPool: " + ex.Message)); } } [HarmonyPatch(typeof(BuildingManager), "Tick")] [HarmonyPostfix] private static void AfterBuildingManagerTick() { ApplyTownHallLookOnce(); RetryTownHallPoolInjection(); } private static void ApplyTownHallLookOnce() { if (!_fcTownHallRegistered || _fcL