Decompiled source of DeathAndTaxes v1.2.0

DeathAndTaxes.dll

Decompiled 4 months ago
using System;
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.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Unity.IL2CPP;
using DeathAndTaxes.Handlers;
using DeathAndTaxes.Integrations;
using DeathAndTaxes.Patches;
using DeathAndTaxes.Utilities;
using HarmonyLib;
using Il2CppSystem.Collections.Generic;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.BepInEx;
using SOD.Common.Extensions;
using SOD.Common.Helpers;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("DeathAndTaxes")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DeathAndTaxes")]
[assembly: AssemblyTitle("DeathAndTaxes")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
}
namespace DeathAndTaxes
{
	[BepInPlugin("Severedsolo.SOD.DeathAndTaxes", "DeathAndTaxes", "1.2.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : PluginController<Plugin>
	{
		public const string PLUGIN_GUID = "Severedsolo.SOD.DeathAndTaxes";

		public const string PLUGIN_NAME = "DeathAndTaxes";

		public const string PLUGIN_VERSION = "1.2.0";

		public override void Load()
		{
			((PluginController<Plugin, IEmptyBindings>)(object)this).Harmony.PatchAll(Assembly.GetExecutingAssembly());
			SCFLog("Plugin is patched", LogLevel.Info, forcePrint: true);
			Lib.Time.OnTimeInitialized += RegisterTimeEvents;
			Lib.SaveGame.OnAfterSave += SaveData;
			Lib.SaveGame.OnAfterLoad += LoadData;
			Lib.SaveGame.OnAfterNewGame += ResetDataOnNewGame;
			Lib.PluginDetection.OnAllPluginsFinishedLoading += ExecuteIntegrations;
			BindConfigs();
		}

		private void ExecuteIntegrations(object? sender, EventArgs e)
		{
			Integration[] array = new Integration[1]
			{
				new LifeAndLivingIntegration()
			};
			for (int i = 0; i < array.Length; i++)
			{
				array[i].Execute();
			}
		}

		private void ResetDataOnNewGame(object? sender, EventArgs e)
		{
			PatchSocialCreditLossOnFined.Reset();
			SocialCreditUtilities.SetSocialCreditPayouts();
		}

		private void BindConfigs()
		{
			Settings.IncomeTaxEnabled = base.Config.Bind<bool>("Taxes", "DeathAndTaxes.IncomeTaxEnabled", true, "Income Tax enabled");
			Settings.IncomeTaxModifier = base.Config.Bind<int>("Taxes", "DeathAndTaxes.IncomeTaxModifier", 10, "Each Social Credit rating below 10 will attract this much tax (ie, at 10%, social credit level of 1 will attract 90% (10-1=9*10=90)) (requires IncomeTaxEnabled to be true)");
			Settings.AdjustSocialCreditOnJobCompletion = base.Config.Bind<bool>("SocialCredit", "DeathAndTaxes.AdjustSocialCreditOnJobCompletion", true, "Adjust social credit to completed objectives (eg when solving a murder, if you only get 4 right you'll get 400 SC instead of 500)");
			Settings.MurderFailPenalty = base.Config.Bind<int>("SocialCredit", "DeathAndTaxes.MurderFailPenalty", 100, "If you fail a murder case, how much social credit should we deduct? (requires AdjustSocialCreditOnJobCompletion to be true)");
			Settings.CanFailCompletedCases = base.Config.Bind<bool>("Difficulty", "DeathAndTaxes.CanFailCompletedCases", true, "If you don't complete all objectives on a case, is there a chance you could \"fail\" and have social credit deducted? (requires AdjustSocialCreditOnJobCompletion to be true)");
			Settings.LandValueTaxEnabled = base.Config.Bind<bool>("Taxes", "DeathAndTaxes.LandValueTaxEnabled", true, "Should a \"land value\" tax be applied every day?");
			Settings.LandValueTaxRate = base.Config.Bind<float>("Taxes", "DeathAndTaxes.LandValueTaxRate", 0.1f, "What percentage of the properties value should be taxed? (1 is 100%) (requires LandValueTaxEnabled to be true)");
			Settings.SocialCreditLossOnDeath = base.Config.Bind<bool>("SocialCredit", "DeathAndTaxes.SocialCreditLossOnDeath", true, "Apply a social credit penalty when detained?");
			Settings.FinedSocialCreditLossModifier = base.Config.Bind<float>("SocialCredit", "DeathAndTaxes.FinedSocialCreditLossModifier", 0.1f, "What percentage of fines should be converted to social credit (1=100%)? (Requires SocialCreditLossOnDeath to be true)");
			Settings.PersistentFines = base.Config.Bind<bool>("Difficulty", "DeathAndTaxes.PersistentFines", true, "Should fines be persistent (ie not lost when you exit a building)?");
			Settings.EnableLogging = base.Config.Bind<bool>("Debugging", "DeathAndTaxes.EnableLogging", false, "Should logging in the console be enabled.");
			Settings.FineReducedBySocialCreditRating = base.Config.Bind<bool>("Difficulty", "DeathAndTaxes.FineReducedBySocialCreditRating", false, "Should fines be reduced the higher up the social credit ladder you are?");
			Settings.SocialCreditForMurderSolve = base.Config.Bind<int>("SocialCredit", "DeathAndTaxes.SocialCreditForMurderSolve", 500, "How much social credit should a murder case pay? (before any modifiers)");
			Settings.SocialCreditForSideJobSolve = base.Config.Bind<int>("SocialCredit", "DeathAndTaxes.SocialCreditForSideJobSolve", 250, "How much social credit should a murder case pay? (before any modifiers)");
			SCFLog("Bound all configs", LogLevel.Info, forcePrint: true);
		}

		private void SaveData(object? sender, SaveGameArgs e)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(PatchSocialCreditLossOnFined.Save());
			using StreamWriter streamWriter = new StreamWriter(GetSavePath(e.FilePath));
			streamWriter.Write(stringBuilder.ToString());
		}

		private void LoadData(object? sender, SaveGameArgs e)
		{
			string savePath = GetSavePath(e.FilePath);
			if (!File.Exists(savePath))
			{
				return;
			}
			List<string> list = new List<string>();
			using (StreamReader streamReader = new StreamReader(savePath))
			{
				while (true)
				{
					string text = streamReader.ReadLine();
					if (text == null)
					{
						break;
					}
					list.Add(text);
				}
			}
			if (list.Count != 0)
			{
				PatchSocialCreditLossOnFined.Load(list[0]);
				SocialCreditUtilities.SetSocialCreditPayouts();
			}
		}

		private static string GetSavePath(string savePath)
		{
			string uniqueString = Lib.SaveGame.GetUniqueString(savePath);
			return Lib.SaveGame.GetSavestoreDirectoryPath(Assembly.GetExecutingAssembly(), "DeathAndTaxes_" + uniqueString + ".txt");
		}

		private void RegisterTimeEvents(object? sender, TimeChangedArgs e)
		{
			Lib.Time.OnDayChanged += DayChanged;
		}

		private void DayChanged(object? sender, TimeChangedArgs e)
		{
			LandValueTaxHandler.PayTax();
		}

		internal static void SCFLog(string messageToLog, LogLevel logLevel, bool forcePrint = false)
		{
			switch (logLevel)
			{
			case LogLevel.Info:
				if (forcePrint || Settings.EnableLogging.Value)
				{
					PluginController<Plugin, IEmptyBindings>.Log.LogInfo((object)messageToLog);
				}
				break;
			case LogLevel.Warning:
				PluginController<Plugin, IEmptyBindings>.Log.LogWarning((object)messageToLog);
				break;
			case LogLevel.Error:
				PluginController<Plugin, IEmptyBindings>.Log.LogError((object)messageToLog);
				break;
			}
		}
	}
	internal enum LogLevel
	{
		Info,
		Warning,
		Error
	}
	public static class Settings
	{
		public static ConfigEntry<bool> IncomeTaxEnabled { get; set; }

		public static ConfigEntry<int> IncomeTaxModifier { get; set; }

		public static ConfigEntry<bool> AdjustSocialCreditOnJobCompletion { get; set; }

		public static ConfigEntry<int> MurderFailPenalty { get; set; }

		public static ConfigEntry<bool> CanFailCompletedCases { get; set; }

		public static ConfigEntry<bool> LandValueTaxEnabled { get; set; }

		public static ConfigEntry<float> LandValueTaxRate { get; set; }

		public static ConfigEntry<bool> SocialCreditLossOnDeath { get; set; }

		public static ConfigEntry<float> FinedSocialCreditLossModifier { get; set; }

		public static ConfigEntry<bool> PersistentFines { get; set; }

		public static ConfigEntry<bool> EnableLogging { get; set; }

		public static ConfigEntry<bool> FineReducedBySocialCreditRating { get; set; }

		public static ConfigEntry<int> SocialCreditForMurderSolve { get; set; }

		public static ConfigEntry<int> SocialCreditForSideJobSolve { get; set; }
	}
}
namespace DeathAndTaxes.Utilities
{
	internal static class SCFRandom
	{
		private static readonly Random RandomRoller = new Random();

