Decompiled source of SODLifeAndLiving v3.0.0

SOD.LifeAndLiving.dll

Decompiled 2 months ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem.Collections.Generic;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.BepInEx.Configuration;
using SOD.Common.Extensions;
using SOD.Common.Helpers;
using SOD.Common.Helpers.DialogObjects;
using SOD.Common.Helpers.ObjectiveObjects;
using SOD.Common.Helpers.SyncDiskObjects;
using SOD.LifeAndLiving.Bindings.EconomicBindings;
using SOD.LifeAndLiving.Bindings.ImRequirementBindings;
using SOD.LifeAndLiving.Bindings.RelationBindings;
using SOD.LifeAndLiving.Bindings.SyncDiskBindings;
using SOD.LifeAndLiving.Content.SocialRelation;
using SOD.LifeAndLiving.Content.SocialRelation.Dialogs;
using SOD.LifeAndLiving.Content.SyncDisks;
using SOD.LifeAndLiving.Patches.EconomyRebalancePatches;
using SOD.RelationsPlus;
using SOD.RelationsPlus.Objects;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("SOD.LifeAndLiving")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+105368c6fd0dd8757a25de203851c1af249c7651")]
[assembly: AssemblyProduct("SOD.LifeAndLiving")]
[assembly: AssemblyTitle("SOD.LifeAndLiving")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace SOD.LifeAndLiving
{
	public interface IPluginBindings : ISideJobBindings, IMurderCaseBindings, ISpawnRateBindings, IHousingBindings, SOD.LifeAndLiving.Bindings.EconomicBindings.IDialogBindings, IMoneyBindings, IShopsBindings, IItemPriceBindings, SOD.LifeAndLiving.Bindings.RelationBindings.IDialogBindings, ImRequirementBindings, ISyncDiskBindings
	{
	}
	[BepInPlugin("Venomaus.SOD.LifeAndLiving", "LifeAndLiving", "3.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : PluginController<Plugin, IPluginBindings>
	{
		public const string PLUGIN_GUID = "Venomaus.SOD.LifeAndLiving";

		public const string PLUGIN_NAME = "LifeAndLiving";

		public const string PLUGIN_VERSION = "3.0.0";

		public readonly Random Random = new Random();

		public override void Load()
		{
			Lib.SaveGame.OnBeforeLoad += SaveGame_OnBeforeLoad;
			Lib.SaveGame.OnAfterLoad += SaveGame_OnAfterLoad;
			Lib.SaveGame.OnBeforeSave += SaveGame_OnBeforeSave;
			Lib.SaveGame.OnBeforeDelete += SaveGame_OnBeforeDelete;
			CivilianDialogAdditions.Initialize();
			Echolocation.Initialize();
			base.Harmony.PatchAll(Assembly.GetExecutingAssembly());
			PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Plugin is patched.");
		}

		public override void OnConfigureBindings()
		{
			base.OnConfigureBindings();
			base.UpdateConfigFileLayout();
		}

		private void SaveGame_OnBeforeDelete(object sender, SaveGameArgs e)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
			NewGameLocationPatches.NewGameLocation_GetPrice.Delete(uniqueString);
			PlayerInterests.Instance.Delete(uniqueString);
		}

		private void SaveGame_OnBeforeSave(object sender, SaveGameArgs e)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
			NewGameLocationPatches.NewGameLocation_GetPrice.Save(uniqueString);
			PlayerInterests.Instance.Save(uniqueString);
		}

		private void SaveGame_OnBeforeLoad(object sender, SaveGameArgs e)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(e.FilePath);
			NewGameLocationPatches.NewGameLocation_GetPrice.Load(uniqueString);
			PlayerInterests.Instance.Load(uniqueString);
		}

		private void SaveGame_OnAfterLoad(object sender, SaveGameArgs e)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			Random random = null;
			List<KeyValuePair<InteractablePreset, int>> list = new List<KeyValuePair<InteractablePreset, int>>();
			Enumerator<Company> enumerator = CityData.Instance.companyDirectory.GetEnumerator();
			while (enumerator.MoveNext())
			{
				Company current = enumerator.Current;
				Enumerator<InteractablePreset, int> enumerator2 = current.prices.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					KeyValuePair<InteractablePreset, int> current2 = enumerator2.Current;
					list.Add(new KeyValuePair<InteractablePreset, int>(current2.Key, current2.Value));
				}
				foreach (KeyValuePair<InteractablePreset, int> item in list)
				{
					Vector2 value = item.Key.value;
					if ((float)item.Value < value.x || (float)item.Value > value.y)
					{
						if (random == null)
						{
							random = new Random((int)Lib.SaveGame.GetUniqueNumber(CityData.Instance.seed));
						}
						current.prices[item.Key] = random.Next((int)value.x, (int)value.y + 1);
					}
				}
				list.Clear();
			}
		}
	}
}
namespace SOD.LifeAndLiving.Content.SyncDisks
{
	internal static class Echolocation
	{
		private static int _effectId;

		internal static Color Color { get; private set; }

		internal static void Initialize()
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.IncludeEcholocationSyncDisk)
			{
				try
				{
					Color color = ColorTranslator.FromHtml(((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.EcholocationTextColor);
					Color = new Color((float)(int)color.R, (float)(int)color.G, (float)(int)color.B, (float)(int)color.A);
				}
				catch
				{
					PluginController<Plugin, IPluginBindings>.Log.LogError((object)"Unable to read config value for \"NpcChatterTextColor\", using fallback cyan color.");
					Color = Color.cyan;
				}
				Lib.SyncDisks.OnAfterSyncDiskInstalled += OnSyncDiskInstall;
				Lib.SyncDisks.OnAfterSyncDiskUninstalled += OnSyncDiskUninstall;
				Lib.SyncDisks.Builder("Echolocation", "Venomaus.SOD.LifeAndLiving", true).SetPrice(((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.EcholocationDiskPrice).SetManufacturer((Manufacturer)5)
					.SetRarity((Rarity)3)
					.AddEffect("Echolocation", "Highlights civilian chatter for your selected case if their voice is identified and their profile is on your selected case board.", ref _effectId, (string)null)
					.AddSaleLocation((SyncDiskSaleLocation[])(object)new SyncDiskSaleLocation[1] { (SyncDiskSaleLocation)23 })
					.CreateAndRegister();
			}
		}

		private static void OnSyncDiskUninstall(object sender, SyncDiskArgs e)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (e.Effect.HasValue && e.Effect.Value.Id == _effectId)
			{
				SpeechController_Update.EffectEnabled = false;
				SpeechController_Update.ClearActors();
			}
		}

		private static void OnSyncDiskInstall(object sender, SyncDiskArgs e)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (e.Effect.HasValue && e.Effect.Value.Id == _effectId)
			{
				SpeechController_Update.EffectEnabled = true;
				SpeechController_Update.ClearActors();
				SpeechController_Update.SetActorsOfCurrentCase();
			}
		}
	}
	[HarmonyPatch(typeof(CasePanelController), "UpdatePinned")]
	internal static class CasePanelController_UpdatePinned
	{
		[HarmonyPostfix]
		internal static void Postfix(CasePanelController __instance)
		{
			if (!MainMenuController.Instance.mainMenuActive && __instance.activeCase != null)
			{
				SpeechController_Update.SetActorsOfCurrentCase();
			}
		}
	}
	[HarmonyPatch(typeof(CasePanelController), "SetActiveCase")]
	internal static class CasePanelController_SetActiveCase
	{
		private static Case _currentCase;

		[HarmonyPrefix]
		internal static void Prefix(CasePanelController __instance)
		{
			_currentCase = __instance.activeCase;
		}

		[HarmonyPostfix]
		internal static void Postfix(CasePanelController __instance)
		{
			if ((_currentCase != null || __instance.activeCase != null) && ((_currentCase == null && __instance.activeCase != null) || (_currentCase != null && __instance.activeCase == null) || _currentCase.id != __instance.activeCase.id))
			{
				SpeechController_Update.ClearActors();
				SpeechController_Update.SetActorsOfCurrentCase();
			}
		}
	}
	[HarmonyPatch(typeof(SpeechController), "Update")]
	internal static class SpeechController_Update
	{
		private static readonly HashSet<int> _actorsOnCurrentCaseboard = new HashSet<int>();

