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;
}
}
}