		internal static int Next(int minNumber, int maxNumber)
		{
			int result = RandomRoller.Next(minNumber, maxNumber);
			Plugin.SCFLog("Rolled " + result, LogLevel.Info);
			return result;
		}

		internal static double NextDouble()
		{
			double num = RandomRoller.NextDouble();
			Plugin.SCFLog("Rolled " + Math.Round(num, 2), LogLevel.Info);
			return num;
		}
	}
	internal static class SocialCreditUtilities
	{
		internal static void AdjustPerksToLevel()
		{
			int num = GameplayController.Instance.GetCurrentSocialCreditLevel() - 1;
			List<SocialCreditBuff> list = EnumerableExtensions.ToList<SocialCreditBuff>(GameplayController.Instance.socialCreditPerks);
			for (int num2 = GameplayController.Instance.socialCreditPerks.Count - 1; num2 >= num; num2--)
			{
				SocialCreditBuff val = list[num2];
				GameplayController.Instance.socialCreditPerks.Remove(val);
				if (GameplayController.Instance.socialCreditPerks.Contains(val))
				{
					Plugin.SCFLog("Failed to remove buff " + val.description, LogLevel.Error);
					break;
				}
				Lib.GameMessage.Broadcast("Removed: " + val.description, (GameMessageType)0, (Icon)21, (Color?)null, 0f);
				Plugin.SCFLog("Removed buff " + val.description, LogLevel.Info);
			}
		}