		private static bool _speechActive = false;

		private static Color _originalColor;

		internal static bool IsDirty = false;

		internal static bool EffectEnabled = false;

		private static readonly HashSet<int> _empty = new HashSet<int>();

		[HarmonyPostfix]
		internal static void Postfix(SpeechController __instance)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			bool flag = (Object)(object)__instance.activeSpeechBubble != (Object)null;
			if ((_speechActive == flag && !IsDirty) || (!IsDirty && (!EffectEnabled || _actorsOnCurrentCaseboard.Count == 0)))
			{
				return;
			}
			_speechActive = flag;
			if (!((Object)(object)__instance.activeSpeechBubble == (Object)null))
			{
				if (flag && !IsDirty)
				{
					_originalColor = ((Graphic)__instance.activeSpeechBubble.text).color;
				}
				((Graphic)__instance.activeSpeechBubble.text).color = GetColorForActor(__instance.actor);
				IsDirty = false;
			}
		}

		internal static void ClearActors()
		{
			_actorsOnCurrentCaseboard.Clear();
			IsDirty = true;
		}

		internal static void SetActorsOfCurrentCase()
		{
			if (CasePanelController.Instance.activeCase == null)
			{
				AdjustActors(_empty);
				return;
			}
			HashSet<int> hashSet = null;
			Enumerator<CaseElement> enumerator = CasePanelController.Instance.activeCase.caseElements.GetEnumerator();
			Evidence val = default(Evidence);
			while (enumerator.MoveNext())
			{
				CaseElement current = enumerator.Current;
				if (!Toolbox.Instance.TryGetEvidence(current.id, ref val))
				{
					continue;
				}
				EvidenceCitizen val2 = ((Il2CppObjectBase)val).TryCast<EvidenceCitizen>();
				if (val2 != null && val.GetTiedKeys(current.dk).Contains((DataKey)4))
				{
					if (hashSet == null)
					{
						hashSet = new HashSet<int>();
					}
					hashSet.Add(val2.witnessController.humanID);
				}
			}
			AdjustActors(hashSet ?? _empty);
		}

		private static Color GetColorForActor(Actor actor)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (!EffectEnabled || !((Object)(object)actor.ai != (Object)null) || !((Object)(object)actor.ai.human != (Object)null) || !_actorsOnCurrentCaseboard.Contains(actor.ai.human.humanID))
			{
				return _originalColor;
			}
			return Echolocation.Color;
		}

		private static void AdjustActors(HashSet<int> actorIds)
		{
			if (_actorsOnCurrentCaseboard.Count == 0 && actorIds.Count == 0)
			{
				return;
			}
			HashSet<int> hashSet = _actorsOnCurrentCaseboard.ToHashSet();
			_actorsOnCurrentCaseboard.Clear();
			foreach (int actorId in actorIds)
			{
				_actorsOnCurrentCaseboard.Add(actorId);
			}
			IsDirty = hashSet.Count != _actorsOnCurrentCaseboard.Count || !hashSet.All((int a) => _actorsOnCurrentCaseboard.Contains(a));
		}
	}
}
namespace SOD.LifeAndLiving.Content.SocialRelation
{
	internal static class CivilianDialogAdditions
	{
		public static void Initialize()
		{
			TheUsualDialog.Register();
		}
	}
	public class PlayerInterests
	{
		private static PlayerInterests _instance;

		public static PlayerInterests Instance => _instance ?? (_instance = new PlayerInterests());

		public bool ContainsContent
		{
			get
			{
				if (ItemsPurchased.Count <= 0)
				{
					return PurchasedItemsFrom.Count > 0;
				}
				return true;
			}
		}

		public Dictionary<int, Dictionary<string, int>> ItemsPurchased { get; set; } = new Dictionary<int, Dictionary<string, int>>();


		public Dictionary<int, Dictionary<string, int>> PurchasedItemsFrom { get; set; } = new Dictionary<int, Dictionary<string, int>>();


		public void RecordPurchasedItem(int companyId, string itemName, Actor from = null)
		{
			if (!ItemsPurchased.TryGetValue(companyId, out var value))
			{
				value = (ItemsPurchased[companyId] = new Dictionary<string, int>());
			}
			if (!value.ContainsKey(itemName))
			{
				value.Add(itemName, 1);
			}
			else
			{
				value[itemName]++;
			}
			Human val = (Human)(object)((from is Human) ? from : null);
			if ((Object)(object)val != (Object)null)
			{
				if (!PurchasedItemsFrom.TryGetValue(val.humanID, out var value2))
				{
					value2 = (PurchasedItemsFrom[val.humanID] = new Dictionary<string, int>());
				}
				string uniqueString = Lib.SaveGame.GetUniqueString(companyId + "_" + itemName);
				if (!value2.ContainsKey(uniqueString))
				{
					value2.Add(uniqueString, 1);
				}
				else
				{
					value2[uniqueString]++;
				}
			}
		}

		internal void Load(string hash)
		{
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "PlayerInterests_" + hash + ".json");
			if (File.Exists(savestoreDirectoryPath))
			{
				PlayerInterests playerInterests = JsonSerializer.Deserialize<PlayerInterests>(File.ReadAllText(savestoreDirectoryPath));
				ItemsPurchased = playerInterests.ItemsPurchased;
				PurchasedItemsFrom = playerInterests.PurchasedItemsFrom;
			}
		}

		internal void Save(string hash)
		{
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "PlayerInterests_" + hash + ".json");
			if (!ContainsContent)
			{
				if (File.Exists(savestoreDirectoryPath))
				{
					File.Delete(savestoreDirectoryPath);
				}
			}
			else
			{
				string contents = JsonSerializer.Serialize(this, new JsonSerializerOptions
				{
					WriteIndented = false
				});
				File.WriteAllText(savestoreDirectoryPath, contents);
			}
		}

		internal void Delete(string hash)
		{
			string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "PlayerInterests_" + hash + ".json");
			if (File.Exists(savestoreDirectoryPath))
			{
				File.Delete(savestoreDirectoryPath);
			}
		}
	}
}
namespace SOD.LifeAndLiving.Content.SocialRelation.Dialogs
{
	internal class TheUsualDialog : IDialogLogic
	{
		private class Item
		{
			public string Name { get; }

			public InteractablePreset Preset { get; }

			public int Price { get; set; }

			public bool Discount { get; set; }

			public Item(string itemName, InteractablePreset preset, int price)
			{
				Name = itemName;
				Preset = preset;
				Price = price;
			}
		}

		private static Guid _positiveResponse;

		private static Guid _positiveDiscountResponse;

		private static Guid _positiveFreeResponse;

		private static Item _item;

		private readonly Dictionary<int, (int Hash, bool Received)> _discountCache = new Dictionary<int, (int, bool)>();

