Decompiled source of ForwindzCustomCornerstones v1.2.2

ForwindzCustomPerksMod.dll

Decompiled 3 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using ATS_API.Biomes;
using ATS_API.Effects;
using ATS_API.Helpers;
using ATS_API.Localization;
using BepInEx;
using BepInEx.Logging;
using Cysharp.Threading.Tasks;
using Cysharp.Threading.Tasks.CompilerServices;
using Eremite;
using Eremite.Buildings;
using Eremite.Controller;
using Eremite.Controller.Effects;
using Eremite.Model;
using Eremite.Model.Effects;
using Eremite.Model.Effects.Hooked;
using Eremite.Model.Orders;
using Eremite.Model.State;
using Eremite.Model.Trade;
using Eremite.Model.ViewsConfigurations;
using Eremite.Services;
using Eremite.Services.Monitors;
using Eremite.Services.Orders;
using Eremite.Services.World;
using Eremite.WorldMap;
using Forwindz.Content;
using Forwindz.Framework.Effects;
using Forwindz.Framework.Hooks;
using Forwindz.Framework.Services;
using Forwindz.Framework.Utils;
using Forwindz.Framework.Utils.Extend;
using Forwindz.Scripts.Framework.Services;
using Forwindz.Scripts.Framework.Utils;
using ForwindzCustomPerks.Framework.Services;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Sirenix.Utilities;
using UniRx;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("ForwindzCustomPerksMod")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyDescription("My First Mod for Against The Storm - by Forwindz")]
[assembly: AssemblyFileVersion("1.2.2.0")]
[assembly: AssemblyInformationalVersion("1.2.2+ba5bc310e22427e3dd43a69993f0e34b14661a33")]
[assembly: AssemblyProduct("ForwindzCustomPerksMod")]
[assembly: AssemblyTitle("ForwindzCustomPerksMod")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.2.2.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 ForwindzCustomPerks
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "ForwindzCustomPerksMod";

		public const string PLUGIN_NAME = "ForwindzCustomPerksMod";

		public const string PLUGIN_VERSION = "1.2.2";
	}
}
namespace ForwindzCustomPerks.Framework.Services
{
	public class DynamicTraderExtraState
	{
		public float chanceToFreeEffect = 0f;
	}
	public class DynamicTraderInfoData
	{
		public List<string> forceTraderNameList = new List<string>();

		[JsonProperty]
		private Dictionary<string, DynamicTraderExtraState> traderGlobalStates = new Dictionary<string, DynamicTraderExtraState>();

		public Dictionary<string, float> effectsSellValue = new Dictionary<string, float>();

		public DynamicTraderExtraState GetTraderGlobalEffects(string traderName)
		{
			if (!traderGlobalStates.TryGetValue(traderName, out var value))
			{
				FLog.Info("[" + traderName + "] does not have extra states, create it", "GetTraderGlobalEffects", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 44);
				value = new DynamicTraderExtraState();
				traderGlobalStates[traderName] = value;
			}
			return value;
		}

		public bool GetEffectModifiedSellValue(string effectName, out float modifiedValue)
		{
			if (effectsSellValue.TryGetValue(effectName, out modifiedValue))
			{
				return true;
			}
			modifiedValue = 0f;
			return false;
		}
	}
	public class TradeDealInfo
	{
		public TraderVisitState visit;

		public TradingOffer villageOffer;

		public TradingOffer traderOffer;
	}
	public class DynamicTraderInfoService : GameService, IDynamicTraderInfoService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		internal DynamicTraderInfoData stateData = new DynamicTraderInfoData();

		private IDisposable traderArriveListener = null;

		public Subject<TradeDealInfo> onTradeCompleteSubject = new Subject<TradeDealInfo>();

		private MethodInfo methodUpdateNextVisit = null;

		public DynamicTraderInfoData DynamicTraderState => stateData;

		public IObservable<TradeDealInfo> OnTradeCompleteEvent => (IObservable<TradeDealInfo>)onTradeCompleteSubject;