		public static int GetNormalisedSocialCreditLevel()
		{
			int currentSocialCreditLevel = GameplayController.Instance.GetCurrentSocialCreditLevel();
			return Math.Min(10, currentSocialCreditLevel);
		}

		public static void SetSocialCreditPayouts()
		{
			GameplayControls.Instance.socialCreditForMurders = Settings.SocialCreditForMurderSolve.Value;
			GameplayControls.Instance.socialCreditForSideJobs = Settings.SocialCreditForSideJobSolve.Value;
		}
	}
}
namespace DeathAndTaxes.Patches
{
	[HarmonyPatch(typeof(Case), "Resolve")]
	internal class JobModifier
	{
		private static int TaxRate => (10 - SocialCreditUtilities.GetNormalisedSocialCreditLevel()) * Settings.IncomeTaxModifier.Value;

		private static string TaxStringForPlayer
		{
			get
			{
				if (TaxRate > 0)
				{
					return TaxRate + "% income tax deducted";
				}
				return "Echelon Program member. No tax is due";
			}
		}

		[HarmonyPostfix]
		internal static void PostFix(Case __instance)
		{
			if (!Settings.IncomeTaxEnabled.Value && !Settings.AdjustSocialCreditOnJobCompletion.Value)
			{
				return;
			}
			Plugin.SCFLog("Job handed in. Attempting to calculate reward modifier", LogLevel.Info);
			if (!__instance.isSolved)
			{
				if (Settings.AdjustSocialCreditOnJobCompletion.Value && IsMurder(__instance))
				{
					GameplayController.Instance.AddSocialCredit(-Settings.MurderFailPenalty.Value, true, "Failed murder case");
					SocialCreditUtilities.AdjustPerksToLevel();
					Plugin.SCFLog("Murder was not solved. Penalising player", LogLevel.Info);
				}
				Plugin.SCFLog("Job was not solved. Aborting", LogLevel.Info);
				return;
			}
			int objectivesCorrect = CorrectObjectives(__instance);
			if (Settings.AdjustSocialCreditOnJobCompletion.Value)
			{
				AdjustSocialCreditRewards(__instance, objectivesCorrect);
			}
			if (Settings.IncomeTaxEnabled.Value)
			{
				GameplayController.Instance.AddMoney(-TotalTax(__instance), true, "Social Credit Tax");
				Lib.GameMessage.Broadcast(TaxStringForPlayer, (GameMessageType)0, (Icon)21, (Color?)null, 0f);
			}
		}