		internal static void Register()
		{
			Func<string> func = () => ((int)((Human)Player.Instance).gender != 0) ? (((int)((Human)Player.Instance).gender != 1) ? ("Good choice, one " + _item?.Name + " coming right up!") : ("Good choice ma'am, one " + _item?.Name + " coming right up!")) : ("Good choice sir, one " + _item?.Name + " coming right up!");
			Lib.Dialogs.Builder((string)null).SetText("For me, the usual as always.").AddCustomResponse(func, ref _positiveResponse)
				.AddCustomResponse((Func<string>)(() => $"You're lucky, this {_item?.Name ?? "item"} has a {((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualDiscountValue}% discount!"), ref _positiveDiscountResponse)
				.AddCustomResponse((Func<string>)(() => "Coming right up, this " + (_item?.Name ?? "item") + " is on the house!"), ref _positiveFreeResponse)
				.AddResponse((Func<string>)(() => "Looks like you can't afford " + (_item?.Name ?? "it") + " today."), false, true)
				.ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset a)
				{
					a.useSuccessTest = true;
					a.ranking = int.MaxValue;
				})
				.SetDialogLogic((IDialogLogic)(object)new TheUsualDialog())
				.CreateAndRegister();
		}

		public bool IsDialogShown(DialogPreset preset, Citizen saysTo, SideJob jobRef)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Invalid comparison between Unknown and I4
			CitizenRelation val = default(CitizenRelation);
			if (!RelationManager.Instance.TryGetValue(((Human)saysTo).humanID, ref val) || (int)val.GetKnowRelation() < 2)
			{
				return false;
			}
			if (!((Object)(object)saysTo == (Object)null) && ((Actor)saysTo).isAtWork)
			{
				Occupation job = ((Human)saysTo).job;
				if (((job != null) ? job.employer : null) != null && FirstPersonItemController.Instance.IsSlotAvailable())
				{
					if (!PlayerInterests.Instance.PurchasedItemsFrom.TryGetValue(((Human)saysTo).humanID, out var value))
					{
						return false;
					}
					return value.Any((KeyValuePair<string, int> a) => a.Value >= 4);
				}
			}
			return false;
		}

		public void OnDialogExecute(DialogController instance, Citizen saysTo, Interactable saysToInteractable, NewNode where, Actor saidBy, bool success, NewRoom roomRef, SideJob jobRef)
		{
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			if (success && _item != null)
			{
				_item.Preset.SpawnIntoInventory();
				if (PluginController<Plugin, IPluginBindings>.Instance.Random.Next(0, 100) < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PositiveInteractionChance)
				{
					CitizenRelation obj = RelationManager.Instance[((Human)saysTo).humanID];
					obj.Like += 0.05f;
				}
				CitizenRelation obj2 = RelationManager.Instance[((Human)saysTo).humanID];
				obj2.Know += 0.05f;
				if (_item.Price > 0)
				{
					GameplayController.Instance.AddMoney(-_item.Price, false, "Purchase");
					((Actor)saysTo).speechController.Speak("dds.blocks", _item.Discount ? _positiveDiscountResponse.ToString() : _positiveResponse.ToString(), false, false, false, 0f, false, default(Color), (Human)null, true, false, (SideJob)null, (DialogPreset)null, (AISpeechPreset)null, (Interactable)null);
				}
				else if (_item.Price == 0)
				{
					((Actor)saysTo).speechController.Speak("dds.blocks", _positiveFreeResponse.ToString(), false, false, false, 0f, false, default(Color), (Human)null, true, false, (SideJob)null, (DialogPreset)null, (AISpeechPreset)null, (Interactable)null);
				}
				if ((Object)(object)((Actor)Player.Instance).currentGameLocation != (Object)null && (Object)(object)((Actor)Player.Instance).currentGameLocation.thisAsAddress != (Object)null && ((Actor)Player.Instance).currentGameLocation.thisAsAddress.company != null && ((Actor)Player.Instance).currentGameLocation.thisAsAddress.company.preset.enableLoiteringBehaviour)
				{
					((Actor)Player.Instance).currentGameLocation.LoiteringPurchase();
				}
			}
			_item = null;
		}

		public ForceSuccess ShouldDialogSucceedOverride(DialogController instance, DialogOption dialog, Citizen saysTo, NewNode where, Actor saidBy)
		{
			if (Object.op_Implicit((Object)(object)saysTo))
			{
				_item = CollectMostPurchasedItem(PlayerInterests.Instance.PurchasedItemsFrom[((Human)saysTo).humanID], ((Human)saysTo).job.employer);
				if (_item == null)
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Could not find item, this should not have happened.");
					return (ForceSuccess)2;
				}
				int deterministicHashCode = GetDeterministicHashCode((Human)(object)saysTo);
				if (!_discountCache.TryGetValue(((Human)saysTo).humanID, out (int, bool) value))
				{
					value = (_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, false));
				}
				if (value.Item1 != deterministicHashCode)
				{
					value = (_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, false));
				}
				if (!value.Item2)
				{
					int num = new Random(deterministicHashCode).Next(0, 100);
					if (num < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualFreeChance)
					{
						_item.Price = 0;
						_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, true);
					}
					else if (num < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualDiscountChance)
					{
						_item.Price -= (int)Math.Round((float)(_item.Price / 100) * (float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.TheUsualDiscountValue);
						_item.Discount = true;
						_discountCache[((Human)saysTo).humanID] = (deterministicHashCode, true);
					}
				}
				if (_item.Price < 0)
				{
					_item.Price = 0;
				}
				if (GameplayController.Instance.money >= _item.Price)
				{
					return (ForceSuccess)0;
				}
				return (ForceSuccess)2;
			}
			return (ForceSuccess)0;
		}

		private static int GetDeterministicHashCode(Human citizen)
		{
			//IL_0005: 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)
			TimeData currentDateTime = Lib.Time.CurrentDateTime;
			return TypeExtensions.GetFnvHashCode($"{((TimeData)(ref currentDateTime)).Year}_{((TimeData)(ref currentDateTime)).Month}_{((TimeData)(ref currentDateTime)).Day}_{((TimeData)(ref currentDateTime)).Hour}_{citizen.humanID}");
		}

		private static Item CollectMostPurchasedItem(Dictionary<string, int> items, Company company)
		{
			string key = (from a in items
				where a.Value >= 5
				orderby a.Value descending
				select a).First().Key;
			string text = null;
			foreach (KeyValuePair<int, Dictionary<string, int>> item in PlayerInterests.Instance.ItemsPurchased)
			{
				int key2 = item.Key;
				foreach (KeyValuePair<string, int> item2 in item.Value)
				{
					string uniqueString = Lib.SaveGame.GetUniqueString(key2 + "_" + item2.Key);
					if (key == uniqueString)
					{
						text = item2.Key;
						break;
					}
				}
				if (text != null)
				{
					break;
				}
			}
			return GetItem(text, company);
		}

		private static Item GetItem(string itemName, Company company)
		{
			if (itemName == null)
			{
				return null;
			}
			Enumerator<InteractablePreset, int> enumerator = company.prices.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<InteractablePreset, int> current = enumerator.Current;
				if (((SoCustomComparison)current.key).presetName == itemName)
				{
					return new Item(itemName, current.Key, current.Value);
				}
			}
			return null;
		}
	}
}
namespace SOD.LifeAndLiving.Content.EconomyRebalance
{
	internal class LostAndFoundPatches
	{
		[HarmonyPatch(typeof(NewBuilding), "TriggerNewLostAndFound")]
		internal class NewBuilding_TriggerNewLostAndFound
		{
			private static HashSet<int> _lostAndFound;

			[HarmonyPrefix]
			internal static void Prefix(NewBuilding __instance)
			{
				_lostAndFound = (from a in EnumerableExtensions.AsEnumerable<LostAndFound>(__instance.lostAndFound)
					select HashCode.Combine(a.ownerID, a.buildingID, a.spawnedItem, a.rewardMoney)).ToHashSet();
			}

			[HarmonyPostfix]
			internal static void Postfix(NewBuilding __instance)
			{
				int payoutReductionLostItems = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionLostItems;
				int num = 0;
				Enumerator<LostAndFound> enumerator = __instance.lostAndFound.GetEnumerator();
				while (enumerator.MoveNext())
				{
					LostAndFound current = enumerator.Current;
					int item = HashCode.Combine(current.ownerID, current.buildingID, current.spawnedItem, current.rewardMoney);
					if (!_lostAndFound.Contains(item))
					{
						current.rewardMoney -= (int)((float)(current.rewardMoney / 100) * (float)payoutReductionLostItems);
						_lostAndFound.Add(item);
						num++;
					}
				}
				_lostAndFound = null;
			}
		}