		static DynamicTraderInfoService()
		{
			CustomServiceManager.RegGameService<DynamicTraderInfoService>();
			PatchesManager.RegPatch<DynamicTraderInfoService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[2]
			{
				(IService)Serviceable.TradeService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public void UpdateNextVisit()
		{
			if (methodUpdateNextVisit == null)
			{
				FLog.Error("Cannot invoke UpdateNextVisit()! The trader state cannot be update!", "UpdateNextVisit", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 105);
			}
			else
			{
				methodUpdateNextVisit.Invoke(Serviceable.TradeService, null);
			}
		}

		public override void OnDestroy()
		{
			traderArriveListener.Dispose();
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			methodUpdateNextVisit = AccessTools.Method(typeof(TradeService), "UpdateNextVisit", (Type[])null, (Type[])null);
			traderArriveListener = ObservableExtensions.Subscribe<TraderVisitState>(Serviceable.TradeService.OnTraderArrived, (Action<TraderVisitState>)OnTraderArrive);
			RestoreData();
			return UniTask.CompletedTask;
		}

		private void RestoreData()
		{
			FLog.Info("Restored DynamicTraderStateInfo > ", "RestoreData", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 128);
			FLog.Info($"Sell Perks Count: {stateData.effectsSellValue.Count} | Force List: {stateData.forceTraderNameList.Count}", "RestoreData", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 129);
		}

		private void OnTraderArrive(TraderVisitState visitState)
		{
			FLog.Info("Trader [" + visitState.trader + "] Arrived! Process its effect price!", "OnTraderArrive", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 134);
			ApplyEffectsToVisitState(visitState);
		}

		private void ApplyEffectsToVisitState(TraderVisitState newVisitState)
		{
			stateData.effectsSellValue.Clear();
			DynamicTraderExtraState traderGlobalEffects = stateData.GetTraderGlobalEffects(newVisitState.trader);
			if (!(traderGlobalEffects.chanceToFreeEffect > 0f))
			{
				return;
			}
			FLog.Info($"{newVisitState.trader} has {traderGlobalEffects.chanceToFreeEffect} free chance.", "ApplyEffectsToVisitState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 150);
			foreach (KeyValuePair<string, bool> effect in newVisitState.effects)
			{
				FLog.Info($"Check {effect}", "ApplyEffectsToVisitState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 153);
				string key = effect.Key;
				if (!effect.Value)
				{
					FLog.Info($"{traderGlobalEffects.chanceToFreeEffect} free chance for {effect}", "ApplyEffectsToVisitState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 158);
					if (StableRNG.StableRoll(traderGlobalEffects.chanceToFreeEffect))
					{
						stateData.effectsSellValue.Add(key, 0f);
						FLog.Info("Set " + key + " as free", "ApplyEffectsToVisitState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 162);
					}
				}
			}
		}

		public TraderModel GetForceTrader()
		{
			if (stateData.forceTraderNameList.Count == 0)
			{
				return null;
			}
			string text = stateData.forceTraderNameList.Where((string x) => !Serviceable.StateService.Trade.assaultedTraders.Contains(x)).FirstOrDefault();
			if (text == null || text.Length == 0)
			{
				return null;
			}
			return Serviceable.Settings.GetTrader(text);
		}

		public void AddForceTrader(string name)
		{
			FLog.Info("Add Force Trader: " + name, "AddForceTrader", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 200);
			RemoveAssaultTrader(name);
			stateData.forceTraderNameList.Add(name);
			ResetNextTrader();
		}

		public void RemoveForceTrader(string name)
		{
			if (!stateData.forceTraderNameList.Remove(name))
			{
				FLog.Warning("Cannot remove forced trader [" + name + "]. It not exists in forced list!", "RemoveForceTrader", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 214);
				return;
			}
			FLog.Info("Remove Force Trader: " + name, "RemoveForceTrader", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 218);
			ResetNextTrader();
		}

		public void RemoveAssaultTrader(string name)
		{
			FLog.Info("Remove Assaulted Trader Record: " + name, "RemoveAssaultTrader", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 225);
			Serviceable.StateService.Trade.assaultedTraders.Remove(name);
		}

		public void ResetNextTrader()
		{
			if (!Serviceable.TradeService.IsMainTraderInTheVillage())
			{
				FLog.Info("Reset Next Trader", "ResetNextTrader", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 237);
				float travelStartTime = -1f;
				bool flag = false;
				if (Serviceable.StateService.Trade.visit != null)
				{
					flag = true;
					travelStartTime = Serviceable.StateService.Trade.visit.travelStartTime;
				}
				Serviceable.StateService.Trade.visit = null;
				UpdateNextVisit();
				if (Serviceable.StateService.Trade.visit != null && flag)
				{
					Serviceable.StateService.Trade.visit.travelStartTime = travelStartTime;
				}
			}
		}

		public void SetEffectFreeChance(string traderName, float chance)
		{
			DynamicTraderExtraState traderGlobalEffects = stateData.GetTraderGlobalEffects(traderName);
			traderGlobalEffects.chanceToFreeEffect = chance;
			FLog.Info($"{traderName} set {chance} free effects chance.", "SetEffectFreeChance", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 261);
		}

		public void AddEffectFreeChance(string traderName, float chance)
		{
			DynamicTraderExtraState traderGlobalEffects = stateData.GetTraderGlobalEffects(traderName);
			traderGlobalEffects.chanceToFreeEffect += chance;
			FLog.Info($"{traderName} add {chance} free effects chance, now it is {traderGlobalEffects.chanceToFreeEffect}", "AddEffectFreeChance", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 268);
		}

		[HarmonyPatch(typeof(TradeService), "UpdateNextVisit")]
		[HarmonyPrefix]
		private static bool TradeService_UpdateNextVisit_PrePatch(TradeService __instance)
		{
			if (__instance.State.visit != null)
			{
				return true;
			}
			DynamicTraderInfoService service = CustomServiceManager.GetService<DynamicTraderInfoService>();
			TraderModel forceTrader = service.GetForceTrader();
			if ((Object)(object)forceTrader != (Object)null)
			{
				FLog.Info("Force to set trader as " + ((SO)forceTrader).Name, "TradeService_UpdateNextVisit_PrePatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 288);
				__instance.State.visit = __instance.CreateVisit(forceTrader, 0);
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(TradeService), "GetValueInCurrency", new Type[] { typeof(EffectModel) })]
		[HarmonyPostfix]
		private static void TradeService_GetValueInCurrency_Effect_PostPatch(TradeService __instance, ref float __result, EffectModel effect)
		{
			DynamicTraderInfoService service = CustomServiceManager.GetService<DynamicTraderInfoService>();
			if (service.stateData.GetEffectModifiedSellValue(((Object)effect).name, out var modifiedValue) && effect.tradingBuyValue != 0)
			{
				float num = __result * modifiedValue / (float)effect.tradingBuyValue;
				FLog.Info($"Change effect price from {__result} to {num}", "TradeService_GetValueInCurrency_Effect_PostPatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicTraderInfoService.cs", 311);
				__result = num;
			}
		}

		[HarmonyPatch(typeof(TradeService), "CompleteTrade", new Type[]
		{
			typeof(TraderVisitState),
			typeof(TradingOffer),
			typeof(TradingOffer)
		})]
		[HarmonyPostfix]
		private static void TradeService_CompleteTrade_PostPatch(TradeService __instance, TraderVisitState visit, TradingOffer villageOffer, TradingOffer traderOffer)
		{
			DynamicTraderInfoService service = CustomServiceManager.GetService<DynamicTraderInfoService>();
			TradeDealInfo tradeDealInfo = new TradeDealInfo
			{
				visit = visit,
				villageOffer = villageOffer,
				traderOffer = traderOffer
			};
			service.onTradeCompleteSubject.OnNext(tradeDealInfo);
		}
	}
}
namespace Forwindz
{
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "Forwindz.CustomCornerstones";

		public const string PLUGIN_NAME = "f9's cornerstones";

		public const string PLUGIN_VERSION = "1.2.2";
	}
	[BepInPlugin("Forwindz.CustomCornerstones", "f9's cornerstones", "1.2.2")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance;

		private void Awake()
		{
			Instance = this;
			ReflectUtils.InitializeAllStatics(typeof(Plugin).Assembly);
			PatchesManager.RegPatch<Plugin>();
			PatchesManager.PatchAll();
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Plugin Forwindz.CustomCornerstones is loaded!");
		}

		[HarmonyPatch(typeof(MainController), "InitReferences")]
		[HarmonyPostfix]
		private static void PostSetupMainController()
		{
			((BaseUnityPlugin)Instance).Logger.LogInfo((object)"Initializing post Init References in MainController");
			LocalizationLoader.LoadLocalization("assets/lang");
			CustomCornerstones.CreateNewCornerstones();
		}
	}
}
namespace Forwindz.Scripts.Framework.Utils
{
	public static class BuildingHelper
	{
		public static int CountDecorationValue(DecorationTier tier)
		{
			int num = 0;
			foreach (Decoration value in GameMB.BuildingsService.Decorations.Values)
			{
				if (((Building)value).IsFinished() && value.model.hasDecorationTier && (Object)(object)value.model.tier == (Object)(object)tier)
				{
					num += value.model.decorationScore;
				}
			}
			return num;
		}

		public static int CountProductionBuildingArea()
		{
			//IL_002b: 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)
			int num = 0;
			foreach (ProductionBuilding productionBuilding in GameMB.BuildingsService.ProductionBuildings)
			{
				if (((Building)productionBuilding).IsFinished())
				{
					Vector2Int size = ((Building)productionBuilding).Size;
					num += ((Vector2Int)(ref size)).x * ((Vector2Int)(ref size)).y;
				}
			}
			return num;
		}

		public static bool IsDecorationBuilding(Building building)
		{
			string name = ((Object)building.BuildingModel.category).name;
			return name.Equals("Decorations");
		}

		public static bool IsRoad(Building building)
		{
			string name = ((Object)building.BuildingModel.category).name;
			return name.Equals("Roads");
		}
	}
	public static class Debug
	{
		static Debug()
		{
			PatchesManager.RegPatch(typeof(Debug));
		}
	}
}
namespace Forwindz.Scripts.Framework.Services
{
	public class BuildingMonitorState
	{
		public int buildingsCompleted = 0;

		public int decorationBuildingsCompleted = 0;

		public int roadsCompleted = 0;

		public int buildingsRemoved = 0;

		public int decorationBuildingsRemoved = 0;

		public int roadsRemoved = 0;
	}
	public class BuildingMonitorService : GameService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		public BuildingMonitorState state = new BuildingMonitorState();

		public readonly Subject<Building> buildingConstructionFinishedSubject = new Subject<Building>();

		public readonly Subject<Building> buildingRemovedSubject = new Subject<Building>();

		public IObservable<Building> OnBuildingConstructionFinished => (IObservable<Building>)buildingConstructionFinishedSubject;

		public IObservable<Building> OnBuildingRemovedFinished => (IObservable<Building>)buildingRemovedSubject;

		static BuildingMonitorService()
		{
			CustomServiceManager.RegGameService<BuildingMonitorService>();
			PatchesManager.RegPatch<BuildingMonitorService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[4]
			{
				(IService)Serviceable.BuildingsService,
				CustomServiceManager.GetAsIService<IExtraStateService>(),
				CustomServiceManager.GetAsIService<IDynamicBuildingStateService>(),
				CustomServiceManager.GetAsIService<IDynamicHearthService>()
			};
		}

		public override void OnDestroy()
		{
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			return UniTask.CompletedTask;
		}

		protected void OnBuildingCompleted(Building building)
		{
			state.buildingsCompleted++;
			if (BuildingHelper.IsDecorationBuilding(building))
			{
				state.decorationBuildingsCompleted++;
			}
			if (BuildingHelper.IsRoad(building))
			{
				state.roadsCompleted++;
			}
			buildingConstructionFinishedSubject.OnNext(building);
		}

		protected void OnBuildingRemoved(Building building)
		{
			state.buildingsRemoved++;
			if (BuildingHelper.IsDecorationBuilding(building))
			{
				state.decorationBuildingsRemoved++;
			}
			if (BuildingHelper.IsRoad(building))
			{
				state.roadsRemoved++;
			}
			buildingRemovedSubject.OnNext(building);
		}

		[HarmonyPatch(typeof(Building), "FinishConstruction")]
		[HarmonyPostfix]
		private static void Building_FinishConstruction_Postfix(Building __instance)
		{
			FLog.Info("Building finish: " + ((Object)__instance).name + " ||\t Category: " + ((Object)__instance.BuildingModel.category).name, "Building_FinishConstruction_Postfix", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\BuildingMonitorService.cs", 105);
			CustomServiceManager.GetService<BuildingMonitorService>().OnBuildingCompleted(__instance);
		}

		[HarmonyPatch(typeof(Building), "MakeBuildingCompleted")]
		[HarmonyPostfix]
		private static void Building_MakeBuildingCompleted_Postfix(Building __instance)
		{
			FLog.Info("Make building complete: " + ((Object)__instance).name + " ||\t Category: " + ((Object)__instance.BuildingModel.category).name, "Building_MakeBuildingCompleted_Postfix", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\BuildingMonitorService.cs", 113);
			CustomServiceManager.GetService<BuildingMonitorService>().OnBuildingCompleted(__instance);
		}

		[HarmonyPatch(typeof(Building), "Remove")]
		[HarmonyPostfix]
		private static void Building_Remove_Postfix(Building __instance)
		{
			FLog.Info("Building remove: " + ((Object)__instance).name + " ||\t Category: " + ((Object)__instance.BuildingModel.category).name, "Building_Remove_Postfix", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\BuildingMonitorService.cs", 121);
			CustomServiceManager.GetService<BuildingMonitorService>().OnBuildingRemoved(__instance);
		}
	}
}
namespace Forwindz.Framework.Utils
{
	public static class AsyncUtils
	{
		public static async Task WaitForConditionAsync(Func<bool> condition, int checkInterval = 100, CancellationToken cancellationToken = default(CancellationToken))
		{
			while (!condition())
			{
				if (cancellationToken.IsCancellationRequested)
				{
					throw new TaskCanceledException();
				}
				await Task.Delay(checkInterval, cancellationToken);
			}
		}
	}
	public class CustomField<ObjectType, FieldType> where ObjectType : class where FieldType : class
	{
		private readonly ConditionalWeakTable<ObjectType, FieldType> customFields = new ConditionalWeakTable<ObjectType, FieldType>();

		private readonly Func<ObjectType, FieldType> initFieldFunc = (ObjectType inst) => null;

		public FieldType GetField(ObjectType instance)
		{
			if (customFields.TryGetValue(instance, out var value))
			{
				return value;
			}
			throw new Exception($"Try to get field {typeof(FieldType).FullName} from {typeof(ObjectType).FullName}, but instance {instance.GetHashCode()} haven't created field");
		}

		public void SetField(ObjectType instance, FieldType fieldContent)
		{
			customFields.Add(instance, fieldContent);
		}

		public void CreateField(ObjectType instance)
		{
			customFields.Add(instance, initFieldFunc(instance));
		}

		public void RemoveField(ObjectType instance)
		{
			customFields.Remove(instance);
		}

		public CustomField(Func<ObjectType, FieldType> initFieldFunc)
		{
			this.initFieldFunc = initFieldFunc;
			PatchUtils.InjectConstructorPostPatch<ObjectType>(CreateField);
		}
	}
	public struct CustomIntEnum<T> where T : Enum
	{
		public int value;

		public CustomIntEnum(int value)
		{
			this.value = value;
		}

		public static implicit operator T(CustomIntEnum<T> enumObj)
		{
			return (T)Enum.ToObject(typeof(T), enumObj.value);
		}

		public static implicit operator CustomIntEnum<T>(T enumObjOrg)
		{
			return new CustomIntEnum<T>((int)(object)enumObjOrg);
		}

		public static T GetMaxOriginalEnum()
		{
			return Enum.GetValues(typeof(T)).Cast<T>().Max();
		}

		public static int GetMaxOriginalEnumValue()
		{
			return (int)(object)Enum.GetValues(typeof(T)).Cast<T>().Max();
		}
	}
	[AttributeUsage(AttributeTargets.Field)]
	public class NewCustomEnumAttribute : Attribute
	{
		public string Name { get; }

		public object PredefinedValue { get; }

		public NewCustomEnumAttribute(string name = null, object predefinedValue = null)
		{
			Name = name;
			PredefinedValue = predefinedValue;
		}
	}
	public class CustomIntEnumManager<T> where T : Enum
	{
		private static Dictionary<string, CustomIntEnum<T>> nameEnumMapping = new Dictionary<string, CustomIntEnum<T>>();

		private static int curMaxIndex = CustomIntEnum<T>.GetMaxOriginalEnumValue();

		private static Dictionary<int, string> valueNameMapping = new Dictionary<int, string>();

		public static int CurrentMaxIndex => curMaxIndex;

		public static IReadOnlyDictionary<string, CustomIntEnum<T>> NameEnumMapping => nameEnumMapping;

		public static IReadOnlyDictionary<int, string> ValueNameMapping => valueNameMapping;

		public static CustomIntEnum<T> AddEnum(string name)
		{
			do
			{
				curMaxIndex++;
			}
			while (valueNameMapping.ContainsKey(curMaxIndex));
			CustomIntEnum<T> customIntEnum = new CustomIntEnum<T>(curMaxIndex);
			nameEnumMapping.Add(name, customIntEnum);
			valueNameMapping.Add(customIntEnum.value, name);
			FLog.Info($"Add enum {name}={customIntEnum.value} to {typeof(T).Name}", "AddEnum", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 80);
			return customIntEnum;
		}

		public static CustomIntEnum<T> AddPredefinedEnum(string name, int value)
		{
			if (value < curMaxIndex)
			{
				FLog.Error($"Try to add enum {name}={value} to {typeof(T).Name}, but the predefined value is already used. This may overwrite the previous enum!", "AddPredefinedEnum", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 88);
			}
			else if (valueNameMapping.ContainsKey(value))
			{
				FLog.Error($"Try to add enum {name}={value} to {typeof(T).Name}, but the predefined value is already used by other predefinitions. This will overwrite the previous enum!", "AddPredefinedEnum", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 92);
			}
			CustomIntEnum<T> customIntEnum = new CustomIntEnum<T>(value);
			nameEnumMapping.Add(name, customIntEnum);
			valueNameMapping.Add(customIntEnum.value, name);
			FLog.Info($"Add predefined enum {name}={customIntEnum.value} to {typeof(T).Name}", "AddPredefinedEnum", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 97);
			return customIntEnum;
		}

		public static void ScanAndAssignEnumValues<C>()
		{
			Type typeFromHandle = typeof(C);
			FieldInfo[] fields = typeFromHandle.GetFields();
			FLog.Info($"{typeof(CustomIntEnum<T>).Name}: Scan enum values for {typeof(C).Name}, static fields count {fields.Length}", "ScanAndAssignEnumValues", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 105);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				NewCustomEnumAttribute customAttribute = fieldInfo.GetCustomAttribute<NewCustomEnumAttribute>();
				if (customAttribute == null)
				{
					continue;
				}
				string name = customAttribute.Name ?? fieldInfo.Name;
				if (!fieldInfo.IsInitOnly)
				{
					FLog.Warning("Enum field " + typeFromHandle.Name + "." + fieldInfo.Name + " is not readonly. New enum should be inmutable.", "ScanAndAssignEnumValues", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 116);
				}
				FLog.Info("Find enum field: " + fieldInfo.FieldType.Name + " " + fieldInfo.Name, "ScanAndAssignEnumValues", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 118);
				Type fieldType = fieldInfo.FieldType;
				if (fieldType == typeof(CustomIntEnum<T>))
				{
					if (customAttribute.PredefinedValue == null)
					{
						fieldInfo.SetValue(null, AddEnum(name));
					}
					else
					{
						fieldInfo.SetValue(null, AddPredefinedEnum(name, (int)customAttribute.PredefinedValue));
					}
					continue;
				}
				if (fieldType == typeof(T))
				{
					if (customAttribute.PredefinedValue == null)
					{
						fieldInfo.SetValue(null, (T)AddEnum(name));
					}
					else
					{
						fieldInfo.SetValue(null, (T)AddPredefinedEnum(name, (int)customAttribute.PredefinedValue));
					}
					continue;
				}
				FLog.Error(typeFromHandle.Name + "." + fieldInfo.Name + " has incorrect type, it should be CustomEnum<" + typeof(T).Name + "," + typeFromHandle.Name + ">", "ScanAndAssignEnumValues", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\CustomIntEnum.cs", 145);
			}
		}
	}
	public static class FLog
	{
		public static ManualLogSource logger = Logger.CreateLogSource("f9");

		public static void Debug(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogDebug((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
		}

		public static void Info(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogInfo((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
		}

		public static void Warning(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogWarning((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
		}

		public static void Error(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogError((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
		}

		public static void ErrorAndThrow(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogError((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
			throw new Exception("Throw Exception:" + obj.ToString());
		}

		public static void Fatal(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogFatal((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
		}

		public static void FatalAndThrow(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogFatal((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
			throw new Exception("Throw Exception:" + obj.ToString());
		}

		public static void Message(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			logger.LogMessage((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + obj));
		}

		public static void Assert(bool result, object message, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			if (!result)
			{
				logger.LogError((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + "Assert failed!"));
				logger.LogError(message);
				throw new Exception("Assert Failed :" + message.ToString());
			}
		}

		public static void AssertNotNull<T>(T obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0) where T : class
		{
			if (obj == null)
			{
				logger.LogError((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + "Not null Assert failed! " + typeof(T).FullName));
				throw new Exception("Not null Assert Failed for " + typeof(T).FullName);
			}
		}

		public static void AssertType<T>(object obj, [CallerMemberName] string memberName = "", [CallerFilePath] string filePath = "", [CallerLineNumber] int lineNumber = 0)
		{
			if (!obj.GetType().Equals(typeof(T)))
			{
				logger.LogError((object)(ProcessMetaInfo(memberName, filePath, lineNumber) + " Type Assert failed! Get <" + obj.GetType().FullName + "> Expect <" + typeof(T).FullName + ">"));
				string text = obj?.ToString();
				if (text == null)
				{
					text = "null";
				}
				throw new Exception("Type Assert Failed :" + text);
			}
		}

		private static string ProcessMetaInfo(string memberName, string filePath, int lineNumber)
		{
			return $"[@{Path.GetFileNameWithoutExtension(filePath)}.{memberName}:{lineNumber}] ";
		}
	}
	public static class PatchesManager
	{
		private static Dictionary<Type, Harmony> patchTypes = new Dictionary<Type, Harmony>();

		public static Harmony harmony = new Harmony("Forwindz");

		private static bool dirty = true;

		public static void RegPatch<T>()
		{
			patchTypes[typeof(T)] = null;
			dirty = true;
		}

		public static void RegPatch(Type type)
		{
			patchTypes[type] = null;
			dirty = true;
		}

		public static void PatchAll()
		{
			if (!dirty)
			{
				return;
			}
			Dictionary<Type, Harmony> dictionary = new Dictionary<Type, Harmony>();
			foreach (KeyValuePair<Type, Harmony> patchType in patchTypes)
			{
				Type key = patchType.Key;
				Harmony value = patchType.Value;
				if (value == null)
				{
					FLog.Info("Try to Patch " + key.Namespace + " > " + key.Name, "PatchAll", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\PatchesManager.cs", 42);
					dictionary[key] = Harmony.CreateAndPatchAll(key, (string)null);
				}
				else
				{
					dictionary[key] = value;
				}
			}
			patchTypes = dictionary;
			dirty = false;
		}
	}
	public static class PatchUtils
	{
		public static void InjectConstructorPostPatch(Type injectClassType, MethodInfo methodInfo)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Expected O, but got Unknown
			ConstructorInfo[] constructors = injectClassType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			ConstructorInfo[] array = constructors;
			foreach (ConstructorInfo constructorInfo in array)
			{
				PatchesManager.harmony.Patch((MethodBase)constructorInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		public static void InjectConstructorPostPatch<T>(Action<T> action)
		{
			InjectConstructorPostPatch(typeof(T), ReflectUtils.GetMethodInfo(action));
		}
	}
	public static class ReflectUtils
	{
		public static MethodInfo GetMethodInfo(Action action)
		{
			return action.Method;
		}

		public static MethodInfo GetMethodInfo<T>(Action<T> action)
		{
			return action.Method;
		}

		public static MethodInfo GetMethodInfo<T, U>(Action<T, U> action)
		{
			return action.Method;
		}

		public static MethodInfo GetMethodInfo<TResult>(Func<TResult> fun)
		{
			return fun.Method;
		}

		public static MethodInfo GetMethodInfo<T, TResult>(Func<T, TResult> fun)
		{
			return fun.Method;
		}

		public static MethodInfo GetMethodInfo<T, U, TResult>(Func<T, U, TResult> fun)
		{
			return fun.Method;
		}

		public static MethodInfo GetMethodInfo(Delegate del)
		{
			return del.Method;
		}

		public static List<Type> GetAllBaseTypes(Type type)
		{
			List<Type> list = new List<Type>();
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				list.Add(baseType);
				baseType = baseType.BaseType;
			}
			return list;
		}

		public static List<Type> GetAllBaseTypesAndInterfaces(Type type)
		{
			List<Type> list = new List<Type>();
			Type baseType = type.BaseType;
			while (baseType != null)
			{
				list.Add(baseType);
				baseType = baseType.BaseType;
			}
			list.AddRange(type.GetInterfaces());
			return list;
		}

		public static void InitializeAllStatics(Assembly assembly)
		{
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (type.TypeInitializer != null)
				{
					RuntimeHelpers.RunClassConstructor(type.TypeHandle);
				}
			}
		}

		public static ConstructorInfo GetNonParameterConstructor(Type type)
		{
			ConstructorInfo[] constructors = type.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FLog.Info("Try to search non parameter constructor " + type.Name, "GetNonParameterConstructor", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\PatchUtils.cs", 87);
			ConstructorInfo[] array = constructors;
			foreach (ConstructorInfo constructorInfo in array)
			{
				ParameterInfo[] parameters = constructorInfo.GetParameters();
				Type declaringType = constructorInfo.DeclaringType;
				FLog.Info($"Detect {constructorInfo.Name} > {parameters} > {declaringType.Name} > Private {constructorInfo.IsPrivate}", "GetNonParameterConstructor", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\PatchUtils.cs", 92);
				if ((parameters == null || parameters.Length == 0) && !constructorInfo.IsStatic && declaringType.Equals(type))
				{
					return constructorInfo;
				}
			}
			return null;
		}

		public static FieldInfo GetDeclaredField<T>(string fieldName) where T : class
		{
			FieldInfo fieldInfo = AccessTools.DeclaredField(typeof(T), fieldName);
			if (fieldInfo == null)
			{
				FLog.Error("Cannot find declared field: " + typeof(T).Namespace + "." + typeof(T).Name + "." + fieldName, "GetDeclaredField", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\PatchUtils.cs", 106);
			}
			return fieldInfo;
		}

		public static FieldInfo GetField<T>(string fieldName) where T : class
		{
			FieldInfo fieldInfo = AccessTools.Field(typeof(T), fieldName);
			if (fieldInfo == null)
			{
				FLog.Error("Cannot find declared field: " + typeof(T).Namespace + "." + typeof(T).Name + "." + fieldName, "GetField", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\Base\\PatchUtils.cs", 116);
			}
			return fieldInfo;
		}
	}
	public class BroadcastCallback : IBroadcaster
	{
		public Action focusAction;

		public Action dismissAction;

		public BroadcastCallback(Action forcusAction, Action dismissAction)
		{
			focusAction = forcusAction;
			this.dismissAction = dismissAction;
		}

		public BroadcastCallback(Action forcusAction)
		{
			focusAction = forcusAction;
			dismissAction = delegate
			{
			};
		}

		public void Dismiss()
		{
			dismissAction();
		}

		public void Focus()
		{
			focusAction();
		}
	}
	public class BroadcastCallbackTranslateCameraToPos : IBroadcaster
	{
		public Vector2Int field;

		public BroadcastCallbackTranslateCameraToPos(Vector2Int field)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			this.field = field;
		}

		public void Dismiss()
		{
		}

		public void Focus()
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			SO.GameBlackboardService.OnFocusRequested.OnNext(field);
		}
	}
	public interface IDynamicValue<T>
	{
		T BaseValue { get; }

		T CurrentValue { get; set; }

		void RestoreOriginalValue();
	}
	public class DynamicValueFloat : IDynamicValue<float>
	{
		private readonly float baseValue;

		private float cacheValue;

		private readonly Func<float> getter;

		private readonly Action<float> adder;

		public float BaseValue => baseValue;

		public float CurrentValue
		{
			get
			{
				return cacheValue;
			}
			set
			{
				SetNewValue(value);
			}
		}

		public float RealValue => getter();

		public DynamicValueFloat(Func<float> getter, Action<float> adder)
		{
			this.getter = getter;
			this.adder = adder;
			cacheValue = (baseValue = this.getter());
		}

		public void SetNewValue(float newValue)
		{
			adder(newValue - cacheValue);
			cacheValue = newValue;
		}

		public void RestoreOriginalValue()
		{
			adder(baseValue - getter());
			cacheValue = baseValue;
		}
	}
	public class DynamicValueInt : IDynamicValue<int>
	{
		private readonly int baseValue;

		private int cacheValue;

		private readonly Func<int> getter;

		private readonly Action<int> adder;

		public int BaseValue => baseValue;

		public int CurrentValue
		{
			get
			{
				return cacheValue;
			}
			set
			{
				SetNewValue(value);
			}
		}

		public int RealValue => getter();

		public DynamicValueInt(Func<int> getter, Action<int> adder)
		{
			this.getter = getter;
			this.adder = adder;
			cacheValue = (baseValue = this.getter());
		}

		public void SetNewValue(int newValue)
		{
			adder(newValue - cacheValue);
			cacheValue = newValue;
		}

		public void RestoreOriginalValue()
		{
			adder(baseValue - getter());
			cacheValue = baseValue;
		}
	}
	public class DynamicValueArray<T> : IDynamicValue<T[]>
	{
		private readonly T[] baseValue;

		private readonly Func<T[]> getter;

		private readonly Action<T[]> setter;

		public T[] BaseValue => baseValue;

		public T[] CurrentValue
		{
			get
			{
				return getter();
			}
			set
			{
				setter(value);
			}
		}

		public T[] RealValue => getter();

		public DynamicValueArray(Func<T[]> getter, Action<T[]> setter)
		{
			this.getter = getter;
			this.setter = setter;
			T[] array = this.getter();
			baseValue = new T[array.Length];
			array.CopyTo(baseValue, 0);
		}

		public void AddNewValue(T newValue)
		{
			setter(ArrayExtension.ForceAdd<T>(getter(), newValue));
		}

		public void Remove(int index)
		{
			setter(getter().ForceRemove(index));
		}

		public void RestoreOriginalValue()
		{
			setter(baseValue);
		}
	}
	public class EffectAvailability
	{
		public static List<IEffectBuilder> RegularCornerstones;

		private static List<IEffectBuilder> AlreadyAddedCornerstones;

		static EffectAvailability()
		{
			RegularCornerstones = new List<IEffectBuilder>();
			AlreadyAddedCornerstones = new List<IEffectBuilder>();
			PatchesManager.RegPatch<EffectAvailability>();
		}

		private static void SetAvailableBasedOnRarity(List<IEffectBuilder> effectModelBuilders)
		{
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Invalid comparison between Unknown and I4
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Invalid comparison between Unknown and I4
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Expected O, but got Unknown
			Settings settings = SO.Settings;
			BiomeModel[] biomes = settings.biomes;
			HashSet<EffectsTable> hashSet = new HashSet<EffectsTable>();
			AlreadyAddedCornerstones.AddRange(RegularCornerstones);
			BiomeModel[] array = biomes;
			foreach (BiomeModel val in array)
			{
				int count = val.seasons.SeasonRewards.Count;
				for (int j = 0; j < count; j++)
				{
					SeasonRewardModel val2 = val.seasons.SeasonRewards[j];
					int year = val2.year;
					bool flag = year == 2 || year == 4 || year == 6;
					EffectsTable effectsTable = val2.effectsTable;
					if (hashSet.Contains(effectsTable))
					{
						continue;
					}
					hashSet.Add(effectsTable);
					EffectsTableEntity[] effects = val2.effectsTable.effects;
					List<EffectsTableEntity> list = new List<EffectsTableEntity>(effects);
					if (val2.effectsTable.effects.Length == 0)
					{
						continue;
					}
					foreach (IEffectBuilder effectModelBuilder in effectModelBuilders)
					{
						EffectModel model = effectModelBuilder.Model;
						EffectRarity rarity = model.rarity;
						EffectRarity val3 = rarity;
						if ((int)val3 != 4)
						{
							if ((int)val3 == 5 && flag)
							{
								EffectsTableEntity val4 = new EffectsTableEntity();
								val4.chance = 100;
								val4.effect = model;
								list.Add(val4);
								FLog.Info($"{((SO)val).Name} Legendary Availability: Add <{((SO)model).Name}> to Year <{year}>, Weight={val4.chance} | {list.Count}", "SetAvailableBasedOnRarity", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\EffectAvailability.cs", 78);
							}
						}
						else if (!flag)
						{
							EffectsTableEntity val5 = new EffectsTableEntity();
							val5.chance = 100;
							val5.effect = model;
							list.Add(val5);
							FLog.Info($"{((SO)val).Name} Epic Availability: Add <{((SO)model).Name}> to Year <{year}>, Weight={val5.chance} | {list.Count}", "SetAvailableBasedOnRarity", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\EffectAvailability.cs", 68);
						}
					}
					val2.effectsTable.effects = list.ToArray();
				}
			}
			RegularCornerstones.Clear();
		}

		[HarmonyPatch(typeof(BiomeManager), "SyncBiomes")]
		[HarmonyPostfix]
		private static void API_BiomeManager_SyncBiomes_PostPatch()
		{
			SetAvailableBasedOnRarity(RegularCornerstones);
		}
	}
	public static class EffectFactoryExtend
	{
		public static T CreateEffect<T>() where T : EffectModel
		{
			T val = ScriptableObject.CreateInstance<T>();
			((EffectModel)val).blockedBy = Array.Empty<EffectModel>();
			((EffectModel)val).usabilityTags = Array.Empty<ModelTag>();
			return val;
		}

		public static T CreateEffect<T>(CompositeEffectBuilder builder) where T : EffectModel
		{
			T val = ScriptableObject.CreateInstance<T>();
			((EffectModel)val).description = ((EffectBuilder<CompositeEffectModel>)(object)builder).Model.description;
			((EffectModel)val).displayName = ((EffectBuilder<CompositeEffectModel>)(object)builder).Model.displayName;
			((EffectModel)val).label = ((EffectBuilder<CompositeEffectModel>)(object)builder).Model.label;
			((EffectModel)val).blockedBy = Array.Empty<EffectModel>();
			((EffectModel)val).usabilityTags = Array.Empty<ModelTag>();
			return val;
		}

		public static T CreateEffect<T>(HookedEffectBuilder builder) where T : EffectModel
		{
			return EffectFactory.NewHookedEffect<T>((IEffectBuilder)(object)builder);
		}

		public static ChanceForNoConsumptionEffectModel AddHookedEffect_ChanceForNoConsumptionEffectModel(IEffectBuilder effectBuilder, float amount)
		{
			ChanceForNoConsumptionEffectModel val = EffectFactory.NewHookedEffect<ChanceForNoConsumptionEffectModel>(effectBuilder);
			val.amount = amount;
			return val;
		}

		public static GoodEdibleEffectModel AddHookedEffect_GoodEdibleEffectModel(IEffectBuilder effectBuilder, GoodModel goodModel, bool ediable)
		{
			GoodEdibleEffectModel goodEdibleEffectModel = EffectFactory.NewHookedEffect<GoodEdibleEffectModel>(effectBuilder);
			goodEdibleEffectModel.good = goodModel;
			goodEdibleEffectModel.eatable = ediable;
			return goodEdibleEffectModel;
		}

		public static AddTraderFreeEffectChanceEffectModel AddHookedEffect_AddTraderFreeEffectChanceEffectModel(IEffectBuilder effectBuilder, TraderModel traderModel, float chance)
		{
			AddTraderFreeEffectChanceEffectModel addTraderFreeEffectChanceEffectModel = EffectFactory.NewHookedEffect<AddTraderFreeEffectChanceEffectModel>(effectBuilder);
			addTraderFreeEffectChanceEffectModel.trader = traderModel;
			addTraderFreeEffectChanceEffectModel.chance = chance;
			return addTraderFreeEffectChanceEffectModel;
		}

		public static OnlyTraderEffectModel AddHookedEffect_OnlyTraderEffectModel(IEffectBuilder effectBuilder, TraderModel traderModel)
		{
			OnlyTraderEffectModel onlyTraderEffectModel = EffectFactory.NewHookedEffect<OnlyTraderEffectModel>(effectBuilder);
			onlyTraderEffectModel.trader = traderModel;
			return onlyTraderEffectModel;
		}

		public static TraderIntervalEffectModel AddHookedEffect_TraderIntervalEffectModel(IEffectBuilder effectBuilder, float amount)
		{
			TraderIntervalEffectModel val = EffectFactory.NewHookedEffect<TraderIntervalEffectModel>(effectBuilder);
			val.amount = amount;
			return val;
		}

		public static HearthPopPercentEffectModel AddHookedEffect_HearthPopPercentEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			HearthPopPercentEffectModel hearthPopPercentEffectModel = EffectFactory.NewHookedEffect<HearthPopPercentEffectModel>(effectBuilder);
			hearthPopPercentEffectModel.percent = percent;
			return hearthPopPercentEffectModel;
		}

		public static DecorationPercentEffectModel AddHookedEffect_DecorationPercentEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			DecorationPercentEffectModel decorationPercentEffectModel = EffectFactory.NewHookedEffect<DecorationPercentEffectModel>(effectBuilder);
			decorationPercentEffectModel.percent = percent;
			return decorationPercentEffectModel;
		}

		public static VillagersBreakTimeRateEffectModel AddHookedEffect_VillagersBreakTimeRateEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			VillagersBreakTimeRateEffectModel val = EffectFactory.NewHookedEffect<VillagersBreakTimeRateEffectModel>(effectBuilder);
			val.amount = percent;
			return val;
		}

		public static GlobalProductionRateEffectModel AddHookedEffect_GlobalProductionRateEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			GlobalProductionRateEffectModel val = EffectFactory.NewHookedEffect<GlobalProductionRateEffectModel>(effectBuilder);
			val.amount = percent;
			return val;
		}

		public static HarvestingRateEffectModel AddHookedEffect_HarvestingRateEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			HarvestingRateEffectModel val = EffectFactory.NewHookedEffect<HarvestingRateEffectModel>(effectBuilder);
			val.amount = percent;
			return val;
		}

		public static VillagersSpeedEffectModel AddHookedEffect_VillagersSpeedEffectModel(IEffectBuilder effectBuilder, VillagerSpeedRewardType type, float percent)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			VillagersSpeedEffectModel val = EffectFactory.NewHookedEffect<VillagersSpeedEffectModel>(effectBuilder);
			val.type = type;
			val.amount = percent;
			return val;
		}

		public static GlobalExtraProductionChanceEffectModel AddHookedEffect_GlobalExtraProductionChanceEffectModel(IEffectBuilder effectBuilder, float percent)
		{
			GlobalExtraProductionChanceEffectModel val = EffectFactory.NewHookedEffect<GlobalExtraProductionChanceEffectModel>(effectBuilder);
			((BaseRateAmountEffectModel)val).amount = percent;
			return val;
		}
	}
	public static class GUIDManagerExtend
	{
		public static T Get<T>(string guid, string name)
		{
			return GUIDManager.Get<T>("Forwindz.CustomCornerstones", typeof(T).FullName + "." + name);
		}
	}
	public static class HookFactoryExtend
	{
		public static GoodProducedHook Create_GoodProducedHook(GoodRef goodRef, bool cycles)
		{
			return new GoodProducedHook
			{
				good = goodRef,
				cycles = cycles
			};
		}

		public static DecorationHook Create_DecorationHook(DecorationTier tier, int amount)
		{
			return new DecorationHook
			{
				decorationTier = tier,
				amount = amount
			};
		}
	}
	public class LocalizationLoader
	{
		public static void LoadLocalization(string folderPath = "lang")
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
			FLog.Info("f9 cornerstone plugin patcher path " + directoryName, "LoadLocalization", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\LocalizationLoader.cs", 23);
			string path = Path.Combine(directoryName, folderPath);
			try
			{
				string[] files = Directory.GetFiles(path, "*.json", SearchOption.AllDirectories);
				string[] array = files;
				foreach (string text in array)
				{
					try
					{
						string text2 = File.ReadAllText(text);
						Dictionary<string, string> dictionary = JSON.FromJson<Dictionary<string, string>>(text2);
						string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(text);
						SystemLanguage val = LocalizationManager.CodeToLanguage(fileNameWithoutExtension);
						foreach (KeyValuePair<string, string> item in dictionary)
						{
							LocalizationManager.AddString(item.Key, item.Value, val);
						}
						Log.Info((object)$"Load {dictionary.Count} entries for {val} language, from {text}", (Object)null);
					}
					catch (Exception ex)
					{
						Log.Error((object)("Error while processing localization file: " + text), (Object)null);
						Log.Error((object)ex, (Object)null);
					}
				}
			}
			catch (Exception ex2)
			{
				Log.Error((object)ex2, (Object)null);
			}
		}
	}
	public class StableRNG
	{
		private static float expectChance = 0f;

		private static float hitCount = 0f;

		private const float tolerateGap = 1f;

		private static float feelUnlucky = 0f;

		private static float unluckyTimes = 0.1f;

		private const float tolerateUnluckyGap = 10f;

		private const float unluckyBonusRatio = 0.02f;

		private const float luckyReduceFactor = 0.1f;

		private static float lastFeelUnluckyTime = -1f;

		private const float regardAsUnluckyInterval = 5f;

		public static bool StableRoll(float chance, float weight, bool isPositive)
		{
			if (chance <= 0f)
			{
				return false;
			}
			if (isPositive)
			{
				return StableRoll(chance, weight);
			}
			return !StableRoll(1f - chance, weight);
		}

		public static bool StableRoll(float chance, float weight = 1f)
		{
			float num = Mathf.Max(expectChance - hitCount - 1f, 0f) + Mathf.Max(0.02f * (feelUnlucky - 10f), 0f) + 1f;
			bool flag = RNG.Roll(num * chance);
			if (flag)
			{
				hitCount += weight;
				feelUnlucky *= 0.1f;
				unluckyTimes *= 0.1f;
			}
			else
			{
				if (CheckUnluckyInterval())
				{
					unluckyTimes += weight;
				}
				feelUnlucky += weight * unluckyTimes;
			}
			expectChance += chance * weight;
			FLog.Info($"RNG Roll: {chance * 100f:F2}% * {num * 100f:F2}% | Exp: {(expectChance - hitCount) * 100f:F2}% | Unlucky: {feelUnlucky:F3}, Times: {unluckyTimes:F3}", "StableRoll", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\StableRNG.cs", 82);
			return flag;
		}

		public static float StableRandom(Vector2 range, float weight = 1f, bool higherIsPositive = true)
		{
			//IL_0065: 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_0074: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(expectChance - hitCount - 1f, 0f) + Mathf.Max(0.02f * (feelUnlucky - 10f), 0f);
			float num2 = Mathf.Min(RNG.Float(0f, 1f) * (1f + RNG.Float(0f, num)), 1f);
			float result = (range.y - range.x) * num2 + range.x;
			if (higherIsPositive)
			{
				StableRandomAdjustState(num2, weight);
			}
			else
			{
				StableRandomAdjustState(1f - num2, weight);
			}
			FLog.Info($"RNG Range: {num2 * 100f:F2}% + {num * 100f:F2}% | Exp: {(expectChance - hitCount) * 100f:F2}% | Unlucky: {feelUnlucky:F3}, Times: {unluckyTimes:F3}", "StableRandom", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\StableRNG.cs", 102);
			return result;
		}

		public static int StableCritialTimes(float chance, float weight = 1f, bool higherIsPositive = true)
		{
			int num = (int)chance;
			if (StableRoll(chance - (float)num, weight / (float)(num + 1), higherIsPositive))
			{
				num++;
			}
			return num;
		}

		private static void StableRandomAdjustState(float rngResult, float weight)
		{
			if (rngResult < 0.5f)
			{
				if (CheckUnluckyInterval())
				{
					unluckyTimes += weight;
				}
				feelUnlucky += (1f - rngResult * rngResult) * weight * unluckyTimes;
			}
			else if (rngResult > 0.7f)
			{
				float num = Mathf.Max(1.01f, 1.1f) - rngResult;
				num *= num;
				feelUnlucky *= num;
				unluckyTimes *= num;
			}
			hitCount += rngResult * weight;
			expectChance += 0.5f * weight;
		}

		private static bool CheckUnluckyInterval()
		{
			float unscaledTime = Time.unscaledTime;
			if (lastFeelUnluckyTime < 0f)
			{
				FLog.Info($"RNG New Time: {unscaledTime}", "CheckUnluckyInterval", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\StableRNG.cs", 143);
				lastFeelUnluckyTime = unscaledTime;
				return false;
			}
			if (unscaledTime - lastFeelUnluckyTime > 5f)
			{
				FLog.Info($"RNG Time gap: {unscaledTime - lastFeelUnluckyTime}, New Unlucky Event!", "CheckUnluckyInterval", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Utils\\StableRNG.cs", 151);
				lastFeelUnluckyTime = unscaledTime;
				return true;
			}
			return false;
		}
	}
	public static class Utils
	{
		public static string GetMd5Hash(string input)
		{
			using MD5 mD = MD5.Create();
			byte[] array = mD.ComputeHash(Encoding.UTF8.GetBytes(input));
			StringBuilder stringBuilder = new StringBuilder();
			byte[] array2 = array;
			foreach (byte b in array2)
			{
				stringBuilder.Append(b.ToString("x2"));
			}
			return stringBuilder.ToString();
		}

		public static T GetValue<T>(this WeakReference<T> instance) where T : class
		{
			if (instance.TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static void SetSeasonsTime(float drizzleTime, float clearanceTime, float stormTime, SeasonQuarter firstCornerstoneTime = 1)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			BiomeModel[] biomes = MB.Settings.biomes;
			foreach (BiomeModel val in biomes)
			{
				val.seasons.DrizzleTime = drizzleTime;
				val.seasons.ClearanceTime = clearanceTime;
				val.seasons.StormTime = stormTime;
				val.seasons.SeasonRewards[0].quarter = firstCornerstoneTime;
			}
		}

		public static string GetGoodIconAndName(GoodModel good)
		{
			string text = ((SO)good).Name;
			int num = text.LastIndexOf("]");
			if (num != -1)
			{
				text = text.Substring(num + 1);
			}
			else if (text.Contains("_Meta"))
			{
				text = text.Substring("_Meta".Length + 1);
			}
			text = text.Trim();
			return "<sprite name=\"" + ((SO)good).Name.ToLowerInvariant() + "\"> " + text;
		}
	}
}
namespace Forwindz.Framework.Utils.Extend
{
	public static class ArrayExt
	{
		public static T[] ForceAdd<T>(this T[] source, T item)
		{
			T[] array = new T[source.Length + 1];
			source.CopyTo(array, 0);
			array[^1] = item;
			return array;
		}

		public static void ForceAdd<T>(ref T[] source, T item)
		{
			source = source.ForceAdd(item);
		}

		public static T[] ForceRemove<T>(this T[] source, T item)
		{
			return source.ForceRemove(Array.IndexOf(source, item));
		}

		public static T[] ForceRemove<T>(this T[] source, int index)
		{
			if (index < 0)
			{
				return source;
			}
			T[] array = new T[source.Length - 1];
			if (index > 0)
			{
				Array.Copy(source, 0, array, 0, index);
			}
			if (index < source.Length - 1)
			{
				Array.Copy(source, index + 1, array, index, source.Length - index - 1);
			}
			return array;
		}

		public static void ForceRemove<T>(ref T[] source, T item)
		{
			source = source.ForceRemove(item);
		}
	}
	public static class GoodModelExt
	{
		public static bool ContainTag(this GoodModel goodModel, string name)
		{
			ModelTag[] tags = goodModel.tags;
			foreach (ModelTag val in tags)
			{
				if (((SO)val).Name.Equals(name))
				{
					return true;
				}
			}
			return false;
		}
	}
	public static class SOExtend
	{
		public static List<T> DeepClone<T>(this List<T> objs) where T : SO
		{
			List<T> list = new List<T>();
			list.Capacity = objs.Count;
			for (int i = 0; i < objs.Count; i++)
			{
				list.Add(((SO)(object)objs[i]).DeepClone<T>());
			}
			return list;
		}

		public static T[] DeepClone<T>(this T[] objs) where T : SO
		{
			T[] array = new T[objs.Length];
			for (int i = 0; i < objs.Length; i++)
			{
				array[i] = ((SO)(object)objs[i]).DeepClone<T>();
			}
			return array;
		}

		public static T Clone<T>(this T original) where T : SO
		{
			if ((Object)(object)original == (Object)null)
			{
				return default(T);
			}
			return Object.Instantiate<T>(original);
		}

		public static SO DeepClone(this SO original)
		{
			if ((Object)(object)original == (Object)null)
			{
				return null;
			}
			SO val = Object.Instantiate<SO>(original);
			SODeepCopyFields(original, val);
			return val;
		}

		public static T DeepClone<T>(this SO original) where T : SO
		{
			return (T)(object)original.DeepClone();
		}

		private static void SODeepCopyFields(object source, object destination)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			FieldInfo[] fields = source.GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				if (!fieldInfo.IsNotSerialized && fieldInfo.FieldType.IsSubclassOf(typeof(SO)))
				{
					SO val = (SO)fieldInfo.GetValue(source);
					SO value = (((Object)(object)val != (Object)null) ? val.DeepClone() : null);
					fieldInfo.SetValue(destination, value);
				}
			}
		}
	}
	public static class TextArgExt
	{
		public static TextArg[] ToTextArgArray(this (TextArgType type, int sourceIndex)[] args)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Expected O, but got Unknown
			TextArg[] array = (TextArg[])(object)new TextArg[args.Length];
			for (int i = 0; i < args.Length; i++)
			{
				array[i] = new TextArg
				{
					sourceIndex = args[i].sourceIndex,
					type = args[i].type
				};
			}
			return array;
		}

		public static TextArg ToTextArg(this (TextArgType type, int sourceIndex) arg)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//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_001f: Expected O, but got Unknown
			TextArg val = new TextArg();
			(val.type, val.sourceIndex) = arg;
			return val;
		}
	}
}
namespace Forwindz.Framework.Services
{
	public static class CustomServiceManager
	{
		private static readonly List<Type> appExtraServiceTypes;

		private static readonly List<Type> gameExtraServiceTypes;

		private static readonly List<Type> metaExtraServiceTypes;

		private static readonly List<Type> worldExtraServiceTypes;

		private static Dictionary<Type, WeakReference<IService>> customServices;

		private static WeakReference<List<IService>> gameServices;

		private static WeakReference<List<IService>> metaServices;

		private static WeakReference<List<IService>> appServices;

		private static WeakReference<List<IService>> worldServices;

		public static IReadOnlyList<IService> GameServicesList => gameServices.GetValue();

		public static IReadOnlyList<IService> MetaServicesList => metaServices.GetValue();

		public static IReadOnlyList<IService> AppServicesList => appServices.GetValue();

		public static IReadOnlyList<IService> WorldServicesList => worldServices.GetValue();

		static CustomServiceManager()
		{
			appExtraServiceTypes = new List<Type>();
			gameExtraServiceTypes = new List<Type>();
			metaExtraServiceTypes = new List<Type>();
			worldExtraServiceTypes = new List<Type>();
			customServices = new Dictionary<Type, WeakReference<IService>>();
			gameServices = null;
			metaServices = null;
			appServices = null;
			worldServices = null;
			PatchesManager.RegPatch(typeof(CustomServiceManager));
		}

		public static void RegAppService<T>() where T : IService
		{
			appExtraServiceTypes.Add(typeof(T));
		}

		public static void RegGameService<T>() where T : IService
		{
			gameExtraServiceTypes.Add(typeof(T));
		}

		public static void RegMetaService<T>() where T : IService
		{
			metaExtraServiceTypes.Add(typeof(T));
		}

		public static void RegWorldService<T>() where T : IService
		{
			worldExtraServiceTypes.Add(typeof(T));
		}

		public static T GetService<T>()
		{
			if (customServices[typeof(T)].TryGetTarget(out var target))
			{
				return (T)(object)target;
			}
			return default(T);
		}

		public static IService GetAsIService<T>()
		{
			if (customServices[typeof(T)].TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static IService GetService(Type type)
		{
			if (customServices[type].TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static IService GetServiceSafe(Type type)
		{
			if (customServices.TryGetValue(type, out var value) && value.TryGetTarget(out var target))
			{
				return target;
			}
			return null;
		}

		public static T GetServiceSafe<T>() where T : IService
		{
			if (customServices.TryGetValue(typeof(T), out var value) && value.TryGetTarget(out var target) && target is T result)
			{
				return result;
			}
			return default(T);
		}

		[HarmonyPatch(typeof(WorldServices), "CreateServices")]
		[HarmonyPrefix]
		private static void WorldServicesCreate_PrePatch(WorldServices __instance)
		{
			foreach (Type worldExtraServiceType in worldExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, worldExtraServiceType);
			}
			FLog.Info($"Try to create {worldExtraServiceTypes.Count} services in WorldServices", "WorldServicesCreate_PrePatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 155);
			worldServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		[HarmonyPatch(typeof(AppServices), "CreateServices")]
		[HarmonyPrefix]
		private static void AppServicesCreate_PrePatch(AppServices __instance)
		{
			foreach (Type appExtraServiceType in appExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, appExtraServiceType);
			}
			FLog.Info($"Try to create {appExtraServiceTypes.Count} services in AppServices", "AppServicesCreate_PrePatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 168);
			appServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		[HarmonyPatch(typeof(GameServices), "CreateServices")]
		[HarmonyPostfix]
		private static void GameServicesCreate_PostPatch(GameServices __instance)
		{
			foreach (Type gameExtraServiceType in gameExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, gameExtraServiceType);
			}
			FLog.Info($"Try to create {gameExtraServiceTypes.Count} services in GameServices", "GameServicesCreate_PostPatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 181);
			gameServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		[HarmonyPatch(typeof(MetaServices), "CreateServices")]
		[HarmonyPrefix]
		private static void MetaServicesCreate_PrePatch(MetaServices __instance)
		{
			foreach (Type metaExtraServiceType in metaExtraServiceTypes)
			{
				CreateServiceToList(__instance.allServices, metaExtraServiceType);
			}
			FLog.Info($"Try to create {metaExtraServiceTypes.Count} services in MetaServices", "MetaServicesCreate_PrePatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 194);
			metaServices = new WeakReference<List<IService>>(__instance.allServices);
		}

		private static void CreateServiceToList(List<IService> allServices, Type serviceType)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Expected O, but got Unknown
			FLog.Info("Try to create service " + serviceType.FullName, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 200);
			FLog.AssertNotNull(allServices, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 201);
			FLog.AssertNotNull(customServices, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 202);
			FLog.AssertNotNull(serviceType, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 203);
			ConstructorInfo nonParameterConstructor = ReflectUtils.GetNonParameterConstructor(serviceType);
			FLog.AssertNotNull(nonParameterConstructor, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 205);
			IService val = null;
			try
			{
				val = (IService)nonParameterConstructor.Invoke(null);
			}
			catch (Exception obj)
			{
				FLog.Error("Failed to create service!", "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 213);
				FLog.Error(obj, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 214);
			}
			FLog.AssertNotNull<IService>(val, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 217);
			List<Type> list = new List<Type>();
			list.AddRange(serviceType.GetInterfaces());
			list.Add(serviceType);
			list.AddRange(TypeExtensions.GetBaseTypes(serviceType, false));
			List<Type> list2 = list;
			foreach (Type item in list2)
			{
				if (!(item == null) && GetServiceSafe(item) == null)
				{
					customServices[item] = new WeakReference<IService>(val);
					FLog.Info("Add Service " + serviceType.Name + " as " + item.Name, "CreateServiceToList", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\Base\\CustomServiceManager.cs", 230);
				}
			}
			allServices.Add(val);
		}
	}
	internal class DecorationModelDelegate
	{
		public DynamicValueInt decorationScoreDynamic;

		public DecorationModelDelegate(DecorationModel decorationModel)
		{
			decorationScoreDynamic = new DynamicValueInt(() => decorationModel.decorationScore, delegate(int delta)
			{
				DecorationModel obj = decorationModel;
				obj.decorationScore += delta;
			});
		}

		public void RestoreToOriginal()
		{
			decorationScoreDynamic.RestoreOriginalValue();
		}
	}
	public class DynamicDecorationStateInfo
	{
		public float decorationPercent = 1f;
	}
	internal class DynamicBuildingState
	{
		[JsonIgnore]
		public Dictionary<string, DecorationModelDelegate> originalDecorations = new Dictionary<string, DecorationModelDelegate>();

		public Dictionary<string, DynamicDecorationStateInfo> decorationStates = new Dictionary<string, DynamicDecorationStateInfo>();

		public void InitGame()
		{
			List<DecorationModel> list = LinqExtensions.FilterCast<DecorationModel>((IEnumerable)MB.Settings.Buildings).ToList();
			foreach (DecorationModel item in list)
			{
				originalDecorations[((SO)item).Name] = new DecorationModelDelegate(item);
			}
			ApplyStates();
		}

		public void AddDecorationPercent(string decoName, float percent)
		{
			if (decorationStates.TryGetValue(decoName, out var value))
			{
				value.decorationPercent += percent;
				return;
			}
			value = new DynamicDecorationStateInfo();
			value.decorationPercent += percent;
			decorationStates[decoName] = value;
		}

		public float GetDecorationPercent(string decoName)
		{
			if (decorationStates.TryGetValue(decoName, out var value))
			{
				return value.decorationPercent;
			}
			return 1f;
		}

		public void ApplyStates()
		{
			foreach (string key in decorationStates.Keys)
			{
				ApplyDecorationState(key);
			}
		}

		public void ApplyDecorationState(string decoName)
		{
			DynamicDecorationStateInfo dynamicDecorationStateInfo = decorationStates[decoName];
			DecorationModelDelegate decorationModelDelegate = originalDecorations[decoName];
			DynamicValueInt decorationScoreDynamic = decorationModelDelegate.decorationScoreDynamic;
			decorationScoreDynamic.SetNewValue((int)((float)decorationModelDelegate.decorationScoreDynamic.BaseValue * dynamicDecorationStateInfo.decorationPercent));
		}

		public void DestoryRestore()
		{
			foreach (string key in decorationStates.Keys)
			{
				DecorationModelDelegate decorationModelDelegate = originalDecorations[key];
				decorationModelDelegate.RestoreToOriginal();
			}
		}
	}
	public class DynamicBuildingStateService : GameService, IDynamicBuildingStateService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		private DynamicBuildingState state = new DynamicBuildingState();

		private FieldInfo fieldInfo_decorationTypeOwning = null;

		private FieldInfo fieldInfo_monitor = null;

		internal static float MIN_DECO_RATIO;

		public readonly Subject<Dictionary<string, DynamicDecorationStateInfo>> decorationValueChangeSubject = new Subject<Dictionary<string, DynamicDecorationStateInfo>>();

		public IObservable<Dictionary<string, DynamicDecorationStateInfo>> OnDecorationValueChange => (IObservable<Dictionary<string, DynamicDecorationStateInfo>>)decorationValueChangeSubject;

		public OrdersMonitor Reflect_OrderService_monitor => (OrdersMonitor)(fieldInfo_monitor?.GetValue(Serviceable.OrdersService));

		public Dictionary<ObjectiveState, DecorationTypeOwningLogic> Reflect_OrderMonitor_decorationTypeOwning
		{
			get
			{
				OrdersMonitor reflect_OrderService_monitor = Reflect_OrderService_monitor;
				if (reflect_OrderService_monitor == null)
				{
					return null;
				}
				return (Dictionary<ObjectiveState, DecorationTypeOwningLogic>)(fieldInfo_decorationTypeOwning?.GetValue(reflect_OrderService_monitor));
			}
		}

		static DynamicBuildingStateService()
		{
			MIN_DECO_RATIO = 0.1f;
			CustomServiceManager.RegGameService<DynamicBuildingStateService>();
			PatchesManager.RegPatch<DynamicBuildingStateService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[4]
			{
				(IService)Serviceable.BuildingsService,
				(IService)Serviceable.RecipesService,
				(IService)Serviceable.OrdersService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public override void OnDestroy()
		{
			state.DestoryRestore();
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0034: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			fieldInfo_monitor = ReflectUtils.GetDeclaredField<OrdersService>("monitor");
			fieldInfo_decorationTypeOwning = ReflectUtils.GetDeclaredField<OrdersMonitor>("decorationTypeOwning");
			state.InitGame();
			UpdateDecorationOrder();
			return UniTask.CompletedTask;
		}

		private void UpdateDecorationOrder()
		{
			Dictionary<ObjectiveState, DecorationTypeOwningLogic> reflect_OrderMonitor_decorationTypeOwning = Reflect_OrderMonitor_decorationTypeOwning;
			if (reflect_OrderMonitor_decorationTypeOwning == null)
			{
				FLog.Error("Failed to get decoration orders, the decoration order info cannot be refreshed!", "UpdateDecorationOrder", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicBuildingStateService.cs", 207);
				return;
			}
			foreach (KeyValuePair<ObjectiveState, DecorationTypeOwningLogic> item in reflect_OrderMonitor_decorationTypeOwning)
			{
				ObjectiveState key = item.Key;
				DecorationTypeOwningLogic value = item.Value;
				((OrderLogic)value).InitState(key);
			}
		}

		public void AddDecorationPercent(string decorationName, float percent)
		{
			AddDecorationPercentWithoutUpdate(decorationName, percent);
			decorationValueChangeSubject.OnNext(state.decorationStates);
			UpdateDecorationInfo();
		}

		private void AddDecorationPercentWithoutUpdate(string decorationName, float percent)
		{
			state.AddDecorationPercent(decorationName, percent);
			state.ApplyDecorationState(decorationName);
		}

		public void AddAllDecorationPercent(float percent)
		{
			foreach (string key in state.originalDecorations.Keys)
			{
				AddDecorationPercentWithoutUpdate(key, percent);
				state.ApplyDecorationState(key);
			}
			UpdateDecorationInfo();
		}

		private void UpdateDecorationInfo()
		{
			decorationValueChangeSubject.OnNext(state.decorationStates);
			UpdateDecorationOrder();
		}

		public float GetDecorationPercent(string decorationName)
		{
			return state.GetDecorationPercent(decorationName);
		}

		public int GetDecorationAmount(DecorationTier tier)
		{
			return Serviceable.BuildingsService.Decorations.Values.Sum((Decoration d) => (((Building)d).IsFinished() && d.model.hasDecorationTier && (Object)(object)d.model.tier == (Object)(object)tier) ? d.model.decorationScore : 0);
		}

		[HarmonyPatch(typeof(ConstructionService), "GetConstructionCostFor")]
		[HarmonyPostfix]
		private static void ConstructionService_GetConstructionCostFor_PostPatch(ConstructionService __instance, BuildingModel building)
		{
			DecorationModel val = (DecorationModel)(object)((building is DecorationModel) ? building : null);
			if (val == null)
			{
				return;
			}
			DynamicBuildingStateService service = CustomServiceManager.GetService<DynamicBuildingStateService>();
			if (service == null)
			{
				FLog.Error("Service is not inited!", "ConstructionService_GetConstructionCostFor_PostPatch", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicBuildingStateService.cs", 283);
				return;
			}
			float decorationPercent = service.state.GetDecorationPercent(((SO)val).Name);
			if (decorationPercent != 1f)
			{
				decorationPercent = Mathf.Max(MIN_DECO_RATIO, decorationPercent);
				float num = 1f / decorationPercent;
				Good[] requiredGoods = building.GetRequiredGoods(__instance.GetCurrentCostsRate() * num);
			}
		}
	}
	internal class DynamicCornerstoneState
	{
		public int noYearlyCornerstone = 0;
	}
	public class DynamicCornerstoneService : GameService, IDynamicCornerstoneService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		internal DynamicCornerstoneState state = new DynamicCornerstoneState();

		static DynamicCornerstoneService()
		{
			CustomServiceManager.RegGameService<DynamicCornerstoneService>();
			PatchesManager.RegPatch<DynamicCornerstoneService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[1] { CustomServiceManager.GetAsIService<IExtraStateService>() };
		}

		public override UniTask OnLoading()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			return ((Service)this).OnLoading();
		}

		public override void OnDestroy()
		{
			((Service)this).OnDestroy();
		}

		public void SetNoCornerstone(bool v)
		{
			state.noYearlyCornerstone += (v ? 1 : (-1));
		}

		public bool GetNoCornerstone()
		{
			return state.noYearlyCornerstone > 0;
		}

		[HarmonyPatch(typeof(CornerstonesService), "CheckForPick")]
		[HarmonyPrefix]
		private static bool CornerstonesService_CheckForPick_PrePatch(CornerstonesService __instance)
		{
			DynamicCornerstoneService service = CustomServiceManager.GetService<DynamicCornerstoneService>();
			if (service == null)
			{
				return true;
			}
			if (service.GetNoCornerstone())
			{
				return false;
			}
			return true;
		}
	}
	public class ModifyGoodTypeState
	{
		public enum OperationType
		{
			SetEdiable,
			SetBurnable,
			SetTag
		}

		[JsonProperty]
		public readonly OperationType op;

		[JsonProperty]
		public readonly string content;

		[JsonProperty]
		public readonly bool boolState;

		private ModifyGoodTypeState()
		{
		}

		private ModifyGoodTypeState(OperationType op, string content, bool boolState)
		{
			this.op = op;
			this.content = content;
			this.boolState = boolState;
		}

		public static ModifyGoodTypeState GenAddTag(string tagName)
		{
			return new ModifyGoodTypeState(OperationType.SetTag, tagName, boolState: true);
		}

		public static ModifyGoodTypeState GenRemoveTag(string tagName)
		{
			return new ModifyGoodTypeState(OperationType.SetTag, tagName, boolState: false);
		}

		public static ModifyGoodTypeState GenSetEdiable(bool ediable)
		{
			return new ModifyGoodTypeState(OperationType.SetEdiable, null, ediable);
		}

		public static ModifyGoodTypeState GenSetBurnable(bool burnable)
		{
			return new ModifyGoodTypeState(OperationType.SetBurnable, null, burnable);
		}

		public bool IsAlreadyApplied(GoodModel goodModel)
		{
			switch (op)
			{
			case OperationType.SetEdiable:
				return goodModel.eatable == boolState;
			case OperationType.SetBurnable:
				return goodModel.canBeBurned = boolState;
			case OperationType.SetTag:
				if (boolState)
				{
					return goodModel.ContainTag(content);
				}
				return !goodModel.ContainTag(content);
			default:
				FLog.Warning($"Unknown enum values {op} in ModifyGoodTypeState", "IsAlreadyApplied", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 89);
				return false;
			}
		}

		public void ApplyState(GoodModel goodModel)
		{
			switch (op)
			{
			case OperationType.SetEdiable:
				goodModel.eatable = boolState;
				if (boolState)
				{
					Serviceable.StateService.Actors.rawFoodConsumptionPermits[((SO)goodModel).Name] = true;
				}
				else
				{
					Serviceable.StateService.Actors.rawFoodConsumptionPermits.Remove(((SO)goodModel).Name);
				}
				break;
			case OperationType.SetBurnable:
				goodModel.canBeBurned = boolState;
				Serviceable.HearthService.SetCanBeBurned(((SO)goodModel).Name, boolState);
				break;
			case OperationType.SetTag:
				if (boolState)
				{
					ArrayExt.ForceAdd(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				else
				{
					ArrayExt.ForceRemove(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				break;
			default:
				FLog.Warning($"Unknown enum values {op} in ModifyGoodTypeState", "ApplyState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 126);
				break;
			}
		}

		public void RemoveState(GoodModel goodModel)
		{
			switch (op)
			{
			case OperationType.SetEdiable:
				goodModel.eatable = !boolState;
				break;
			case OperationType.SetBurnable:
				goodModel.canBeBurned = !boolState;
				break;
			case OperationType.SetTag:
				if (!boolState)
				{
					ArrayExt.ForceAdd(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				else
				{
					ArrayExt.ForceRemove(ref goodModel.tags, Serviceable.Settings.GetTag(content));
				}
				break;
			default:
				FLog.Warning($"Unknown enum values {op} in ModifyGoodTypeState", "RemoveState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 153);
				break;
			}
		}

		public ModifyGoodTypeState GenerateInverseState()
		{
			return new ModifyGoodTypeState(op, content, !boolState);
		}

		public override bool Equals(object obj)
		{
			if (obj is ModifyGoodTypeState modifyGoodTypeState)
			{
				if (modifyGoodTypeState.op == op)
				{
					switch (op)
					{
					case OperationType.SetEdiable:
					case OperationType.SetBurnable:
						return modifyGoodTypeState.boolState == boolState;
					case OperationType.SetTag:
						return modifyGoodTypeState.boolState == boolState && modifyGoodTypeState.content.Equals(content);
					}
				}
				return false;
			}
			return base.Equals(obj);
		}

		public override int GetHashCode()
		{
			uint num = (boolState ? 1u : 0u);
			uint num2 = ((op == OperationType.SetTag) ? ((uint)EqualityComparer<string>.Default.GetHashCode(content)) : 0u);
			uint hashCode = (uint)op.GetHashCode();
			return (int)((num << 31) | ((hashCode & 3) << 29)) | ((int)num2 & -1);
		}

		public override string ToString()
		{
			int num = (boolState ? 1 : 0);
			string text = $"{num}_{op.ToString()}";
			if (op == OperationType.SetTag)
			{
				text = text + "_" + content;
			}
			return text;
		}

		public string ToInvString()
		{
			int num = ((!boolState) ? 1 : 0);
			string text = $"{num}_{op.ToString()}";
			if (op == OperationType.SetTag)
			{
				text = text + "_" + content;
			}
			return text;
		}
	}
	public class ModifyGoodTypeInfo
	{
		[JsonProperty]
		private string goodName;

		[JsonProperty]
		private ModifyGoodTypeState state;

		[JsonProperty]
		private readonly bool isOriginalState;

		[JsonProperty]
		internal int duplicateTimes = 0;

		[JsonIgnore]
		public string GoodName => goodName;

		[JsonIgnore]
		public ModifyGoodTypeState State => state;

		[JsonIgnore]
		public bool IsOriginalState => isOriginalState;

		public ModifyGoodTypeInfo()
		{
		}

		public ModifyGoodTypeInfo(string goodName, ModifyGoodTypeState state)
		{
			this.goodName = goodName;
			this.state = state;
			isOriginalState = state.IsAlreadyApplied(GetGoodModel());
		}

		public GoodModel GetGoodModel()
		{
			return Serviceable.Settings.GetGood(goodName);
		}

		public void ApplyState()
		{
			FLog.Info("+State " + ToString(), "ApplyState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 255);
			state.ApplyState(GetGoodModel());
		}

		public void RemoveState()
		{
			if (!isOriginalState)
			{
				FLog.Info("-State " + ToString(), "RemoveState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 266);
				state.RemoveState(GetGoodModel());
			}
		}

		public ModifyGoodTypeInfo GenerateInverseInfo()
		{
			return new ModifyGoodTypeInfo(goodName, state.GenerateInverseState());
		}

		public override string ToString()
		{
			return state.ToString() + "_" + goodName;
		}

		public string ToInvString()
		{
			return state.ToInvString() + "_" + goodName;
		}
	}
	[Serializable]
	public class FluctuationInfo
	{
		[JsonProperty]
		public Vector2 range;

		[JsonProperty]
		private float totalValue = 0f;

		[JsonProperty]
		private int triggerTimes = 0;

		[JsonProperty]
		private string goodName;

		[JsonIgnore]
		private GoodModel goodModel;

		[JsonIgnore]
		public float TotalValue => totalValue;

		[JsonIgnore]
		public float TriggerTimes => triggerTimes;

		[JsonIgnore]
		public string GoodName => goodName;

		[JsonIgnore]
		public GoodModel GoodModel => goodModel;

		public FluctuationInfo(Vector2 range, string goodName)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			this.range = range;
			this.goodName = goodName;
			goodModel = MB.Settings.GetGood(goodName);
		}

		public void Restore()
		{
			goodModel = MB.Settings.GetGood(goodName);
		}

		public void TriggerEffect(int times = 1)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			float num = 0f;
			for (int i = 0; i < times; i++)
			{
				num += StableRNG.StableRandom(range);
				if (totalValue + num < -1f)
				{
					num = 0f - (totalValue + 1f);
				}
			}
			totalValue += num;
			triggerTimes += times;
			SO.EffectsService.GrantTraderSellPriceRate(goodName, num);
			FLog.Info($"Trigger Fluctuation: {goodName} | Range={range} | {times} times | Change Delta = {num}", "TriggerEffect", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 335);
		}

		public void RemoveEffect()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			FLog.Info($"Remove Fluctuation: {goodName} | Range={range} | {triggerTimes} times | Total Change = {totalValue}", "RemoveEffect", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 340);
			SO.EffectsService.GrantTraderSellPriceRate(goodName, 0f - totalValue);
			totalValue = 0f;
			triggerTimes = 0;
		}
	}
	public class ModifyGoodTypeStatesTracker
	{
		[JsonProperty]
		private Dictionary<string, ModifyGoodTypeInfo> duplicateTracker = new Dictionary<string, ModifyGoodTypeInfo>();

		[JsonProperty]
		private Dictionary<string, Dictionary<int, FluctuationInfo>> fluctuationInfo = new Dictionary<string, Dictionary<int, FluctuationInfo>>();

		public void AddFluctuationDefine(string goodName, Vector2 range)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!fluctuationInfo.TryGetValue(goodName, out var value))
			{
				Dictionary<int, FluctuationInfo> dictionary2 = (fluctuationInfo[goodName] = new Dictionary<int, FluctuationInfo>());
				value = dictionary2;
			}
			int hashCode = ((object)(Vector2)(ref range)).GetHashCode();
			if (!value.TryGetValue(hashCode, out var value2))
			{
				value2 = new FluctuationInfo(range, goodName);
				value[hashCode] = value2;
			}
		}

		public void TriggerFluctuation(string goodName, Vector2 range, int times = 1)
		{
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			if (!this.fluctuationInfo.TryGetValue(goodName, out var value))
			{
				Dictionary<int, FluctuationInfo> dictionary2 = (this.fluctuationInfo[goodName] = new Dictionary<int, FluctuationInfo>());
				value = dictionary2;
			}
			int hashCode = ((object)(Vector2)(ref range)).GetHashCode();
			if (!value.TryGetValue(hashCode, out var value2))
			{
				value2 = (value[hashCode] = new FluctuationInfo(range, goodName));
			}
			value2.TriggerEffect(times);
		}

		public void RemoveFluctuationDefine(string goodName, Vector2 range)
		{
			if (fluctuationInfo.TryGetValue(goodName, out var value))
			{
				int hashCode = ((object)(Vector2)(ref range)).GetHashCode();
				if (value.TryGetValue(hashCode, out var value2))
				{
					value2.RemoveEffect();
					value.Remove(hashCode);
				}
			}
		}

		public float GetFluctuation(string goodName, Vector2 range)
		{
			if (fluctuationInfo.TryGetValue(goodName, out var value))
			{
				int hashCode = ((object)(Vector2)(ref range)).GetHashCode();
				if (value.TryGetValue(hashCode, out var value2))
				{
					return value2.TotalValue;
				}
			}
			return 0f;
		}

		public ModifyGoodTypeInfo GetExistingInfo(ModifyGoodTypeInfo info)
		{
			ModifyGoodTypeInfo value = null;
			string key = info.ToString();
			if (!duplicateTracker.TryGetValue(key, out value))
			{
				value = info;
				duplicateTracker[key] = value;
			}
			return value;
		}

		public ModifyGoodTypeInfo GetExistingInvInfo(ModifyGoodTypeInfo info)
		{
			ModifyGoodTypeInfo value = null;
			string key = info.ToInvString();
			if (!duplicateTracker.TryGetValue(key, out value))
			{
				value = info;
				duplicateTracker[key] = value.GenerateInverseInfo();
			}
			return value;
		}

		public void AddState(ModifyGoodTypeInfo stateInfo)
		{
			ModifyGoodTypeInfo existingInfo = GetExistingInfo(stateInfo);
			ModifyGoodTypeInfo existingInvInfo = GetExistingInvInfo(stateInfo);
			if (existingInfo.duplicateTimes == existingInvInfo.duplicateTimes)
			{
				FLog.Info($"Apply state {stateInfo}", "AddState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 451);
				existingInfo.ApplyState();
			}
			existingInfo.duplicateTimes++;
		}

		public void RemoveState(ModifyGoodTypeInfo stateInfo)
		{
			ModifyGoodTypeInfo existingInfo = GetExistingInfo(stateInfo);
			ModifyGoodTypeInfo existingInvInfo = GetExistingInvInfo(stateInfo);
			if (existingInfo.duplicateTimes == existingInvInfo.duplicateTimes)
			{
				FLog.Info($"Remove state {stateInfo}", "RemoveState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 465);
				existingInfo.RemoveState();
			}
			existingInfo.duplicateTimes--;
		}

		public void RemoveAllState()
		{
			FLog.Info("remove all dynamic good states", "RemoveAllState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 474);
			foreach (ModifyGoodTypeInfo value in duplicateTracker.Values)
			{
				ModifyGoodTypeInfo modifyGoodTypeInfo = duplicateTracker[value.ToInvString()];
				if (value.duplicateTimes > modifyGoodTypeInfo.duplicateTimes)
				{
					value.RemoveState();
				}
			}
			duplicateTracker.Clear();
		}

		public void RestoreState()
		{
			try
			{
				FLog.Info($"restore dynamic good states, total states type: {duplicateTracker.Count}", "RestoreState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 490);
				foreach (ModifyGoodTypeInfo value in duplicateTracker.Values)
				{
					ModifyGoodTypeInfo modifyGoodTypeInfo = duplicateTracker[value.ToInvString()];
					if (value.duplicateTimes > modifyGoodTypeInfo.duplicateTimes)
					{
						value.ApplyState();
					}
				}
				FLog.Info("finish restore dynamic good states", "RestoreState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 499);
			}
			catch (Exception obj)
			{
				FLog.Error(obj, "RestoreState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 502);
				FLog.Error("Failed to restore :(", "RestoreState", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 503);
			}
		}
	}
	public class DynamicGoodTypeService : GameService, IDynamicGoodTypeService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		protected ModifyGoodTypeStatesTracker modifyGoodState = new ModifyGoodTypeStatesTracker();

		private MethodInfo cacheMethod;

		public ModifyGoodTypeStatesTracker GetStateTracker => modifyGoodState;

		static DynamicGoodTypeService()
		{
			CustomServiceManager.RegGameService<DynamicGoodTypeService>();
		}

		private void RecomputeCache()
		{
			cacheMethod.Invoke(Serviceable.GoodsService, null);
		}

		public override UniTask OnLoading()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			FLog.Info("Load Dynamic Good State!", "OnLoading", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 532);
			modifyGoodState.RestoreState();
			cacheMethod = AccessTools.Method(((object)Serviceable.GoodsService).GetType(), "Cache", (Type[])null, (Type[])null);
			FLog.AssertNotNull(cacheMethod, "OnLoading", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 535);
			RecomputeCache();
			return UniTask.CompletedTask;
		}

		public override void OnDestroy()
		{
			modifyGoodState.RemoveAllState();
			((Service)this).OnDestroy();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[2]
			{
				(IService)Serviceable.GoodsService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public void GoodSetEatable(string goodName, bool state)
		{
			FLog.Info($"Set Ediable {goodName} {state}", "GoodSetEatable", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 558);
			modifyGoodState.AddState(new ModifyGoodTypeInfo(goodName, ModifyGoodTypeState.GenSetEdiable(state)));
			RecomputeCache();
		}

		public void GoodAddTag(string goodName, string tagName)
		{
			FLog.Info("Add Tag " + goodName + " " + tagName, "GoodAddTag", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 569);
			modifyGoodState.AddState(new ModifyGoodTypeInfo(goodName, ModifyGoodTypeState.GenAddTag(tagName)));
			RecomputeCache();
		}

		public void GoodRemoveTag(string goodName, string tagName)
		{
			FLog.Info("Remove Tag " + goodName + " " + tagName, "GoodRemoveTag", "D:\\dev\\projects\\game_mod\\against_storm\\try_modding\\AtS-my-first-mod\\Scripts\\Framework\\Services\\DynamicGoodTypeService.cs", 580);
			modifyGoodState.AddState(new ModifyGoodTypeInfo(goodName, ModifyGoodTypeState.GenRemoveTag(tagName)));
			RecomputeCache();
		}

		public void AddGoodPriceFluctuationDefine(string goodName, Vector2 range)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			modifyGoodState.AddFluctuationDefine(goodName, range);
		}

		public void TriggerGoodPriceFluctuation(string goodName, Vector2 range, int times = 1)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			modifyGoodState.TriggerFluctuation(goodName, range, times);
		}

		public void RemoveGoodPriceFluctuationDefine(string goodName, Vector2 range)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			modifyGoodState.RemoveFluctuationDefine(goodName, range);
		}

		public float GetGoodPriceFluctuation(string goodName, Vector2 range)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return modifyGoodState.GetFluctuation(goodName, range);
		}
	}
	public class HubTierDelegate
	{
		public DynamicValueInt hubPop;

		public HubTierDelegate(HubTier hub)
		{
			hubPop = new DynamicValueInt(() => hub.minPopulation, delegate(int delta)
			{
				HubTier obj = hub;
				obj.minPopulation += delta;
			});
		}

		public void RestoreToOriginal()
		{
			hubPop.RestoreOriginalValue();
		}
	}
	internal class DynamicHearthState
	{
		[JsonIgnore]
		public List<HubTierDelegate> hubTierDelegates = new List<HubTierDelegate>();

		public float hubPopRequirePercent = 1f;

		public int hubPopRequireCount = 0;

		public void InitGame()
		{
			HubTier[] hubsTiers = MB.Settings.hubsTiers;
			foreach (HubTier hub in hubsTiers)
			{
				hubTierDelegates.Add(new HubTierDelegate(hub));
			}
		}

		public void ApplyStates()
		{
			HubTier[] hubsTiers = MB.Settings.hubsTiers;
			foreach (HubTierDelegate hubTierDelegate in hubTierDelegates)
			{
				hubTierDelegate.hubPop.SetNewValue((int)((float)hubTierDelegate.hubPop.BaseValue * hubPopRequirePercent + (float)hubPopRequireCount));
			}
			IEnumerable<Hearth> enumerable = LinqExtensions.FilterCast<Hearth>((IEnumerable)Serviceable.BuildingsService.Buildings.Values);
			foreach (Hearth item in enumerable)
			{
				((Building)item).SlowUpdate();
			}
		}

		public void DestoryRestore()
		{
			foreach (HubTierDelegate hubTierDelegate in hubTierDelegates)
			{
				hubTierDelegate.RestoreToOriginal();
			}
		}
	}
	public class DynamicHearthService : GameService, IDynamicHearthService, IService
	{
		[ModSerializedField(SaveLoadType.Unknown, "")]
		private DynamicHearthState state = new DynamicHearthState();

		static DynamicHearthService()
		{
			CustomServiceManager.RegGameService<DynamicHearthService>();
		}

		public override IService[] GetDependencies()
		{
			return (IService[])(object)new IService[2]
			{
				(IService)Serviceable.HearthService,
				CustomServiceManager.GetAsIService<IExtraStateService>()
			};
		}

		public override void OnDestroy()
		{
			state.DestoryRestore();
			((Service)this).OnDestroy();
		}

		public override UniTask OnLoading()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: 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)
			state.InitGame();
			state.ApplyStates();
			return UniTask.CompletedTask;
		}

		public void AddHearthRequirePopPercent(float v)
		{
			state.hubPopRequirePercent += v;
			state.ApplyStates();
		}

		publi