		private static int CorrectObjectives(Case job)
		{
			int num = 0;
			Enumerator<ResolveQuestion> enumerator = job.resolveQuestions.GetEnumerator();
			while (enumerator.MoveNext())
			{
				if (enumerator.Current.isCorrect)
				{
					num++;
				}
			}
			return num;
		}

		private static int TotalTax(Case job)
		{
			int totalReward = GetTotalReward(job);
			float num = (float)TaxRate / 100f;
			int result = (int)((float)totalReward * num);
			Plugin.SCFLog("Taxing player at " + TaxRate + "% for " + result, LogLevel.Info);
			return result;
		}

		private static int GetTotalReward(Case job)
		{
			int num = 0;
			int num2 = 0;
			Enumerator<ResolveQuestion> enumerator = job.resolveQuestions.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ResolveQuestion current = enumerator.Current;
				if (current.isCorrect)
				{
					num += current.reward;
					num2++;
				}
			}
			Plugin.SCFLog("Found " + num2 + " completed rewards with a total value of " + num, LogLevel.Info);
			return num;
		}

		private static void AdjustSocialCreditRewards(Case job, int objectivesCorrect)
		{
			float num = (float)objectivesCorrect / (float)job.resolveQuestions.Count;
			int num2 = SocialCreditForJob(job);
			int num3 = (int)((float)num2 * num);
			if (!ClientIsHappy(num, job))
			{
				num3 -= num2;
			}
			int num4 = num3 - num2;
			GameplayController.Instance.AddSocialCredit(num4, true, "Didn't meet all objectives");
			Plugin.SCFLog("Social Credit adjusted by " + num4, LogLevel.Info);
			SocialCreditUtilities.AdjustPerksToLevel();
		}

		private static bool IsMurder(Case job)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Invalid comparison between Unknown and I4
			if ((int)job.caseType != 1)
			{
				return (int)job.caseType == 0;
			}
			return true;
		}

		private static bool ClientIsHappy(float percentageOfObjectivesComplete, Case job)
		{
			if (!Settings.CanFailCompletedCases.Value)
			{
				return true;
			}
			Plugin.SCFLog("Chance of Success: " + Math.Round(percentageOfObjectivesComplete, 2), LogLevel.Info);
			bool flag = SCFRandom.NextDouble() < (double)percentageOfObjectivesComplete;
			BroadcastOutcome(flag, IsMurder(job));
			Plugin.SCFLog("Job passed: " + flag, LogLevel.Info);
			return flag;
		}