		[HarmonyPatch(typeof(InteractableCreator), "CreateFurnitureSpawnedInteractableThreadSafe")]
		internal class InteractableCreator_CreateFurnitureSpawnedInteractableThreadSafe
		{
			[HarmonyPrefix]
			internal static void Prefix(InteractablePreset preset, List<Passed> passedVars)
			{
				if ((SoCustomComparison)(object)preset != (SoCustomComparison)null && ((SoCustomComparison)preset).Equals((SoCustomComparison)(object)CityControls.Instance.lostAndFoundNote))
				{
					Passed val = EnumerableExtensions.AsEnumerable<Passed>(passedVars).FirstOrDefault((Func<Passed, bool>)((Passed a) => (int)a.varType == 25));
					if (val != null)
					{
						int payoutReductionLostItems = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionLostItems;
						val.value -= (float)(int)(val.value / 100f * (float)payoutReductionLostItems);
					}
				}
			}
		}
	}
}
namespace SOD.LifeAndLiving.Patches.SocialRelationPatches
{
	internal class PurchaseItemPatches
	{
		[HarmonyPatch(typeof(ShopSelectButtonController), "PurchaseExecute")]
		internal static class ShopSelectButtonController_PurchaseExecute
		{
			[HarmonyPrefix]
			internal static void Prefix(out int __state)
			{
				__state = EnumerableExtensions.Select<InventorySlot, InventorySlot>(FirstPersonItemController.Instance.slots, (Func<InventorySlot, InventorySlot>)((InventorySlot a) => a)).Count((InventorySlot a) => (int)a.isStatic == 0 && a.GetInteractable() == null);
			}

			[HarmonyPostfix]
			internal static void Postfix(ShopSelectButtonController __instance, int __state)
			{
				if (EnumerableExtensions.Select<InventorySlot, InventorySlot>(FirstPersonItemController.Instance.slots, (Func<InventorySlot, InventorySlot>)((InventorySlot a) => a)).Count((InventorySlot a) => (int)a.isStatic == 0 && a.GetInteractable() == null) == __state)
				{
					_purchasedFrom = null;
					return;
				}
				NewGameLocation currentGameLocation = ((Actor)Player.Instance).currentGameLocation;
				object obj;
				if (currentGameLocation == null)
				{
					obj = null;
				}
				else
				{
					NewAddress thisAsAddress = currentGameLocation.thisAsAddress;
					obj = ((thisAsAddress != null) ? thisAsAddress.company : null);
				}
				Company val = (Company)obj;
				if (val != null)
				{
					PlayerInterests.Instance.RecordPurchasedItem(val.companyID, ((SoCustomComparison)__instance.preset).presetName, _purchasedFrom);
				}
				if ((Object)(object)_purchasedFrom != (Object)null && _resetFieldAction == null)
				{
					_resetFieldAction = delegate
					{
						_purchasedFrom = null;
						__instance.thisWindow.OnWindowClosed -= WindowClosed.op_Implicit(_resetFieldAction);
						_resetFieldAction = null;
					};
					__instance.thisWindow.OnWindowClosed += WindowClosed.op_Implicit(_resetFieldAction);
				}
			}
		}

		[HarmonyPatch(typeof(DialogController), "BuySomething")]
		internal static class DialogController_BuySomething
		{
			[HarmonyPrefix]
			internal static void Prefix(Citizen saysTo, bool success)
			{
				if (!success)
				{
					_purchasedFrom = null;
				}
				else
				{
					_purchasedFrom = (Actor)(object)saysTo;
				}
			}
		}

		private static Actor _purchasedFrom;

		private static Action _resetFieldAction;
	}
}
namespace SOD.LifeAndLiving.Patches.ImmersiveRequirementPatches
{
	internal class AirVentScrewdriverPatches
	{
		[HarmonyPatch(typeof(Interactable), "OnInteraction", new Type[]
		{
			typeof(InteractionAction),
			typeof(Actor),
			typeof(bool),
			typeof(float)
		})]
		internal class Interactable_OnInteraction
		{
			private static void Prefix(Interactable __instance, InteractionAction action, Actor who)
			{
				if (!((SoCustomComparison)(object)__instance.preset == (SoCustomComparison)null) && !string.IsNullOrWhiteSpace(((SoCustomComparison)__instance.preset).presetName) && ((SoCustomComparison)__instance.preset).presetName.Equals("AirVent") && action != null && !((Object)(object)who == (Object)null) && who.isPlayer && ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.RequireScrewdriverForVents && (action.interactionName.Equals("Open") || action.interactionName.Equals("Close")))
				{
					_attemptOpenOrCloseAirVent = true;
				}
			}
		}

		[HarmonyPatch(typeof(Interactable), "SetSwitchState")]
		internal class Interactable_SetSwitchState
		{
			private static bool Prefix(Actor interactor)
			{
				if ((Object)(object)interactor == (Object)null || !interactor.isPlayer || !_attemptOpenOrCloseAirVent)
				{
					return true;
				}
				_attemptOpenOrCloseAirVent = false;
				Interactable[] array = default(Interactable[]);
				if (!Lib.Gameplay.HasInteractableInInventory("Screwdriver", ref array))
				{
					Lib.GameMessage.ShowPlayerSpeech("I could open this with a screwdriver, maybe I should look for one.", 5f, true);
					return false;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(ChapterIntro), "InvestigateWriterAddress")]
		internal class ChapterIntro_InvestigateWriterAddress
		{
			private static void Prefix(ChapterIntro __instance)
			{
				if (!((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.RequireScrewdriverForVents)
				{
					return;
				}
				Interactable[] array = default(Interactable[]);
				if (Lib.Gameplay.HasInteractableInInventory("Screwdriver", ref array))
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Already have a screwdriver in the inventory, no need to add objective or spawn a new one.");
					return;
				}
				AirVent[] array2 = default(AirVent[]);
				if (!Lib.Gameplay.AirVentExistsInHouse(__instance.kidnapper.home, ref array2))
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"No airvents found, no need to spawn a screwdriver.");
					return;
				}
				Interactable[] source = default(Interactable[]);
				if (!Lib.Gameplay.InteractableExistsInHouse("Screwdriver", __instance.kidnapper.home, ref source))
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"No screwdrivers found, spawning atleast one.");
					FurnitureLocation val = default(FurnitureLocation);
					Lib.Gameplay.AddInteractableToHouse("Screwdriver", __instance.kidnapper.home, ref val, ref ScrewDriverForVent, (Human)null, (Human)null, (Human)null, (OwnedPlacementRule)0);
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)("Screwdriver was spawned in: " + ScrewDriverForVent.node.room.name));
				}
				else
				{
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"A screwdriver is already present, no need to spawn an extra one.");
					ScrewDriverForVent = source.First();
				}
				Lib.CaseObjectives.OnObjectiveCompleted += CaseObjectives_OnObjectiveCompleted;
			}

			private static void CaseObjectives_OnObjectiveCompleted(object sender, ObjectiveArgs e)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				if (ScrewDriverForVent != null && e.EntryRef.StartsWith("Look around for vents for a potential quick exit"))
				{
					Lib.CaseObjectives.Builder(e.Case).SetText("Look around for a screwdriver to open the air vent").SetIcon((Icon)0)
						.SetPointer(ScrewDriverForVent.GetWorldPosition(true))
						.SetCompletionTrigger(PredefinedTrigger.GoToNode(ScrewDriverForVent.node))
						.Register();
					ScrewDriverForVent = null;
					Lib.CaseObjectives.OnObjectiveCompleted -= CaseObjectives_OnObjectiveCompleted;
				}
			}
		}

		private static bool _attemptOpenOrCloseAirVent;

		private static Interactable ScrewDriverForVent;
	}
}
namespace SOD.LifeAndLiving.Patches.EconomyRebalancePatches
{
	internal class ActionControllerPatches
	{
		[HarmonyPatch(typeof(ActionController), "TakeLockpickKit")]
		internal class ActionController_TakeLockpickKit
		{
			private static int _previousLockPicks;

			[HarmonyPrefix]
			internal static void Prefix()
			{
				_previousLockPicks = GameplayController.Instance.lockPicks;
			}

			[HarmonyPostfix]
			internal static void Postfix()
			{
				int num = GameplayController.Instance.lockPicks - _previousLockPicks;
				GameplayController.Instance.AddLockpicks(-num + ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LockPickKitAmount, false);
			}
		}
	}
	internal class BuyInterfacePatches
	{
		[HarmonyPatch(typeof(BuyInterfaceController), "UpdateElements")]
		internal class BuyInterfaceController_UpdateElements
		{
			[HarmonyPostfix]
			internal static void Postfix(BuyInterfaceController __instance)
			{
				//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Expected O, but got Unknown
				List<ShopSelectButtonController> spawned = __instance.spawned;
				bool flag = __instance.company != null && __instance.company.preset.enableSellingOfIllegalItems;
				int maxSellPriceAllItemsGeneral = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxSellPriceAllItemsGeneral;
				int maxSellPriceAllItemsBlackMarket = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxSellPriceAllItemsBlackMarket;
				bool flag2 = false;
				int num = 0;
				Enumerator<ShopSelectButtonController> enumerator = spawned.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ShopSelectButtonController current = enumerator.Current;
					if (current.sellInteractable != null && current.sellMode && !((SoCustomComparison)current.sellInteractable.preset).presetName.Equals("Diamond"))
					{
						int price = current.price;
						current.price = Math.Min(current.price, flag ? maxSellPriceAllItemsBlackMarket : maxSellPriceAllItemsGeneral);
						if (price != current.price)
						{
							((ButtonController)current).UpdateButtonText();
							flag2 = true;
							num++;
						}
					}
				}
				if (flag2)
				{
					__instance.UpdatePurchaseAbility();
					ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
					bool flag3 = default(bool);
					BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(49, 1, ref flag3);
					if (flag3)
					{
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Capped sale price of \"");
						((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
						((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" items at store interface.");
					}
					log.LogInfo(val);
				}
			}
		}
	}
	internal class CityControlsPatches
	{
		[HarmonyPatch(typeof(CityControls), "Awake")]
		internal class CityControls_Awake
		{
			[HarmonyPrefix]
			internal static void Prefix(CityControls __instance)
			{
				__instance.hotelCostLower = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.CostLowerSuiteHotel;
				__instance.hotelCostUpper = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.CostHigherSuiteHotel;
				PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Updated hotel suite prices.");
			}
		}
	}
	internal class GameplayControlsPatches
	{
		[HarmonyPatch(typeof(GameplayControls), "Awake")]
		internal class GameplayControls_Awake
		{
			private static bool _appliedOnce;

			[HarmonyPostfix]
			internal static void Postfix(GameplayControls __instance)
			{
				if (!_appliedOnce)
				{
					_appliedOnce = true;
					ReduceMurderPayouts(__instance);
				}
			}