		private static void BroadcastOutcome(bool jobPassed, bool isMurder)
		{
			if (jobPassed)
			{
				if (isMurder)
				{
					Lib.GameMessage.Broadcast("We secured a conviction based on the evidence you provided. Good job detective", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
				}
				else
				{
					Lib.GameMessage.Broadcast("The client was satisfied with your investigation", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
				}
			}
			else if (isMurder)
			{
				Lib.GameMessage.Broadcast("We failed to secure a conviction based on the evidence you provided. A penalty will be applied", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
			}
			else
			{
				Lib.GameMessage.Broadcast("The client was dissatisfied with your investigation. A penalty will be applied", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
			}
		}

		private static int SocialCreditForJob(Case job)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			if (IsMurder(job))
			{
				return GameplayControls.Instance.socialCreditForMurders;
			}
			if ((int)job.caseType != 2)
			{
				return 0;
			}
			return GameplayControls.Instance.socialCreditForSideJobs;
		}
	}
	[HarmonyPatch(typeof(StatusController), "PayActiveFines")]
	internal class PatchSocialCreditLossOnFined
	{
		internal static int PreviousFines { get; set; }

		internal static bool PlayerWasRecentlyKnockedOut { get; set; }

		[HarmonyPrefix]
		internal static void Prefix()
		{
			PlayerWasRecentlyKnockedOut = true;
		}

		[HarmonyPostfix]
		private static void Postfix()
		{
			FinePlayerSocialCredit();
			FinePlayerMoney();
			PreviousFines = 0;
		}

		private static void FinePlayerSocialCredit()
		{
			if (Settings.SocialCreditLossOnDeath.Value)
			{
				int num = PreviousFines + SkipFineEscapeCheckPatch.GetTotalActiveFines();
				int num2 = (int)((float)num * Settings.FinedSocialCreditLossModifier.Value);
				GameplayController.Instance.AddSocialCredit(-num2, true, "Player was fined " + num);
				Lib.GameMessage.Broadcast("You lost " + num2 + " social credit", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
				Plugin.SCFLog("Player was fined " + num, LogLevel.Info);
				Plugin.SCFLog("Deducted " + num2 + " social credit from player", LogLevel.Info);
				SocialCreditUtilities.AdjustPerksToLevel();
			}
		}

		private static void FinePlayerMoney()
		{
			if (Settings.PersistentFines.Value)
			{
				int totalActiveFines = SkipFineEscapeCheckPatch.GetTotalActiveFines();
				int num = PreviousFines + totalActiveFines;
				float num2 = 1f;
				if (Settings.FineReducedBySocialCreditRating.Value)
				{
					num2 = 1f - (float)(SocialCreditUtilities.GetNormalisedSocialCreditLevel() - 1) / 10f;
				}
				num = (int)((float)num * num2);
				int num3 = num - totalActiveFines;
				GameplayController.Instance.AddMoney(-num3, false, "persistent fines");
				Lib.GameMessage.Broadcast("You were fined " + num + "cr", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
			}
		}

		internal static string Save()
		{
			if (!Settings.SocialCreditLossOnDeath.Value)
			{
				return string.Empty;
			}
			return (PreviousFines + SkipFineEscapeCheckPatch.GetTotalActiveFines()).ToString();
		}

		internal static void Load(string s)
		{
			if (int.TryParse(s, out var result) && result != 0)
			{
				PreviousFines = result;
				Plugin.SCFLog("Loaded " + result + " in previous fines", LogLevel.Info);
			}
		}

		internal static void Reset()
		{
			PreviousFines = 0;
		}
	}
	[HarmonyPatch(typeof(StatusController), "FineEscapeCheck")]
	internal class SkipFineEscapeCheckPatch
	{
		[HarmonyPrefix]
		internal static void Prefix()
		{
			if (!Settings.PersistentFines.Value)
			{
				return;
			}
			int previousFines = PatchSocialCreditLossOnFined.PreviousFines;
			if (PatchSocialCreditLossOnFined.PlayerWasRecentlyKnockedOut)
			{
				PatchSocialCreditLossOnFined.PlayerWasRecentlyKnockedOut = false;
				return;
			}
			PatchSocialCreditLossOnFined.PreviousFines += GetTotalActiveFines();
			if (PatchSocialCreditLossOnFined.PreviousFines != previousFines)
			{
				Plugin.SCFLog("Fines cleared. New total fines are " + PatchSocialCreditLossOnFined.PreviousFines, LogLevel.Info);
			}
		}

		internal static int GetTotalActiveFines()
		{
			int num = 0;
			Enumerator<StatusInstance, List<StatusCount>> enumerator = StatusController.Instance.activeStatusCounts.GetEnumerator();
			while (enumerator.MoveNext())
			{
				KeyValuePair<StatusInstance, List<StatusCount>> current = enumerator.Current;
				if (!((Object)(object)current.Key.building != (Object)null) || !((Object)(object)current.Key.building == (Object)(object)((Actor)Player.Instance).currentGameLocation.building))
				{
					List<StatusCount> list = EnumerableExtensions.ToList<StatusCount>(current.Value);
					for (int i = 0; i < current.Value.Count; i++)
					{
						StatusCount val = list[i];
						num += val.GetPenaltyAmount();
					}
				}
			}
			return num;
		}
	}
}
namespace DeathAndTaxes.Integrations
{
	internal abstract class Integration
	{
		private BasePlugin? _basePlugin;

		internal abstract string PluginGuid { get; }

		internal PluginInfo PluginInfo => Lib.PluginDetection.GetPluginInfo(PluginGuid);

		internal BasePlugin Plugin => _basePlugin ?? (_basePlugin = Lib.PluginDetection.GetPlugin(PluginInfo, true));

		public void Execute()
		{
			if (Lib.PluginDetection.IsPluginLoaded(PluginGuid))
			{
				DeathAndTaxes.Plugin.SCFLog("[Integration] \"" + PluginInfo.Metadata.Name + "\" found.", LogLevel.Info, forcePrint: true);
				Logic();
				DeathAndTaxes.Plugin.SCFLog("[Integration] \"" + PluginInfo.Metadata.Name + "\" has been enabled.", LogLevel.Info, forcePrint: true);
			}
		}

		internal abstract void Logic();
	}
	internal class LifeAndLivingIntegration : Integration
	{
		internal override string PluginGuid => "Venomaus.SOD.LifeAndLiving";

		internal override void Logic()
		{
			ConfigEntry<int> val = default(ConfigEntry<int>);
			if (base.Plugin.Config.TryGetEntry<int>("LifeAndLiving.MurderCases", "PayoutReductionMurders", ref val))
			{
				val.Value = 0;
			}
			ConfigEntry<int> val2 = default(ConfigEntry<int>);
			if (base.Plugin.Config.TryGetEntry<int>("LifeAndLiving.SideJobs", "PayoutReductionJobs", ref val2))
			{
				val2.Value = 0;
			}
		}
	}
}
namespace DeathAndTaxes.Handlers
{
	internal static class LandValueTaxHandler
	{
		private static int dayTaxLastPaid;

		internal static void PayTax()
		{
			//IL_0017: 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)
			//IL_01b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b7: Unknown result type (might be due to invalid IL or missing references)
			if (!Settings.LandValueTaxEnabled.Value)
			{
				return;
			}
			int num = dayTaxLastPaid;
			TimeData currentDateTime = Lib.Time.CurrentDateTime;
			if (num == ((TimeData)(ref currentDateTime)).Day)
			{
				return;
			}
			Plugin.SCFLog("Paying Land Tax on all owned apartments", LogLevel.Info);
			List<NewAddress> list = EnumerableExtensions.ToList<NewAddress>(Player.Instance.apartmentsOwned);
			if (list.Count == 0)
			{
				return;
			}
			for (int num2 = list.Count - 1; num2 >= 0; num2--)
			{
				NewAddress val = list[num2];
				if (!((Object)(object)val == (Object)null))
				{
					int num3 = (int)((float)((NewGameLocation)val).GetPrice(false) * Settings.LandValueTaxRate.Value);
					if (GameplayController.Instance.money > num3)
					{
						GameplayController.Instance.AddMoney(-num3, true, "Land Value Tax");
						Lib.GameMessage.Broadcast("Land Tax of " + num3 + "cr for " + ((Object)val).name + " paid", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
						Plugin.SCFLog("Paid Land Tax of " + num3 + " on " + ((Object)val).name, LogLevel.Info);
					}
					else
					{
						Player.Instance.apartmentsOwned.Remove(val);
						Lib.GameMessage.Broadcast(((Object)val).name + " has been repossessed due to tax not being paid", (GameMessageType)0, (Icon)21, (Color?)null, 0f);
						Plugin.SCFLog("Repossessed " + ((Object)val).name + " due to lack of funds", LogLevel.Info);
						if (!((Object)(object)((Human)Player.Instance).residence.address != (Object)(object)val))
						{
							((Human)Player.Instance).SetResidence(FindNewResidence(), true);
						}
					}
				}
			}
			currentDateTime = Lib.Time.CurrentDateTime;
			dayTaxLastPaid = ((TimeData)(ref currentDateTime)).Day;
		}

		private static ResidenceController? FindNewResidence()
		{
			ResidenceController val = ((Player.Instance.apartmentsOwned.Count == 0) ? null : EnumerableExtensions.ToList<NewAddress>(Player.Instance.apartmentsOwned).Last().residence);
			string text = (((Object)(object)val == (Object)null) ? "You are now homeless" : ("You now live at " + ((Object)val).name));
			Lib.GameMessage.Broadcast(text, (GameMessageType)0, (Icon)21, (Color?)null, 0f);
			return val;
		}
	}
}