			private static void ReduceMurderPayouts(GameplayControls __instance)
			{
				//IL_003e: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_009b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_0155: Unknown result type (might be due to invalid IL or missing references)
				//IL_015c: Expected O, but got Unknown
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_010c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				int payoutReductionMurders = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionMurders;
				int minimumMurderResolveQuestionPayout = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinimumMurderResolveQuestionPayout;
				int num = 0;
				Enumerator<ResolveQuestion> enumerator = __instance.murderResolveQuestions.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ResolveQuestion current = enumerator.Current;
					int num2 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.rewardRange.x - (int)(current.rewardRange.x / 100f * (float)payoutReductionMurders));
					int num3 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.rewardRange.y - (int)(current.rewardRange.y / 100f * (float)payoutReductionMurders));
					current.rewardRange = new Vector2((float)num2, (float)num3);
					if (current.penaltyRange.x > 0f && current.penaltyRange.y > 0f)
					{
						num2 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.penaltyRange.x + (int)(current.penaltyRange.x / 100f * (float)(payoutReductionMurders / 4)));
						num3 = Math.Max(minimumMurderResolveQuestionPayout, (int)current.penaltyRange.y + (int)(current.penaltyRange.y / 100f * (float)(payoutReductionMurders / 4)));
						current.penaltyRange = new Vector2((float)num2, (float)num3);
					}
					num++;
				}
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(43, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reduced \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" murder resolve question payouts.");
				}
				log.LogInfo(val);
			}
		}
	}
	internal class InteractablePatches
	{
		[HarmonyPatch(typeof(Interactable), "UpdateName")]
		internal class Interactable_SetValue
		{
			[HarmonyPrefix]
			internal static void Prefix(Interactable __instance)
			{
				if (!((SoCustomComparison)(object)__instance.preset == (SoCustomComparison)null))
				{
					Dictionary<string, int> dictionary = new Dictionary<string, int>
					{
						{
							"M1",
							((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM1Crows
						},
						{
							"M2",
							((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM2Crows
						},
						{
							"M3",
							((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM3Crows
						},
						{
							"M4",
							((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxM4Crows
						}
					};
					if (__instance.preset.isMoney && dictionary.TryGetValue(((SoCustomComparison)__instance.preset).presetName, out var value) && __instance.val > (float)value)
					{
						__instance.val = value;
					}
				}
			}
		}
	}
	internal class NewGameLocationPatches
	{
		[HarmonyPatch(typeof(NewGameLocation), "GetPrice")]
		internal class NewGameLocation_GetPrice
		{
			private static readonly Random _valueRandom = new Random();

			internal static readonly Dictionary<string, int> ApartementPriceCache = new Dictionary<string, int>();

			[HarmonyPostfix]
			internal static void Postfix(NewGameLocation __instance, ref int __result)
			{
				string key = __instance.building.buildingID + "_" + __instance.residenceNumber;
				if (ApartementPriceCache.TryGetValue(key, out var value))
				{
					__result = value;
					return;
				}
				__result += __result / 100 * ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ApartementCostPercentage;
				if (__result < ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinimumApartementCost)
				{
					int num = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinimumApartementCost / 2;
					int num2 = num / 100 * 25;
					__result = RoundToNearestInterval(_valueRandom.Next(num, num + num2) * 2, 50, 100);
				}
				ApartementPriceCache.Add(key, __result);
			}

			private static int RoundToNearestInterval(int number, int lowerInterval, int higherInterval)
			{
				int num = (int)Math.Round((double)number / (double)lowerInterval) * lowerInterval;
				int num2 = (int)Math.Round((double)number / (double)higherInterval) * higherInterval;
				int num3 = Math.Abs(number - num);
				int num4 = Math.Abs(number - num2);
				if (num3 < num4)
				{
					return num;
				}
				return num2;
			}

			internal static void Load(string hash)
			{
				ApartementPriceCache.Clear();
				string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "apartmentpricecache_" + hash + ".json");
				if (!File.Exists(savestoreDirectoryPath))
				{
					return;
				}
				foreach (KeyValuePair<string, int> item in JsonSerializer.Deserialize<Dictionary<string, int>>(File.ReadAllText(savestoreDirectoryPath)))
				{
					ApartementPriceCache.Add(item.Key, item.Value);
				}
				PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Loaded apartment price cache.");
			}

			internal static void Save(string hash)
			{
				if (ApartementPriceCache.Count > 0)
				{
					string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "apartmentpricecache_" + hash + ".json");
					string contents = JsonSerializer.Serialize(ApartementPriceCache, new JsonSerializerOptions
					{
						WriteIndented = false
					});
					File.WriteAllText(savestoreDirectoryPath, contents);
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Saved apartment price cache.");
				}
			}

			internal static void Delete(string hash)
			{
				string savestoreDirectoryPath = Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "apartmentpricecache_" + hash + ".json");
				if (File.Exists(savestoreDirectoryPath))
				{
					File.Delete(savestoreDirectoryPath);
					PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Deleted apartment price cache.");
				}
			}
		}
	}
	internal class PriceVisualPatches
	{
		[HarmonyPatch(typeof(MurderController), "UpdateResolveQuestions")]
		internal class MurderController_UpdateResolveQuestions
		{
			[HarmonyPostfix]
			internal static void Postfix(MurderController __instance)
			{
				//IL_002a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				if (__instance.currentActiveCase != null)
				{
					Enumerator<ResolveQuestion> enumerator = __instance.currentActiveCase.resolveQuestions.GetEnumerator();
					while (enumerator.MoveNext())
					{
						ResolveQuestion current = enumerator.Current;
						current.reward = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.rewardRange) * Game.Instance.jobRewardMultiplier);
						current.penalty = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.penaltyRange) * Game.Instance.jobPenaltyMultiplier);
					}
				}
			}
		}

		[HarmonyPatch(typeof(SideJob), "GenerateResolveQuestions")]
		internal class SideJob_GenerateResolveQuestions
		{
			[HarmonyPostfix]
			internal static void Postfix(SideJob __instance)
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_002c: Invalid comparison between Unknown and I4
				//IL_007b: Unknown result type (might be due to invalid IL or missing references)
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_0057: Unknown result type (might be due to invalid IL or missing references)
				//IL_0062: Unknown result type (might be due to invalid IL or missing references)
				__instance.reward = 0;
				Enumerator<ResolveQuestion> enumerator = __instance.resolveQuestions.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ResolveQuestion current = enumerator.Current;
					float num = 1f;
					if ((int)current.inputType == 3)
					{
						RevengeObjective revengeObjective = __instance.GetRevengeObjective(current);
						if ((SoCustomComparison)(object)revengeObjective != (SoCustomComparison)null)
						{
							float num2 = Toolbox.Instance.Rand(0f, 1f, false);
							num = Mathf.Lerp(revengeObjective.rewardMultiplier.x, revengeObjective.rewardMultiplier.y, num2);
						}
					}
					current.reward = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.rewardRange) * Game.Instance.jobRewardMultiplier * num * GameplayControls.Instance.sideJobDifficultyRewardMultiplier.Evaluate(__instance.GetDifficulty()));
					current.reward = Mathf.RoundToInt((float)current.reward * (1f + UpgradeEffectController.Instance.GetUpgradeEffect((Effect)17)));
					current.penalty = Mathf.RoundToInt(Toolbox.Instance.VectorToRandom(current.penaltyRange) * Game.Instance.jobPenaltyMultiplier * GameplayControls.Instance.sideJobDifficultyRewardMultiplier.Evaluate(__instance.GetDifficulty()));
					__instance.reward += current.reward;
				}
			}
		}
	}
	internal class ToolboxPatches
	{
		[HarmonyPatch(typeof(Toolbox), "LoadAll")]
		internal class Toolbox_LoadAll
		{
			private static bool _appliedOnce;

			[HarmonyPostfix]
			internal static void Postfix(Toolbox __instance)
			{
				if (!_appliedOnce)
				{
					_appliedOnce = true;
					ReduceJobPayouts(__instance);
					AdjustInteractableSpawns(__instance);
					AdjustFurnitureCostPrices(__instance);
					AdjustDialogCostPrices(__instance);
					AdjustItemPrices(__instance);
					AdjustCompanyItemSellMultipliers(__instance);
				}
			}

			private static void AdjustDialogCostPrices(Toolbox __instance)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Expected O, but got Unknown
				int dialogCostPricePercentage = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.DialogCostPricePercentage;
				int num = 0;
				Enumerator<DialogPreset> enumerator = __instance.allDialog.GetEnumerator();
				while (enumerator.MoveNext())
				{
					DialogPreset current = enumerator.Current;
					if (current.cost > 0)
					{
						current.cost += (int)((float)current.cost / 100f * (float)dialogCostPricePercentage);
						num++;
					}
				}
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(31, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" dialog cost prices.");
				}
				log.LogInfo(val);
			}

			private static void AdjustFurnitureCostPrices(Toolbox __instance)
			{
				//IL_0064: Unknown result type (might be due to invalid IL or missing references)
				//IL_006b: Expected O, but got Unknown
				int furniteCostPercentage = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.FurniteCostPercentage;
				int num = 0;
				Enumerator<FurniturePreset> enumerator = __instance.allFurniture.GetEnumerator();
				while (enumerator.MoveNext())
				{
					FurniturePreset current = enumerator.Current;
					if (current.cost > 0)
					{
						current.cost += (int)((float)current.cost / 100f * (float)furniteCostPercentage);
						num++;
					}
				}
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(34, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" furniture cost prices.");
				}
				log.LogInfo(val);
			}

			private static void AdjustCompanyItemSellMultipliers(Toolbox __instance)
			{
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007e: Expected O, but got Unknown
				int percentageSalePriceGeneral = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageSalePriceGeneral;
				int percentageSalePriceBlackMarket = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageSalePriceBlackMarket;
				int num = 0;
				Enumerator<CompanyPreset> enumerator = __instance.allCompanyPresets.GetEnumerator();
				while (enumerator.MoveNext())
				{
					CompanyPreset current = enumerator.Current;
					if (current.enableSellingOfIllegalItems)
					{
						current.sellValueMultiplier = (float)percentageSalePriceBlackMarket / 100f;
					}
					else
					{
						current.sellValueMultiplier = (float)percentageSalePriceGeneral / 100f;
					}
					num++;
				}
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(25, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" store prices.");
				}
				log.LogInfo(val);
			}

			private static void AdjustItemPrices(Toolbox __instance)
			{
				//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ea: Expected O, but got Unknown
				//IL_0037: Unknown result type (might be due to invalid IL or missing references)
				//IL_0135: Unknown result type (might be due to invalid IL or missing references)
				//IL_014a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0156: Unknown result type (might be due to invalid IL or missing references)
				//IL_0164: Unknown result type (might be due to invalid IL or missing references)
				//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00be: Invalid comparison between Unknown and I4
				//IL_00c6: 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)
				//IL_00d9: Invalid comparison between Unknown and I4
				Random random = new Random(1000);
				int num = 0;
				Enumerator<string, InteractablePreset> enumerator = __instance.objectPresetDictionary.GetEnumerator();
				while (enumerator.MoveNext())
				{
					InteractablePreset value = enumerator.Current.value;
					if ((SoCustomComparison)(object)value != (SoCustomComparison)null && value.value.y > 0f && !((SoCustomComparison)value).presetName.Equals("Diamond") && !((SoCustomComparison)value).presetName.Equals("SyncDiskUpgrade"))
					{
						int num2 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageValueIncreaseGeneral;
						int num3 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinGeneralItemValue;
						if ((SoCustomComparison)(object)value.retailItem != (SoCustomComparison)null && value.retailItem.isConsumable && ((int)value.retailItem.menuCategory == 1 || (int)value.retailItem.menuCategory == 0 || (int)value.retailItem.menuCategory == 2) && (value.retailItem.nourishment > 0f || value.retailItem.hydration > 0f))
						{
							num2 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PercentageValueIncreaseFood;
							num3 = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinFoodItemValue;
						}
						float num4 = (float)num2 / 100f + 1f;
						int num5 = Math.Max(num3, (int)value.value.x);
						int num6 = Math.Max(num5 + ((int)value.value.y - (int)value.value.x), (int)value.value.y);
						num5 = (int)((float)num5 * num4);
						num6 = (int)((float)num6 * num4);
						int num7 = num5 - num3;
						if (num7 > 0)
						{
							num5 -= random.Next(0, Math.Min(num7, 15) + 1);
						}
						num6 += random.Next(0, 16);
						value.value = new Vector2((float)num5, (float)num6);
						num++;
					}
				}
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(33, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Adjusted \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" item purchase prices.");
				}
				log.LogInfo(val);
			}

			private static void ReduceJobPayouts(Toolbox __instance)
			{
				//IL_014d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0154: Expected O, but got Unknown
				//IL_0060: 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)
				//IL_008c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
				//IL_0121: Unknown result type (might be due to invalid IL or missing references)
				List<JobPreset> allSideJobs = __instance.allSideJobs;
				int payoutReductionJobs = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.PayoutReductionJobs;
				int num = 0;
				int minSideJobReward = ((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinSideJobReward;
				Enumerator<JobPreset> enumerator = allSideJobs.GetEnumerator();
				while (enumerator.MoveNext())
				{
					JobPreset current = enumerator.Current;
					int num2 = 0;
					int num3 = 0;
					Enumerator<ResolveQuestion> enumerator2 = current.resolveQuestions.GetEnumerator();
					while (enumerator2.MoveNext())
					{
						ResolveQuestion current2 = enumerator2.Current;
						int num4 = Math.Max(1, (int)current2.rewardRange.x - (int)(current2.rewardRange.x / 100f * (float)payoutReductionJobs));
						int num5 = Math.Max(1, (int)current2.rewardRange.y - (int)(current2.rewardRange.y / 100f * (float)payoutReductionJobs));
						current2.rewardRange = new Vector2((float)num4, (float)num5);
						num2 += num4;
						num3 += num5;
					}
					if (num2 < minSideJobReward || num3 < minSideJobReward)
					{
						int num6 = (int)Math.Ceiling((float)minSideJobReward / (float)current.resolveQuestions.Count);
						enumerator2 = current.resolveQuestions.GetEnumerator();
						while (enumerator2.MoveNext())
						{
							enumerator2.Current.rewardRange = new Vector2((float)num6, (float)num6);
						}
					}
					num++;
				}
				ManualLogSource log = PluginController<Plugin, IPluginBindings>.Log;
				bool flag = default(bool);
				BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(23, 1, ref flag);
				if (flag)
				{
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Reduced \"");
					((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
					((BepInExLogInterpolatedStringHandler)val).AppendLiteral("\" job payouts.");
				}
				log.LogInfo(val);
			}

			private static void AdjustInteractableSpawns(Toolbox __instance)
			{
				//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
				//IL_0183: Unknown result type (might be due to invalid IL or missing references)
				InteractablePreset interactablePreset = __instance.GetInteractablePreset("Diamond");
				InteractablePreset interactablePreset2 = __instance.GetInteractablePreset("Hairpin");
				InteractablePreset interactablePreset3 = __instance.GetInteractablePreset("Paperclip");
				InteractablePreset interactablePreset4 = __instance.GetInteractablePreset("SyncDiskUpgrade");
				InteractablePreset interactablePreset5 = __instance.GetInteractablePreset("SyncDisk");
				InteractablePreset[] looseChange = new string[4] { "M1", "M2", "M3", "M4" }.Select((string a) => __instance.GetInteractablePreset(a)).ToArray();
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceDiamondSpawnPerAddress)
				{
					interactablePreset.perRoomLimit = 1;
					interactablePreset.perAddressLimit = 1;
					interactablePreset.limitPerRoom = true;
					interactablePreset.limitPerAddress = true;
				}
				interactablePreset.value = new Vector2((float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinDiamondValue, (float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxDiamondValue);
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.SpawnDiamondsOnlyInApartements)
				{
					interactablePreset.autoPlacement = (AutoPlacement)2;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitSpawnrateSyncDiskUpgradeModules)
				{
					interactablePreset4.perRoomLimit = 1;
					interactablePreset4.perAddressLimit = 2;
					interactablePreset4.perObjectLimit = 1;
					interactablePreset4.perCommercialLimit = 2;
					interactablePreset4.limitInCommercial = true;
					interactablePreset4.limitPerRoom = true;
					interactablePreset4.limitPerAddress = true;
					interactablePreset4.limitPerObject = true;
				}
				interactablePreset4.value = new Vector2((float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MinSyncDiskUpgradeModuleValue, (float)((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.MaxSyncDiskUpgradeModuleValue);
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitSpawnrateSyncDisks)
				{
					interactablePreset5.perRoomLimit = 1;
					interactablePreset5.perAddressLimit = 2;
					interactablePreset5.perObjectLimit = 1;
					interactablePreset5.perCommercialLimit = 2;
					interactablePreset5.limitInCommercial = true;
					interactablePreset5.limitPerRoom = true;
					interactablePreset5.limitPerAddress = true;
					interactablePreset5.limitPerObject = true;
				}
				AdjustHairPins(interactablePreset2);
				AdjustPaperClips(interactablePreset3);
				AdjustLooseChange(looseChange);
				PluginController<Plugin, IPluginBindings>.Log.LogInfo((object)"Adjusted spawn rate of interactables.");
			}

			private static void AdjustLooseChange(InteractablePreset[] looseChange)
			{
				foreach (InteractablePreset val in looseChange)
				{
					val.perRoomLimit = 1;
					val.perAddressLimit = 1;
					val.frequencyPerOwnerMax = 1;
					val.limitPerAddress = true;
					val.limitPerRoom = true;
					val.limitPerObject = true;
					if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitLooseMoneyToApartementsOnly)
					{
						val.autoPlacement = (AutoPlacement)2;
					}
				}
			}

			private static void AdjustPaperClips(InteractablePreset paperClipPreset)
			{
				paperClipPreset.frequencyPerOwnerMin = 0;
				paperClipPreset.frequencyPerOwnerMax = 1;
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerRoom)
				{
					paperClipPreset.perRoomLimit = 1;
					paperClipPreset.limitPerRoom = true;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerAddress)
				{
					paperClipPreset.perAddressLimit = 2;
					paperClipPreset.limitPerAddress = true;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitPaperclipToOfficeOnly)
				{
					paperClipPreset.autoPlacement = (AutoPlacement)1;
				}
			}

			private static void AdjustHairPins(InteractablePreset hairPinPreset)
			{
				hairPinPreset.frequencyPerOwnerMin = 0;
				hairPinPreset.frequencyPerOwnerMax = 1;
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerRoom)
				{
					hairPinPreset.perRoomLimit = 1;
					hairPinPreset.limitPerRoom = true;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.ReduceLockPickSpawnPerAddress)
				{
					hairPinPreset.perAddressLimit = 2;
					hairPinPreset.limitPerAddress = true;
				}
				if (((PluginController<Plugin, IPluginBindings>)PluginController<Plugin, IPluginBindings>.Instance).Config.LimitHairPinToHomeOnly)
				{
					hairPinPreset.autoPlacement = (AutoPlacement)2;
				}
			}
		}
	}
}
namespace SOD.LifeAndLiving.Bindings.SyncDiskBindings
{
	public interface ISyncDiskBindings
	{
		[Binding(true, "Add's the Echolocation sync disk to the game.", "LifeAndLiving.SyncDisks.IncludeEcholocationSyncDisk")]
		bool IncludeEcholocationSyncDisk { get; set; }

		[Binding("#00fbff", "The color for the Echolocation in hex.", "LifeAndLiving.SyncDisks.EcholocationTextColor")]
		string EcholocationTextColor { get; set; }

		[Binding(1250, "The price of the Echolocation sync disk.", "LifeAndLiving.SyncDisks.EcholocationDiskPrice")]
		int EcholocationDiskPrice { get; set; }
	}
}
namespace SOD.LifeAndLiving.Bindings.RelationBindings
{
	public interface IDialogBindings
	{
		[Binding(10, "The percentage chance of the usual being free.", "LifeAndLiving.RelationsDialog.TheUsualFreeChance")]
		int TheUsualFreeChance { get; set; }

		[Binding(25, "The percentage chance to get a discount on the usual.", "LifeAndLiving.RelationsDialog.TheUsualDiscountChance")]
		int TheUsualDiscountChance { get; set; }

		[Binding(35, "The percentage value of the usual's discount.", "LifeAndLiving.RelationsDialog.TheUsualDiscountValuePercentage")]
		int TheUsualDiscountValue { get; set; }

		[Binding(10, "The percentage chance to get a positive interaction when having certain dialog with an npc.", "LifeAndLiving.RelationsDialog.PositiveInteractionChance")]
		int PositiveInteractionChance { get; set; }
	}
}
namespace SOD.LifeAndLiving.Bindings.ImRequirementBindings
{
	public interface ImRequirementBindings
	{
		[Binding(true, "Should the player need a screwdriver in their inventory to open vents?", "LifeAndLiving.ImmersiveRequirements.RequireScrewdriverForVents")]
		bool RequireScrewdriverForVents { get; set; }
	}
}
namespace SOD.LifeAndLiving.Bindings.EconomicBindings
{
	public interface ISideJobBindings
	{
		[Binding(150, "The minimum amount a side job should reward.", "LifeAndLiving.SideJobs.MinSideJobReward")]
		int MinSideJobReward { get; set; }

		[Binding(75, "The percentage reduction of job resolve payouts.", "LifeAndLiving.SideJobs.PayoutReductionJobs")]
		int PayoutReductionJobs { get; set; }

		[Binding(-150, "The percentage reduction of lost items payouts.", "LifeAndLiving.SideJobs.PayoutReductionLostItems")]
		int PayoutReductionLostItems { get; set; }
	}
	public interface IMurderCaseBindings
	{
		[Binding(80, "The percentage reduction of murder case resolve payouts.", "LifeAndLiving.MurderCases.PayoutReductionMurders")]
		int PayoutReductionMurders { get; set; }

		[Binding(50, "The minimum a resolve question of a murder case should payout.", "LifeAndLiving.MurderCases.MinimumMurderResolveQuestionPayout")]
		int MinimumMurderResolveQuestionPayout { get; set; }
	}
	public interface ISpawnRateBindings
	{
		[Binding(true, "This drastically reduces lockpicks per room", "LifeAndLiving.SpawnRate.ReduceLockPickSpawnPerRoom")]
		bool ReduceLockPickSpawnPerRoom { get; set; }

		[Binding(true, "This drastically reduces lockpicks per address", "LifeAndLiving.SpawnRate.ReduceLockPickSpawnPerAddress")]
		bool ReduceLockPickSpawnPerAddress { get; set; }

		[Binding(true, "This drastically reduces diamonds spawned per address", "LifeAndLiving.SpawnRate.ReduceDiamondSpawnPerAddress")]
		bool ReduceDiamondSpawnPerAddress { get; set; }

		[Binding(true, "Should diamonds only spawn in apartements.", "LifeAndLiving.SpawnRate.SpawnDiamondsOnlyInApartements")]
		bool SpawnDiamondsOnlyInApartements { get; set; }

		[Binding(true, "Should hair pins only spawn in apartment homes?", "LifeAndLiving.SpawnRate.LimitHairPinToHomeOnly")]
		bool LimitHairPinToHomeOnly { get; set; }

		[Binding(true, "Should paper clips only spawn in office buildings?", "LifeAndLiving.SpawnRate.LimitPaperclipToOfficeOnly")]
		bool LimitPaperclipToOfficeOnly { get; set; }

		[Binding(true, "Should loose change only spawn in apartements.", "LifeAndLiving.SpawnRate.LimitLooseMoneyToApartementsOnly")]
		bool LimitLooseMoneyToApartementsOnly { get; set; }

		[Binding(true, "This drastically reduces sync disk upgrade modules spawns.", "LifeAndLiving.SpawnRate.LimitSpawnrateSyncDiskUpgradeModules")]
		bool LimitSpawnrateSyncDiskUpgradeModules { get; set; }

		[Binding(true, "This drastically reduces sync disk spawns.", "LifeAndLiving.SpawnRate.LimitSpawnrateSyncDisks")]
		bool LimitSpawnrateSyncDisks { get; set; }
	}
	public interface IHousingBindings
	{
		[Binding(50, "The percentage increase of apartement cost based on the existing price", "LifeAndLiving.Housing.ApartementCostPercentage")]
		int ApartementCostPercentage { get; set; }

		[Binding(5000, "The minimum $ cost of an apartement, if the percentage increase does not cover this minimum it will be adjusted.", "LifeAndLiving.Housing.MinimumApartementCost")]
		int MinimumApartementCost { get; set; }

		[Binding(40, "The percentage increase of furniture cost based on the existing price", "LifeAndLiving.Housing.FurniteCostPercentage")]
		int FurniteCostPercentage { get; set; }

		[Binding(250, "The cost of a lower suite in a hotel per day.", "LifeAndLiving.Housing.CostLowerSuiteHotel")]
		int CostLowerSuiteHotel { get; set; }

		[Binding(500, "The cost of a higher suite in a hotel per day.", "LifeAndLiving.Housing.CostHigherSuiteHotel")]
		int CostHigherSuiteHotel { get; set; }
	}
	public interface IDialogBindings
	{
		[Binding(80, "The percentage increase of things such as guest pass cost, things within dialogs.", "LifeAndLiving.Dialog.DialogCostPricePercentage")]
		int DialogCostPricePercentage { get; set; }
	}
	public interface IMoneyBindings
	{
		[Binding(7, "The maximum $ of loose change in a small stack.", "LifeAndLiving.Money.MaxM1Crows")]
		int MaxM1Crows { get; set; }

		[Binding(14, "The maximum $ of loose change in a medium stack.", "LifeAndLiving.Money.MaxM2Crows")]
		int MaxM2Crows { get; set; }

		[Binding(18, "The maximum $ of loose change in a big stack.", "LifeAndLiving.Money.MaxM3Crows")]
		int MaxM3Crows { get; set; }

		[Binding(25, "The maximum $ of loose change in a huge stack.", "LifeAndLiving.Money.MaxM4Crows")]
		int MaxM4Crows { get; set; }
	}
	public interface IShopsBindings
	{
		[Binding(5, "The amount of lockpicks the buyable kit should give", "LifeAndLiving.Shops.LockPickKitAmount")]
		int LockPickKitAmount { get; set; }

		[Binding(15, "The percentage of item value that is taken for selling items to general stores (default game is 50%)", "LifeAndLiving.Shops.PercentageSalePriceGeneral")]
		int PercentageSalePriceGeneral { get; set; }

		[Binding(40, "The percentage of item value that is taken for selling items to blackmarket (default game is 80%)", "LifeAndLiving.Shops.PercentageSalePriceBlackMarket")]
		int PercentageSalePriceBlackMarket { get; set; }

		[Binding(70, "The max price an item can be sold for in general stores. (diamond excluded)", "LifeAndLiving.Shops.MaxSellPriceAllItemsGeneral")]
		int MaxSellPriceAllItemsGeneral { get; set; }

		[Binding(200, "The max price an item can be sold for in blackmarket. (diamond excluded)", "LifeAndLiving.Shops.MaxSellPriceAllItemsBlackMarket")]
		int MaxSellPriceAllItemsBlackMarket { get; set; }
	}
	public interface IItemPriceBindings
	{
		[Binding(65, "The percentage the value should increase of general items that isn't food.", "LifeAndLiving.ItemPrice.PercentageValueIncreaseGeneral")]
		int PercentageValueIncreaseGeneral { get; set; }

		[Binding(25, "The percentage the value should increase of edible food items.", "LifeAndLiving.ItemPrice.PercentageValueIncreaseFood")]
		int PercentageValueIncreaseFood { get; set; }

		[Binding(25, "The minimum value of a general item that isn't food.", "LifeAndLiving.ItemPrice.MinGeneralItemValue")]
		int MinGeneralItemValue { get; set; }

		[Binding(10, "The minimum value of an edible food item.", "LifeAndLiving.ItemPrice.MinFoodItemValue")]
		int MinFoodItemValue { get; set; }

		[Binding(300, "The minimum value of a diamond.", "LifeAndLiving.ItemPrice.MinDiamondValue")]
		int MinDiamondValue { get; set; }

		[Binding(1000, "The maximum value of a diamond.", "LifeAndLiving.ItemPrice.MaxDiamondValue")]
		int MaxDiamondValue { get; set; }

		[Binding(750, "The minimum value of a sync disk upgrade module.", "LifeAndLiving.ItemPrice.MinSyncDiskUpgradeModuleValue")]
		int MinSyncDiskUpgradeModuleValue { get; set; }

		[Binding(1000, "The maximum value of a sync disk upgrade module.", "LifeAndLiving.ItemPrice.MaxSyncDiskUpgradeModuleValue")]
		int MaxSyncDiskUpgradeModuleValue { get; set; }
	}
}