Decompiled source of FAndCDaveCo v2.0.0

BepInEx/plugins/tesinormed.FAndCDaveCo.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using CSync.Extensions;
using CSync.Lib;
using GameNetcodeStuff;
using HarmonyLib;
using InteractiveTerminalAPI.UI;
using InteractiveTerminalAPI.UI.Application;
using InteractiveTerminalAPI.UI.Cursor;
using InteractiveTerminalAPI.UI.Screen;
using LethalModDataLib.Enums;
using LethalModDataLib.Events;
using LethalModDataLib.Features;
using LethalNetworkAPI;
using LethalNetworkAPI.Utils;
using LobbyCompatibility.Attributes;
using Microsoft.CodeAnalysis;
using Unity.Netcode;
using UnityEngine;
using tesinormed.FAndCDaveCo.Bank;
using tesinormed.FAndCDaveCo.Bank.UI;
using tesinormed.FAndCDaveCo.Extensions;
using tesinormed.FAndCDaveCo.Insurance;
using tesinormed.FAndCDaveCo.Insurance.UI;
using tesinormed.FAndCDaveCo.Network;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: IgnoresAccessChecksTo("ClientNetworkTransform")]
[assembly: IgnoresAccessChecksTo("DissonanceVoip")]
[assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")]
[assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")]
[assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")]
[assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")]
[assembly: IgnoresAccessChecksTo("Unity.Burst")]
[assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")]
[assembly: IgnoresAccessChecksTo("Unity.Collections")]
[assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem")]
[assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")]
[assembly: IgnoresAccessChecksTo("Unity.Jobs")]
[assembly: IgnoresAccessChecksTo("Unity.Mathematics")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")]
[assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")]
[assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")]
[assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")]
[assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")]
[assembly: IgnoresAccessChecksTo("Unity.Services.QoS")]
[assembly: IgnoresAccessChecksTo("Unity.Services.Relay")]
[assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")]
[assembly: IgnoresAccessChecksTo("Unity.Timeline")]
[assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")]
[assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")]
[assembly: IgnoresAccessChecksTo("UnityEngine.UI")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("tesinormed.FAndCDaveCo")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("2.0.0.0")]
[assembly: AssemblyInformationalVersion("2.0.0+14e4dc01ea4c406787181855f4e5b262b6c36517")]
[assembly: AssemblyProduct("FAndCDaveCo")]
[assembly: AssemblyTitle("tesinormed.FAndCDaveCo")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("2.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace tesinormed.FAndCDaveCo
{
	public class Config : SyncedConfig2<Config>
	{
		[SyncedEntryField]
		public readonly SyncedEntry<bool> GameDisableDeathCreditPenalty;

		[SyncedEntryField]
		public readonly SyncedEntry<double> EconomicBasePremium;

		[SyncedEntryField]
		public readonly SyncedEntry<double> EconomicDeductible;

		[SyncedEntryField]
		public readonly SyncedEntry<double> EconomicDeductibleMaximum;

		[SyncedEntryField]
		public readonly SyncedEntry<double> EconomicDeductibleMinimum;

		[SyncedEntryField]
		public readonly SyncedEntry<double> StandardBasePremium;

		[SyncedEntryField]
		public readonly SyncedEntry<double> StandardDeductible;

		[SyncedEntryField]
		public readonly SyncedEntry<double> StandardDeductibleMaximum;

		[SyncedEntryField]
		public readonly SyncedEntry<double> StandardDeductibleMinimum;

		[SyncedEntryField]
		public readonly SyncedEntry<double> BespokeBasePremium;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption00;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption01;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption02;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption03;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption04;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption05;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption06;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption07;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption08;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption09;

		[SyncedEntryField]
		public readonly SyncedEntry<int> CoverageOption10;

		[SyncedEntryField]
		public readonly SyncedEntry<int> ClaimRetentionDays;

		[SyncedEntryField]
		public readonly SyncedEntry<double> ClaimPremiumIncrease;

		[SyncedEntryField]
		public readonly SyncedEntry<int> PenaltyStartDaysFromIssuance;

		[SyncedEntryField]
		public readonly SyncedEntry<double> PenaltyAmount;

		[SyncedEntryField]
		public readonly SyncedEntry<double> InterestAmount;

		public Config(ConfigFile configFile)
			: base("tesinormed.FAndCDaveCo")
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			//IL_0032: Expected O, but got Unknown
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Expected O, but got Unknown
			//IL_0066: Expected O, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Expected O, but got Unknown
			//IL_009a: Expected O, but got Unknown
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_00ce: Expected O, but got Unknown
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Expected O, but got Unknown
			//IL_0102: Expected O, but got Unknown
			//IL_0113: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			//IL_0136: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0160: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Expected O, but got Unknown
			//IL_016a: Expected O, but got Unknown
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019e: Expected O, but got Unknown
			//IL_019e: Expected O, but got Unknown
			//IL_01af: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Expected O, but got Unknown
			//IL_01d2: Expected O, but got Unknown
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Expected O, but got Unknown
			//IL_0206: Expected O, but got Unknown
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Expected O, but got Unknown
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Expected O, but got Unknown
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Expected O, but got Unknown
			//IL_027a: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Expected O, but got Unknown
			//IL_029b: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Expected O, but got Unknown
			//IL_02bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cc: Expected O, but got Unknown
			//IL_02dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ed: Expected O, but got Unknown
			//IL_02fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_030e: Expected O, but got Unknown
			//IL_031f: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: Expected O, but got Unknown
			//IL_0340: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Expected O, but got Unknown
			//IL_0361: Unknown result type (might be due to invalid IL or missing references)
			//IL_0371: Expected O, but got Unknown
			//IL_0382: Unknown result type (might be due to invalid IL or missing references)
			//IL_039b: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a5: Expected O, but got Unknown
			//IL_03a5: Expected O, but got Unknown
			//IL_03b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d2: Expected O, but got Unknown
			//IL_03d2: Expected O, but got Unknown
			//IL_03e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fe: Expected O, but got Unknown
			//IL_03fe: Expected O, but got Unknown
			//IL_040f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0428: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Expected O, but got Unknown
			//IL_0432: Expected O, but got Unknown
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0466: Expected O, but got Unknown
			//IL_0466: Expected O, but got Unknown
			GameDisableDeathCreditPenalty = SyncedBindingExtensions.BindSyncedEntry<bool>(configFile, new ConfigDefinition("Game", "DisableDeathCreditPenalty"), true, new ConfigDescription("Whether to disable the death credit penalty (only if there is a current insurance policy)", (AcceptableValueBase)null, Array.Empty<object>()));
			EconomicBasePremium = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Economic", "BasePremium"), 0.07, new ConfigDescription("Initial premiums before any additional penalties due to submitted claims", (AcceptableValueBase)null, Array.Empty<object>()));
			EconomicDeductible = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Economic", "Deductible"), 0.25, new ConfigDescription("Percent of claim amount that must be paid before a payout is made", (AcceptableValueBase)null, Array.Empty<object>()));
			EconomicDeductibleMinimum = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Economic", "DeductibleMinimum"), 0.15, new ConfigDescription("Percent of coverage that sets the deductible minimum amount", (AcceptableValueBase)null, Array.Empty<object>()));
			EconomicDeductibleMaximum = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Economic", "DeductibleMaximum"), 0.6, new ConfigDescription("Percent of coverage that sets the deductible maximum amount", (AcceptableValueBase)null, Array.Empty<object>()));
			StandardBasePremium = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Standard", "BasePremium"), 0.15, new ConfigDescription("Initial premiums before any additional penalties due to submitted claims", (AcceptableValueBase)null, Array.Empty<object>()));
			StandardDeductible = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Standard", "Deductible"), 0.1, new ConfigDescription("Percent of claim amount that must be paid before a payout is made", (AcceptableValueBase)null, Array.Empty<object>()));
			StandardDeductibleMinimum = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Standard", "DeductibleMinimum"), 0.1, new ConfigDescription("Percent of coverage that sets the deductible minimum amount", (AcceptableValueBase)null, Array.Empty<object>()));
			StandardDeductibleMaximum = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Standard", "DeductibleMaximum"), 0.3, new ConfigDescription("Percent of coverage that sets the deductible maximum amount", (AcceptableValueBase)null, Array.Empty<object>()));
			BespokeBasePremium = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Policies.Bespoke", "BasePremium"), 0.35, new ConfigDescription("Initial premiums before any additional penalties due to submitted claims", (AcceptableValueBase)null, Array.Empty<object>()));
			CoverageOption00 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option00"), 150, (ConfigDescription)null);
			CoverageOption01 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option01"), 400, (ConfigDescription)null);
			CoverageOption02 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option02"), 800, (ConfigDescription)null);
			CoverageOption03 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option03"), 1500, (ConfigDescription)null);
			CoverageOption04 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option04"), 2250, (ConfigDescription)null);
			CoverageOption05 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option05"), 3600, (ConfigDescription)null);
			CoverageOption06 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option06"), 5500, (ConfigDescription)null);
			CoverageOption07 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option07"), 8000, (ConfigDescription)null);
			CoverageOption08 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option08"), 11125, (ConfigDescription)null);
			CoverageOption09 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option09"), 15250, (ConfigDescription)null);
			CoverageOption10 = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Coverage", "Option10"), 18000, (ConfigDescription)null);
			ClaimPremiumIncrease = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Insurance.Claims", "PremiumIncrease"), 0.25, new ConfigDescription("Percent of the cumulative premium increase for each submitted claim", (AcceptableValueBase)null, Array.Empty<object>()));
			ClaimRetentionDays = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Insurance.Claims", "RetentionDays"), 10, new ConfigDescription("Days that claims are retained in the save (sets the maximum increase for premiums)", (AcceptableValueBase)null, Array.Empty<object>()));
			PenaltyStartDaysFromIssuance = SyncedBindingExtensions.BindSyncedEntry<int>(configFile, new ConfigDefinition("Bank.Loan.Penalty", "StartDaysFromIssuance"), 4, new ConfigDescription("Start of the late penalty in days from the issuance date", (AcceptableValueBase)null, Array.Empty<object>()));
			PenaltyAmount = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Bank.Loan.Penalty", "Amount"), 0.1, new ConfigDescription("Percent of the credits garnished each day", (AcceptableValueBase)null, Array.Empty<object>()));
			InterestAmount = SyncedBindingExtensions.BindSyncedEntry<double>(configFile, new ConfigDefinition("Bank.Loan", "InterestAmount"), 0.05, new ConfigDescription("Percent of the principal added on for interest (only added once)", (AcceptableValueBase)null, Array.Empty<object>()));
			ConfigManager.Register<Config>((SyncedConfig2<Config>)(object)this);
		}
	}
	[BepInPlugin("tesinormed.FAndCDaveCo", "FAndCDaveCo", "2.0.0")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency("LethalNetworkAPI", "3.0.0")]
	[BepInDependency("com.sigurd.csync", "5.0.0")]
	[LobbyCompatibility(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		public static Plugin Instance { get; private set; }

		internal static ManualLogSource Logger { get; private set; }

		internal static Terminal Terminal { get; set; }

		internal Config Config { get; private set; }

		public State State { get; private set; }

		private void Awake()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Expected O, but got Unknown
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			Config = new Config(((BaseUnityPlugin)this).Config);
			State = new State();
			SaveLoadEvents.PostSaveGameEvent += (PostSaveGameEventHandler)delegate
			{
				State.Save();
			};
			SaveLoadEvents.PostLoadGameEvent += (PostLoadGameEventHandler)delegate
			{
				State.Load();
			};
			SaveLoadEvents.PostDeleteSaveEvent += (PostDeleteSaveEventHandler)delegate
			{
				State.Reset();
				HUDManagerEvents.QueuedHudTips.Clear();
			};
			SaveLoadEvents.PostResetSavedGameValuesEvent += (PostResetSavedGameValuesEventHandler)delegate
			{
				State.Reset();
				HUDManagerEvents.QueuedHudTips.Clear();
				State.Save();
			};
			CreditEvents.Init();
			HUDManagerEvents.Init();
			InteractiveTerminalManager.RegisterApplication<PolicyInformationTerminal>(new string[3] { "insurance info", "insurance information", "insurance policy" });
			InteractiveTerminalManager.RegisterApplication<PolicySelectTerminal>(new string[2] { "insurance select", "insurance get" });
			InteractiveTerminalManager.RegisterApplication<PolicyClaimTerminal>(new string[3] { "insurance claim", "insurance claims", "insurance make claim" });
			InteractiveTerminalManager.RegisterApplication<BankLoanInformationTerminal>(new string[2] { "bank loan info", "bank loan information" });
			InteractiveTerminalManager.RegisterApplication<BankLoanGetTerminal>(new string[2] { "bank loan get", "bank loan" });
			InteractiveTerminalManager.RegisterApplication<BankLoanPaymentTerminal>(new string[2] { "bank loan pay", "bank loan payment" });
			Harmony val = new Harmony("tesinormed.FAndCDaveCo");
			Logger.LogDebug((object)"patching in progress");
			val.PatchAll(Assembly.GetExecutingAssembly());
			Logger.LogDebug((object)"finished patching");
			Logger.LogInfo((object)"tesinormed.FAndCDaveCo (FAndCDaveCo) version 2.0.0 loaded");
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "tesinormed.FAndCDaveCo";

		public const string PLUGIN_NAME = "FAndCDaveCo";

		public const string PLUGIN_VERSION = "2.0.0";
	}
}
namespace tesinormed.FAndCDaveCo.Patches
{
	[HarmonyPatch(typeof(NetworkManager), "Initialize")]
	internal static class NetworkManager_Initialize_Patch
	{
		public static void Postfix(ref NetworkManager __instance)
		{
			if (LNetworkUtils.IsHostOrServer)
			{
				__instance.OnClientConnectedCallback += delegate
				{
					Plugin.Instance.State.MakeDirty();
				};
			}
		}
	}
	[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
	internal static class RoundManager_DespawnPropsAtEndOfRound_Patch
	{
		public static void Prefix(ref RoundManager __instance)
		{
			if (!((NetworkBehaviour)__instance).IsServer || !StartOfRound.Instance.allPlayersDead || Plugin.Instance.State.Policy.Tier == PolicyTier.None)
			{
				return;
			}
			int totalScrapValue = (from grabbableObject in GameObject.Find("/Environment/HangarShip").GetComponentsInChildren<GrabbableObject>()
				where grabbableObject.itemProperties.isScrap && !(grabbableObject is RagdollGrabbableObject)
				select grabbableObject).Sum((GrabbableObject grabbableObject) => grabbableObject.scrapValue);
			if (totalScrapValue > 0)
			{
				int claimDay = StartOfRound.Instance.gameStats.daysSpent - 1;
				Plugin.Instance.State.MutateClaims(delegate(Dictionary<int, Claim> claims)
				{
					claims[claimDay] = new Claim(totalScrapValue);
				});
				Plugin.Logger.LogInfo((object)$"crew all dead, recorded pending claim with value of {totalScrapValue} for day {claimDay}");
				HUDManagerEvents.InsuranceClaimAvailable.InvokeClients();
			}
		}
	}
	[HarmonyPatch(typeof(StartOfRound), "EndOfGame")]
	internal static class StartOfRound_EndOfGame_Patch
	{
		public static void Prefix(ref StartOfRound __instance)
		{
			StartOfRound val = __instance;
			if (val == null || !((NetworkBehaviour)val).IsServer || val.isChallengeFile)
			{
				return;
			}
			foreach (KeyValuePair<int, Claim> keyValuePair in Plugin.Instance.State.Claims.Where<KeyValuePair<int, Claim>>((KeyValuePair<int, Claim> pair) => StartOfRound.Instance.gameStats.daysSpent - pair.Key > SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.ClaimRetentionDays)))
			{
				Plugin.Instance.State.MutateClaims(delegate(Dictionary<int, Claim> claims)
				{
					claims.Remove(keyValuePair.Key);
				});
				Plugin.Logger.LogDebug((object)$"deleted old claim from day {keyValuePair.Key}: {keyValuePair.Value}");
			}
			if (Plugin.Instance.State.Policy != Policy.None)
			{
				if (Plugin.Terminal.groupCredits >= Plugin.Instance.State.TotalPremium)
				{
					CreditEvents.DeductGroupCredits.SendServer(Plugin.Instance.State.TotalPremium);
					HUDManagerEvents.InsuranceRenewalSuccess.SendClients(Plugin.Instance.State.TotalPremium);
					Plugin.Logger.LogDebug((object)$"insurance successfully renewed with premium of {Plugin.Instance.State.TotalPremium}");
				}
				else
				{
					Plugin.Instance.State.Policy = Policy.None;
					HUDManagerEvents.InsuranceRenewalFail.InvokeClients();
					Plugin.Logger.LogDebug((object)"insurance failed to renew");
				}
			}
			if (Plugin.Instance.State.Loan.AmountUnpaid > 0 && Plugin.Instance.State.Loan.DaysSinceIssuance >= SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.PenaltyStartDaysFromIssuance))
			{
				int num = Math.Min((int)((double)Plugin.Terminal.groupCredits * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.PenaltyAmount)), Plugin.Instance.State.Loan.AmountUnpaid);
				CreditEvents.DeductGroupCredits.SendServer(num);
				Plugin.Logger.LogDebug((object)$"garnished ${num} from group credits due to loan nonpayment");
				if (Plugin.Instance.State.Loan.AmountUnpaid - num == 0)
				{
					Plugin.Instance.State.Loan = Loan.None;
					Plugin.Logger.LogDebug((object)"loan fully paid off due to garnishment");
				}
				else
				{
					Plugin.Instance.State.Loan = Plugin.Instance.State.Loan with
					{
						AmountPaid = Plugin.Instance.State.Loan.AmountPaid + num
					};
					Plugin.Logger.LogDebug((object)$"loan amount paid increased by {num}");
				}
				HUDManagerEvents.BankLoanCreditsGarnished.SendClients(num);
			}
		}

		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		public static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator generator)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			CodeMatcher obj = new CodeMatcher(instructions, generator).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, AccessTools.Method(typeof(HUDManager), "ApplyPenalty", (Type[])null, (Type[])null)))).SearchBack((Func<CodeInstruction, bool>)((CodeInstruction instruction) => CodeInstructionExtensions.LoadsField(instruction, AccessTools.Field(typeof(StartOfRound), "isChallengeFile"), false))).SearchForward((Func<CodeInstruction, bool>)((CodeInstruction instruction) => instruction.opcode == OpCodes.Brtrue));
			object operand = obj.Operand;
			return obj.Advance(1).InsertAndAdvance((CodeInstruction[])(object)new CodeInstruction[2]
			{
				new CodeInstruction(OpCodes.Call, (object)AccessTools.PropertyGetter(typeof(State), "DisableDeathCreditPenalty")),
				new CodeInstruction(OpCodes.Brtrue, operand)
			}).InstructionEnumeration();
		}

		public static IEnumerator Postfix(IEnumerator values, StartOfRound __instance)
		{
			do
			{
				yield return values.Current;
			}
			while (values.MoveNext());
			if (__instance != null && ((NetworkBehaviour)__instance).IsServer && !__instance.isChallengeFile && !((double)TimeOfDay.Instance.timeUntilDeadline <= 0.0))
			{
				HUDManagerEvents.RunShowQueuedHudTips.InvokeClients();
			}
		}
	}
	[HarmonyPatch(typeof(Terminal), "Awake")]
	internal static class Terminal_Awake_Patch
	{
		public static void Postfix(ref Terminal __instance)
		{
			Plugin.Terminal = __instance;
		}
	}
}
namespace tesinormed.FAndCDaveCo.Network
{
	public static class CreditEvents
	{
		public static LNetworkMessage<int> DeductGroupCredits;

		public static LNetworkMessage<int> SpawnGoldBar;

		internal static LNetworkMessage<Tuple<NetworkObjectReference, int>> SyncItemScrap;

		public static LNetworkEvent TakeOutLoan;

		internal static void Init()
		{
			DeductGroupCredits = LNetworkMessage<int>.Connect("DeductGroupCredits", (Action<int, ulong>)delegate(int amount, ulong _)
			{
				if (Plugin.Terminal.groupCredits < amount)
				{
					Plugin.Logger.LogError((object)$"could not deduct {amount} credits; balance would be under 0");
				}
				else
				{
					Terminal terminal = Plugin.Terminal;
					terminal.groupCredits -= amount;
					Plugin.Terminal.SyncGroupCreditsServerRpc(Plugin.Terminal.groupCredits, Plugin.Terminal.numberOfItemsInDropship);
					Plugin.Logger.LogDebug((object)$"deducted {amount} credits");
				}
			}, (Action<int>)null, (Action<int, ulong>)null);
			SpawnGoldBar = LNetworkMessage<int>.Connect("SpawnGoldBar", (Action<int, ulong>)delegate(int value, ulong client)
			{
				//IL_0065: Unknown result type (might be due to invalid IL or missing references)
				//IL_006a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0072: Unknown result type (might be due to invalid IL or missing references)
				//IL_0104: Unknown result type (might be due to invalid IL or missing references)
				Item val = StartOfRound.Instance.allItemsList.itemsList.Single((Item item) => item.itemName.ToLower() == "gold bar");
				PlayerControllerB playerController = LethalNetworkExtensions.GetPlayerController(client);
				if ((Object)(object)playerController == (Object)null)
				{
					Plugin.Logger.LogError((object)$"could not get player controller for client {client}");
				}
				else
				{
					Vector3 position = ((Component)playerController).transform.position;
					GameObject val2 = Object.Instantiate<GameObject>(val.spawnPrefab, position, Quaternion.identity, GameObject.Find("/Environment/HangarShip").transform);
					val2.GetComponent<GrabbableObject>().itemProperties.isScrap = true;
					val2.GetComponent<GrabbableObject>().itemProperties.creditsWorth = value;
					val2.GetComponent<GrabbableObject>().SetScrapValue(value);
					playerController.SetItemInElevator(true, true, val2.GetComponent<GrabbableObject>());
					val2.GetComponent<NetworkObject>().Spawn(true);
					Plugin.Logger.LogDebug((object)$"spawned gold bar with value of {value} at client {LethalNetworkExtensions.GetClientId(playerController)}");
					SyncItemScrap.SendClients(new Tuple<NetworkObjectReference, int>(NetworkObjectReference.op_Implicit(val2.GetComponent<NetworkObject>()), value));
				}
			}, (Action<int>)null, (Action<int, ulong>)null);
			SyncItemScrap = LNetworkMessage<Tuple<NetworkObjectReference, int>>.Connect("SyncItemScrapValue", (Action<Tuple<NetworkObjectReference, int>, ulong>)null, (Action<Tuple<NetworkObjectReference, int>>)delegate(Tuple<NetworkObjectReference, int> value)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				NetworkObjectReference.op_Implicit(value.Item1).GetComponent<GrabbableObject>().SetScrapValue(value.Item2);
			}, (Action<Tuple<NetworkObjectReference, int>, ulong>)null);
			TakeOutLoan = LNetworkEvent.Connect("TakeOutLoan", (Action<ulong>)delegate
			{
				Loan loan = new Loan(StartOfRound.Instance.gameStats.daysSpent, TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled);
				Plugin.Instance.State.Loan = loan;
				Plugin.Logger.LogDebug((object)$"took out a loan for {loan.Principal}");
				TimeOfDay.Instance.quotaFulfilled = TimeOfDay.Instance.profitQuota;
				TakeOutLoan.InvokeClients();
			}, (Action)delegate
			{
				TimeOfDay.Instance.quotaFulfilled = TimeOfDay.Instance.profitQuota;
				TimeOfDay.Instance.UpdateProfitQuotaCurrentTime();
				StartOfRound.Instance.AutoSaveShipData();
			}, (Action<ulong>)null);
		}
	}
	public static class HUDManagerEvents
	{
		public static LNetworkMessage<int> InsuranceRenewalSuccess = null;

		public static LNetworkEvent InsuranceRenewalFail = null;

		public static LNetworkEvent InsuranceClaimAvailable = null;

		public static LNetworkMessage<int> BankLoanCreditsGarnished = null;

		public static LNetworkEvent RunShowQueuedHudTips = null;

		internal static readonly List<Action> QueuedHudTips = new List<Action>();

		internal static void Init()
		{
			InsuranceRenewalSuccess = LNetworkMessage<int>.Connect("InsuranceRenewalSuccess", (Action<int, ulong>)null, (Action<int>)delegate(int value)
			{
				QueuedHudTips.Add(delegate
				{
					HUDManager.Instance.DisplayTip("Insurance renewed", $"{value} credits have been deducted.", false, false, "LC_Tip1");
				});
				Plugin.Logger.LogDebug((object)"queued insurance renewal success on HUD");
			}, (Action<int, ulong>)null);
			InsuranceRenewalFail = LNetworkEvent.Connect("InsuranceRenewalFail", (Action<ulong>)null, (Action)delegate
			{
				QueuedHudTips.Add(delegate
				{
					HUDManager.Instance.DisplayTip("Insurance canceled", "You do not have sufficient credits.", true, false, "LC_Tip1");
				});
				Plugin.Logger.LogDebug((object)"queued insurance renewal fail on HUD");
			}, (Action<ulong>)null);
			InsuranceClaimAvailable = LNetworkEvent.Connect("InsuranceClaimAvailable", (Action<ulong>)null, (Action)delegate
			{
				QueuedHudTips.Add(delegate
				{
					HUDManager.Instance.DisplayTip("Insurance claim", "Confirm the pending claim at the terminal.", false, false, "LC_Tip1");
				});
				Plugin.Logger.LogDebug((object)"queued insurance claim available on HUD");
			}, (Action<ulong>)null);
			BankLoanCreditsGarnished = LNetworkMessage<int>.Connect("BankLoanCreditsGarnished", (Action<int, ulong>)null, (Action<int>)delegate(int value)
			{
				QueuedHudTips.Add(delegate
				{
					HUDManager.Instance.DisplayTip("Credits garnished", $"Due to loan nonpayment, {(int)(SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.PenaltyAmount) * 100.0)}% of your credits (▮{value}) have been garnished.", true, false, "LC_Tip1");
				});
				Plugin.Logger.LogDebug((object)"queued loan credit garnishing warning on HUD");
			}, (Action<int, ulong>)null);
			RunShowQueuedHudTips = LNetworkEvent.Connect("RunShowQueuedHudTips", (Action<ulong>)null, (Action)delegate
			{
				((MonoBehaviour)HUDManager.Instance).StartCoroutine(ShowQueuedHudTips());
			}, (Action<ulong>)null);
		}

		private static IEnumerator ShowQueuedHudTips()
		{
			for (int index = 0; index < QueuedHudTips.Count; index++)
			{
				Action tip = QueuedHudTips[index];
				if (index == 0)
				{
					yield return (object)new WaitForSeconds(3f);
				}
				tip();
				Plugin.Logger.LogDebug((object)"displayed queued HUD tip");
				yield return (object)new WaitForSeconds(7.5f);
			}
			QueuedHudTips.Clear();
		}
	}
	public record State
	{
		public static bool DisableDeathCreditPenalty
		{
			get
			{
				if (Plugin.Instance.State.Policy.Tier == PolicyTier.None)
				{
					return false;
				}
				return SyncedEntry<bool>.op_Implicit(Plugin.Instance.Config.GameDisableDeathCreditPenalty);
			}
		}

		public Policy Policy
		{
			get
			{
				return _policy.Value;
			}
			set
			{
				_policy.Value = value;
			}
		}

		public Dictionary<int, Claim> Claims
		{
			get
			{
				return _claims.Value;
			}
			set
			{
				_claims.Value = value;
			}
		}

		public Dictionary<int, Claim> ClaimedClaims => Claims.Where<KeyValuePair<int, Claim>>((KeyValuePair<int, Claim> pair) => pair.Value.Claimed).ToDictionary();

		public Dictionary<int, Claim> UnclaimedClaims => Claims.Where<KeyValuePair<int, Claim>>((KeyValuePair<int, Claim> pair) => !pair.Value.Claimed).ToDictionary();

		public double FractionalPremiumIncrease => (double)ClaimedClaims.Count * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.ClaimPremiumIncrease);

		public int TotalPremium => CalculateTotalPremium(Policy.BasePremium);

		public Loan Loan
		{
			get
			{
				return _loan.Value;
			}
			set
			{
				_loan.Value = value;
			}
		}

		private readonly LNetworkVariable<Policy> _policy = LNetworkVariable<tesinormed.FAndCDaveCo.Insurance.Policy>.Connect("Policy", (Policy)null, (LNetworkVariableWritePerms)2, (Action<Policy, Policy>)delegate(Policy previous, Policy current)
		{
			Plugin.Logger.LogDebug((object)string.Format("{0} changed from ({1}) to ({2})", "Policy", previous, current));
		});

		private readonly LNetworkVariable<Dictionary<int, Claim>> _claims = LNetworkVariable<Dictionary<int, Claim>>.Connect("Claims", (Dictionary<int, Claim>)null, (LNetworkVariableWritePerms)2, (Action<Dictionary<int, Claim>, Dictionary<int, Claim>>)delegate(Dictionary<int, Claim> previous, Dictionary<int, Claim> current)
		{
			Plugin.Logger.LogDebug((object)("Claims changed from (" + string.Join(", ", previous ?? new Dictionary<int, Claim>()) + ") to (" + string.Join(", ", current ?? new Dictionary<int, Claim>()) + ")"));
		});

		private readonly LNetworkVariable<Loan> _loan = LNetworkVariable<tesinormed.FAndCDaveCo.Bank.Loan>.Connect("Loan", (Loan)null, (LNetworkVariableWritePerms)2, (Action<Loan, Loan>)delegate(Loan previous, Loan current)
		{
			Plugin.Logger.LogDebug((object)string.Format("{0} changed from ({1}) to ({2})", "Loan", previous, current));
		});

		public void MutateClaims(Action<Dictionary<int, Claim>> mutation)
		{
			mutation(Claims);
			_claims.MakeDirty();
		}

		internal int CalculateTotalPremium(Policy policy)
		{
			return CalculateTotalPremium(policy.BasePremium);
		}

		private int CalculateTotalPremium(int basePremium)
		{
			return (int)((double)basePremium * (1.0 + FractionalPremiumIncrease));
		}

		public void MutateLoan(Action<Loan> mutation)
		{
			mutation(Loan);
			_loan.MakeDirty();
		}

		internal void Save()
		{
			SaveLoadHandler.SaveData<Policy>(Policy, "Policy", (SaveLocation)0, true);
			SaveLoadHandler.SaveData<Dictionary<int, Claim>>(Claims, "Claims", (SaveLocation)0, true);
			SaveLoadHandler.SaveData<Loan>(Loan, "Loan", (SaveLocation)0, true);
		}

		internal void Load()
		{
			if (LNetworkUtils.IsHostOrServer)
			{
				Policy = SaveLoadHandler.LoadData<Policy>("Policy", (SaveLocation)0, tesinormed.FAndCDaveCo.Insurance.Policy.None, true);
				Claims = SaveLoadHandler.LoadData<Dictionary<int, Claim>>("Claims", (SaveLocation)0, new Dictionary<int, Claim>(), true);
				Loan = SaveLoadHandler.LoadData<Loan>("Loan", (SaveLocation)0, tesinormed.FAndCDaveCo.Bank.Loan.None, true);
			}
		}

		internal void Reset()
		{
			Policy = tesinormed.FAndCDaveCo.Insurance.Policy.None;
			Claims = new Dictionary<int, Claim>();
			Loan = tesinormed.FAndCDaveCo.Bank.Loan.None;
		}

		internal void MakeDirty()
		{
			_policy.MakeDirty();
			_claims.MakeDirty();
			_loan.MakeDirty();
		}

		[CompilerGenerated]
		protected virtual bool PrintMembers(StringBuilder builder)
		{
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("Policy = ");
			builder.Append(Policy);
			builder.Append(", Claims = ");
			builder.Append(Claims);
			builder.Append(", ClaimedClaims = ");
			builder.Append(ClaimedClaims);
			builder.Append(", UnclaimedClaims = ");
			builder.Append(UnclaimedClaims);
			builder.Append(", FractionalPremiumIncrease = ");
			builder.Append(FractionalPremiumIncrease.ToString());
			builder.Append(", TotalPremium = ");
			builder.Append(TotalPremium.ToString());
			builder.Append(", Loan = ");
			builder.Append(Loan);
			return true;
		}
	}
}
namespace tesinormed.FAndCDaveCo.Insurance
{
	[ES3Serializable]
	public record Claim
	{
		public int Value;

		public bool Claimed;

		public Claim(int value, bool claimed = false)
		{
			if (value < 0)
			{
				throw new ArgumentOutOfRangeException("value", "nonnegative number required");
			}
			Value = value;
			Claimed = claimed;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Claim { ");
			stringBuilder.Append(string.Format("{0} = {1}, ", "Value", Value));
			stringBuilder.Append(string.Format("{0} = {1}", "Claimed", Claimed));
			stringBuilder.Append(" }");
			return stringBuilder.ToString();
		}
	}
	[ES3Serializable]
	public record Policy
	{
		[ES3NonSerializable]
		public int BasePremium => Tier switch
		{
			PolicyTier.HighDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.EconomicBasePremium)), 
			PolicyTier.LowDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.StandardBasePremium)), 
			PolicyTier.NoDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.BespokeBasePremium)), 
			_ => 0, 
		};

		[ES3NonSerializable]
		public double DeductiblePercent => Tier switch
		{
			PolicyTier.HighDeductible => SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.EconomicDeductible), 
			PolicyTier.LowDeductible => SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.StandardDeductible), 
			_ => 0.0, 
		};

		[ES3NonSerializable]
		public int DeductibleMinimum => Tier switch
		{
			PolicyTier.HighDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.EconomicDeductibleMinimum)), 
			PolicyTier.LowDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.StandardDeductibleMinimum)), 
			_ => 0, 
		};

		[ES3NonSerializable]
		public int DeductibleMaximum => Tier switch
		{
			PolicyTier.HighDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.EconomicDeductibleMaximum)), 
			PolicyTier.LowDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.StandardDeductibleMaximum)), 
			_ => 0, 
		};

		[ES3NonSerializable]
		public static readonly Policy None = new Policy(PolicyTier.None, 0);

		public PolicyTier Tier;

		public int Coverage;

		public Policy(PolicyTier tier, int coverage)
		{
			if (coverage < 0)
			{
				throw new ArgumentOutOfRangeException("coverage", "nonnegative number required");
			}
			Tier = tier;
			Coverage = coverage;
		}

		public int CalculatePayout(int value)
		{
			if (value < 0)
			{
				throw new ArgumentOutOfRangeException("value", "nonnegative number required");
			}
			return Math.Min(value, Coverage);
		}

		public int CalculateDeductible(int value)
		{
			if (value < 0)
			{
				throw new ArgumentOutOfRangeException("value", "nonnegative number required");
			}
			return Math.Clamp((int)Math.Floor((double)CalculatePayout(value) * DeductiblePercent), DeductibleMinimum, DeductibleMaximum);
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Policy { ");
			stringBuilder.Append(string.Format("{0} = {1}, ", "Tier", Tier));
			stringBuilder.Append(string.Format("{0} = {1}", "Coverage", Coverage));
			stringBuilder.Append(" }");
			return stringBuilder.ToString();
		}

		[CompilerGenerated]
		protected virtual bool PrintMembers(StringBuilder builder)
		{
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("Tier = ");
			builder.Append(Tier.ToString());
			builder.Append(", Coverage = ");
			builder.Append(Coverage.ToString());
			builder.Append(", BasePremium = ");
			builder.Append(BasePremium.ToString());
			builder.Append(", DeductiblePercent = ");
			builder.Append(DeductiblePercent.ToString());
			builder.Append(", DeductibleMinimum = ");
			builder.Append(DeductibleMinimum.ToString());
			builder.Append(", DeductibleMaximum = ");
			builder.Append(DeductibleMaximum.ToString());
			return true;
		}

		[CompilerGenerated]
		protected Policy(Policy original)
		{
			Tier = original.Tier;
			Coverage = original.Coverage;
		}
	}
	public static class PolicyExtensions
	{
		public static Policy CreatePolicy(this PolicyTier policyTier, int coverage)
		{
			return new Policy(policyTier, coverage);
		}
	}
	public enum PolicyTier : byte
	{
		None,
		HighDeductible,
		LowDeductible,
		NoDeductible
	}
	public static class PolicyTierExtensions
	{
		public static string ToFriendlyString(this PolicyTier policyTier)
		{
			return policyTier switch
			{
				PolicyTier.HighDeductible => "Economic", 
				PolicyTier.LowDeductible => "Standard", 
				PolicyTier.NoDeductible => "Bespoke", 
				PolicyTier.None => "No Policy?", 
				_ => throw new ArgumentOutOfRangeException("policyTier", $"unexpected value: {policyTier}"), 
			};
		}
	}
}
namespace tesinormed.FAndCDaveCo.Insurance.UI
{
	public class PolicyClaimTerminal : InteractiveTerminalApplication
	{
		protected override string Title => "F&C Dave Co. Insurance: Make a claim";

		private CursorElement CreateCursorElement(int day, Claim claim)
		{
			Claim claim2 = claim;
			return CursorElement.Create($"Day {day}: ${claim2.Value}", "", (Action)delegate
			{
				ConfirmClaim(day, claim2);
			}, (Func<CursorElement, bool>)((CursorElement _) => true), false);
		}

		public override void Initialization()
		{
			if (Plugin.Instance.State.Policy.Tier == PolicyTier.None)
			{
				LockedNotification((ITextElement)TextElement.Create("You do not have an active insurance policy."));
				return;
			}
			if (Plugin.Instance.State.UnclaimedClaims.Count == 0)
			{
				LockedNotification((ITextElement)TextElement.Create("You do not have any claims."));
				return;
			}
			CursorElement[] seed = Array.Empty<CursorElement>();
			seed = Plugin.Instance.State.UnclaimedClaims.Aggregate<KeyValuePair<int, Claim>, CursorElement[]>(seed, delegate(CursorElement[] current, KeyValuePair<int, Claim> pair)
			{
				int num = 0;
				CursorElement[] array = (CursorElement[])(object)new CursorElement[1 + current.Length];
				ReadOnlySpan<CursorElement> readOnlySpan = new ReadOnlySpan<CursorElement>(current);
				readOnlySpan.CopyTo(new Span<CursorElement>(array).Slice(num, readOnlySpan.Length));
				num += readOnlySpan.Length;
				array[num] = CreateCursorElement(pair.Key, pair.Value);
				num++;
				return array;
			});
			(base.MainScreen, base.MainCursorMenu) = Selection("Select a pending claim.", seed);
		}

		private void ConfirmClaim(int day, Claim claim)
		{
			Claim claim2 = claim;
			int deductible = Plugin.Instance.State.Policy.CalculateDeductible(claim2.Value);
			int payout = Plugin.Instance.State.Policy.CalculatePayout(claim2.Value);
			Confirm(delegate
			{
				ProcessClaim(day, deductible, payout, claim2);
			}, delegate
			{
				ConfirmDeleteClaim(day);
			}, (ITextElement[])(object)new ITextElement[2]
			{
				(ITextElement)TextElement.Create($"Are you sure you want to confirm this claim? You will need to pay a deductible of ${deductible}."),
				(ITextElement)TextElement.Create($"You will be given back ${payout}.")
			});
		}

		private void ConfirmDeleteClaim(int day)
		{
			Confirm(delegate
			{
				DeleteClaim(day);
			}, base.PreviousMainScreenAction, (ITextElement)TextElement.Create($"Do you want to delete this claim for day {day}?"));
		}

		private void DeleteClaim(int day)
		{
			Plugin.Instance.State.MutateClaims(delegate(Dictionary<int, Claim> claims)
			{
				claims.Remove(day);
			});
			LockedNotification((ITextElement)TextElement.Create($"The claim for day {day} has been deleted."));
		}

		private void ProcessClaim(int day, int deductible, int payout, Claim claim)
		{
			Claim claim2 = claim;
			if (((TerminalApplication)this).terminal.groupCredits < deductible)
			{
				Notification(base.PreviousMainScreenAction, (ITextElement)TextElement.Create("You do not have enough credits to continue with this claim."));
				return;
			}
			Plugin.Instance.State.MutateClaims(delegate(Dictionary<int, Claim> claims)
			{
				claims[day] = new Claim(claim2.Value, claimed: true);
			});
			CreditEvents.DeductGroupCredits.SendServer(deductible);
			CreditEvents.SpawnGoldBar.SendServer(payout);
			LockedNotification((ITextElement)TextElement.Create($"You have been given a gold bar worth ${payout}."), (ITextElement)TextElement.Create($"You have been charged ${deductible}."), (ITextElement)TextElement.Create($"Your premiums have increased by {(int)(Plugin.Instance.State.FractionalPremiumIncrease * 100.0)}%."));
		}
	}
	public class PolicyInformationTerminal : TerminalApplication
	{
		public override void Initialization()
		{
			List<ITextElement> list = new List<ITextElement>();
			if (Plugin.Instance.State.Policy.Tier == PolicyTier.None)
			{
				list.Add((ITextElement)(object)TextElement.Create("You do not currently have an insurance policy."));
			}
			else
			{
				list.Add((ITextElement)(object)TextElement.Create($"You currently have the {Plugin.Instance.State.Policy.Tier.ToFriendlyString()} policy (${Plugin.Instance.State.Policy.Coverage})."));
				list.Add((ITextElement)(object)TextElement.Create($"You have made {Plugin.Instance.State.ClaimedClaims.Count} claim(s) recently (within {Plugin.Instance.Config.ClaimRetentionDays.Value} days)."));
				list.Add((ITextElement)(object)((Plugin.Instance.State.FractionalPremiumIncrease == 0.0) ? TextElement.Create($"You pay ${Plugin.Instance.State.TotalPremium} per day.") : TextElement.Create($"You pay ${Plugin.Instance.State.TotalPremium} (+{(int)(Plugin.Instance.State.FractionalPremiumIncrease * 100.0)}%) per day.")));
				list.Add((ITextElement)(object)((Plugin.Instance.State.Policy.DeductiblePercent != 0.0) ? TextElement.Create($"Your deductible is currently {(int)(Plugin.Instance.State.Policy.DeductiblePercent * 100.0)}% (minimum: ${Plugin.Instance.State.Policy.DeductibleMinimum}, maximum: ${Plugin.Instance.State.Policy.DeductibleMaximum}).") : TextElement.Create("You do not pay deductibles.")));
			}
			BoxedScreen currentScreen = BoxedScreen.Create("F&C Dave Co. Insurance: Policy information", list.ToArray());
			((TerminalApplication)this).currentScreen = (IScreen)(object)currentScreen;
		}
	}
	public class PolicySelectTerminal : InteractiveTerminalApplication
	{
		protected override string Title => "F&C Dave Co. Insurance: Selection";

		private CursorElement CreatePolicyTierCursorElement(PolicyTier policyTier, string description)
		{
			return CursorElement.Create(policyTier.ToFriendlyString() + ": " + description, "", (Action)delegate
			{
				SelectCoverage(policyTier);
			}, (Func<CursorElement, bool>)((CursorElement _) => true), false);
		}

		private CursorElement CreateCoverageCursorElement(Policy policy)
		{
			Policy policy2 = policy;
			return CursorElement.Create($"${policy2.Coverage}", "", (Action)delegate
			{
				ConfirmEverything(policy2);
			}, (Func<CursorElement, bool>)((CursorElement _) => ((TerminalApplication)this).terminal.groupCredits >= Plugin.Instance.State.CalculateTotalPremium(policy2)), true);
		}

		public override void Initialization()
		{
			if (StartOfRound.Instance.isChallengeFile)
			{
				LockedNotification((ITextElement)TextElement.Create("You cannot get an insurance policy while doing a challenge moon."));
				Plugin.Logger.LogDebug((object)"local player tried to get an insurance policy while doing a challenge moon");
				return;
			}
			(base.MainScreen, base.MainCursorMenu) = Selection("Select a policy tier.", CreatePolicyTierCursorElement(PolicyTier.HighDeductible, "High deductible, low premium"), CreatePolicyTierCursorElement(PolicyTier.LowDeductible, "Low deductible, medium premium"), CreatePolicyTierCursorElement(PolicyTier.NoDeductible, "No deductible, high premium"), CursorElement.Create("Cancel policy", "", (Action)ConfirmCancelPolicy, (Func<CursorElement, bool>)((CursorElement _) => Plugin.Instance.State.Policy.Tier != PolicyTier.None), true));
		}

		private void ConfirmCancelPolicy()
		{
			if (Plugin.Instance.State.Policy.Tier == PolicyTier.None)
			{
				Notification(base.PreviousScreenAction, (ITextElement)TextElement.Create("You do not currently have a policy."));
			}
			else
			{
				Confirm(CancelPolicy, base.PreviousScreenAction, (ITextElement)TextElement.Create("Are you sure you want to cancel your current policy?"), (ITextElement)TextElement.Create($"Your current policy is {Plugin.Instance.State.Policy.Tier.ToFriendlyString()} (${Plugin.Instance.State.Policy.Coverage})."));
			}
		}

		private void CancelPolicy()
		{
			Plugin.Instance.State.Policy = Policy.None;
			LockedNotification((ITextElement)TextElement.Create("Your policy has been canceled."));
		}

		private void SelectCoverage(PolicyTier policyTier)
		{
			SelectionWithBack("Select the coverage amount.", base.PreviousMainScreenAction, CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption00))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption01))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption02))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption03))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption04))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption05))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption06))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption07))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption08))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption09))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.CoverageOption10))));
		}

		private void ConfirmEverything(Policy policy)
		{
			Policy policy2 = policy;
			if (policy2 == Plugin.Instance.State.Policy)
			{
				Notification(base.PreviousScreenAction, (ITextElement)TextElement.Create("You already have this policy."));
				return;
			}
			if (((TerminalApplication)this).terminal.groupCredits < Plugin.Instance.State.CalculateTotalPremium(policy2))
			{
				Notification(base.PreviousScreenAction, (ITextElement)TextElement.Create("You do not have enough credits to purchase this policy."));
				return;
			}
			Confirm(delegate
			{
				SetEverything(policy2, Plugin.Instance.State.CalculateTotalPremium(policy2));
			}, base.PreviousScreenAction, (ITextElement)TextElement.Create($"Are you sure you want to pick {policy2.Tier.ToFriendlyString()} (${policy2.Coverage})?"), (ITextElement)TextElement.Create((policy2.DeductiblePercent == 0.0) ? "This policy has no deductibles." : $"The deductibles are {(int)(policy2.DeductiblePercent * 100.0)}%, with a minimum of ${policy2.DeductibleMinimum} and a maximum of ${policy2.DeductibleMaximum}."), (ITextElement)TextElement.Create($"You will be charged ${Plugin.Instance.State.CalculateTotalPremium(policy2)}."));
		}

		private void SetEverything(Policy policy, int cost)
		{
			Plugin.Instance.State.Policy = policy;
			CreditEvents.DeductGroupCredits.SendServer(cost);
			LockedNotification((ITextElement)TextElement.Create($"Your policy has been updated to {policy.Tier.ToFriendlyString()} (${policy.Coverage})."), (ITextElement)TextElement.Create($"You have been charged ${cost}."));
		}
	}
	internal static class PolicyTerminal
	{
		internal const string Title = "F&C Dave Co. Insurance";
	}
}
namespace tesinormed.FAndCDaveCo.Extensions
{
	public static class DictionaryExtensions
	{
		public static Dictionary<TKey, TValue> ToDictionary<TKey, TValue>(this IEnumerable<KeyValuePair<TKey, TValue>> dictionary)
		{
			return dictionary.ToDictionary<KeyValuePair<TKey, TValue>, TKey, TValue>((KeyValuePair<TKey, TValue> keyValuePair) => keyValuePair.Key, (KeyValuePair<TKey, TValue> keyValuePair) => keyValuePair.Value);
		}
	}
	public abstract class InteractiveTerminalApplication : InteractiveTerminalApplication
	{
		protected abstract string Title { get; }

		protected IScreen MainScreen { get; set; }

		protected CursorMenu MainCursorMenu { get; set; }

		private IScreen? PreviousScreen { get; set; }

		private CursorMenu? PreviousCursorMenu { get; set; }

		protected Action PreviousMainScreenAction => delegate
		{
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen(MainScreen, MainCursorMenu, true);
		};

		protected Action PreviousScreenAction => delegate
		{
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen(PreviousScreen ?? throw new InvalidOperationException("no previous screen"), PreviousCursorMenu ?? throw new InvalidOperationException("no previous cursor menu"), true);
		};

		protected override void SwitchScreen(IScreen screen, CursorMenu cursorMenu, bool previous)
		{
			PreviousScreen = ((TerminalApplication)this).currentScreen;
			PreviousCursorMenu = ((BaseInteractiveApplication<CursorMenu, CursorElement>)this).currentCursorMenu;
			((BaseInteractiveApplication<CursorMenu, CursorElement>)this).SwitchScreen(screen, cursorMenu, previous);
		}

		protected (IScreen, CursorMenu) Selection(string prompt, params CursorElement[] options)
		{
			CursorMenu val = CursorMenu.Create(0, '>', options, (Func<CursorElement, CursorElement, int>[])null);
			ITextElement[] array = (ITextElement[])(object)new ITextElement[3]
			{
				(ITextElement)TextElement.Create(prompt),
				(ITextElement)TextElement.Create(" "),
				(ITextElement)val
			};
			BoxedScreen val2 = BoxedScreen.Create(Title, array);
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen((IScreen)(object)val2, val, false);
			return ((IScreen)(object)val2, val);
		}

		protected void SelectionWithBack(string prompt, Action backAction, params CursorElement[] options)
		{
			CursorElement[] array = options;
			int num = 0;
			CursorElement[] array2 = (CursorElement[])(object)new CursorElement[1 + array.Length];
			ReadOnlySpan<CursorElement> readOnlySpan = new ReadOnlySpan<CursorElement>(array);
			readOnlySpan.CopyTo(new Span<CursorElement>(array2).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			array2[num] = CursorElement.Create("Back", "", backAction, (Func<CursorElement, bool>)((CursorElement _) => true), false);
			num++;
			options = array2;
			CursorMenu val = CursorMenu.Create(0, '>', options, (Func<CursorElement, CursorElement, int>[])null);
			ITextElement[] array3 = (ITextElement[])(object)new ITextElement[3]
			{
				(ITextElement)TextElement.Create(prompt),
				(ITextElement)TextElement.Create(" "),
				(ITextElement)val
			};
			BoxedScreen val2 = BoxedScreen.Create(Title, array3);
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen((IScreen)(object)val2, val, false);
		}

		protected void Confirm(Action confirmAction, params ITextElement[] text)
		{
			CursorMenu val = CursorMenu.Create(0, '>', (CursorElement[])(object)new CursorElement[1] { CursorElement.Create("Confirm", "", confirmAction, (Func<CursorElement, bool>)null, true) }, (Func<CursorElement, CursorElement, int>[])null);
			int num = 0;
			ITextElement[] array = (ITextElement[])(object)new ITextElement[2 + text.Length];
			ReadOnlySpan<ITextElement> readOnlySpan = new ReadOnlySpan<ITextElement>(text);
			readOnlySpan.CopyTo(new Span<ITextElement>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			array[num] = (ITextElement)(object)TextElement.Create(" ");
			num++;
			array[num] = (ITextElement)(object)val;
			num++;
			ITextElement[] array2 = array;
			BoxedScreen val2 = BoxedScreen.Create(Title, array2);
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen((IScreen)(object)val2, val, false);
		}

		protected void Confirm(Action confirmAction, Action declineAction, params ITextElement[] text)
		{
			CursorMenu val = CursorMenu.Create(0, '>', (CursorElement[])(object)new CursorElement[2]
			{
				CursorElement.Create("Confirm", "", confirmAction, (Func<CursorElement, bool>)null, true),
				CursorElement.Create("Decline", "", declineAction, (Func<CursorElement, bool>)null, true)
			}, (Func<CursorElement, CursorElement, int>[])null);
			int num = 0;
			ITextElement[] array = (ITextElement[])(object)new ITextElement[2 + text.Length];
			ReadOnlySpan<ITextElement> readOnlySpan = new ReadOnlySpan<ITextElement>(text);
			readOnlySpan.CopyTo(new Span<ITextElement>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			array[num] = (ITextElement)(object)TextElement.Create(" ");
			num++;
			array[num] = (ITextElement)(object)val;
			num++;
			ITextElement[] array2 = array;
			BoxedScreen val2 = BoxedScreen.Create(Title, array2);
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen((IScreen)(object)val2, val, false);
		}

		protected void Notification(Action backAction, params ITextElement[] text)
		{
			CursorMenu val = CursorMenu.Create(0, '>', (CursorElement[])(object)new CursorElement[1] { CursorElement.Create("Back", "", backAction, (Func<CursorElement, bool>)null, true) }, (Func<CursorElement, CursorElement, int>[])null);
			int num = 0;
			ITextElement[] array = (ITextElement[])(object)new ITextElement[2 + text.Length];
			ReadOnlySpan<ITextElement> readOnlySpan = new ReadOnlySpan<ITextElement>(text);
			readOnlySpan.CopyTo(new Span<ITextElement>(array).Slice(num, readOnlySpan.Length));
			num += readOnlySpan.Length;
			array[num] = (ITextElement)(object)TextElement.Create(" ");
			num++;
			array[num] = (ITextElement)(object)val;
			num++;
			ITextElement[] array2 = array;
			BoxedScreen val2 = BoxedScreen.Create(Title, array2);
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen((IScreen)(object)val2, val, false);
		}

		protected void LockedNotification(params ITextElement[] text)
		{
			BoxedScreen val = BoxedScreen.Create(Title, text);
			CursorMenu val2 = CursorMenu.Create(0, '>', (CursorElement[])null, (Func<CursorElement, CursorElement, int>[])null);
			((BaseInteractiveApplication<CursorMenu, CursorElement>)(object)this).SwitchScreen((IScreen)(object)val, val2, false);
		}
	}
	public static class InteractiveTerminalManager
	{
		public static void RegisterApplication<T>(params string[] commands) where T : TerminalApplication, new()
		{
			for (int i = 0; i < commands.Length; i++)
			{
				InteractiveTerminalManager.RegisterApplication<T>(commands[i]);
			}
		}
	}
	public abstract class TerminalApplication : TerminalApplication
	{
		protected override string GetApplicationText()
		{
			return ((ITextElement)base.currentScreen).GetText(51);
		}

		protected override Action PreviousScreen()
		{
			return delegate
			{
			};
		}
	}
}
namespace tesinormed.FAndCDaveCo.Bank
{
	[ES3Serializable]
	public record Loan
	{
		[ES3NonSerializable]
		public int DaysSinceIssuance => StartOfRound.Instance.gameStats.daysSpent - IssuanceDate;

		[ES3NonSerializable]
		public int Interest => CalculateInterest(Principal);

		[ES3NonSerializable]
		public int Total => Principal + Interest;

		[ES3NonSerializable]
		public int AmountUnpaid => Total - AmountPaid;

		[ES3NonSerializable]
		public static readonly Loan None = new Loan(0, 0);

		public int IssuanceDate;

		public int Principal;

		public int AmountPaid;

		public static int CalculateInterest(int principal)
		{
			return (int)((double)principal * SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.InterestAmount));
		}

		public Loan(int issuanceDate, int principal, int amountPaid = 0)
		{
			if (issuanceDate < 0)
			{
				throw new ArgumentOutOfRangeException("issuanceDate", "nonnegative number required");
			}
			if (principal < 0)
			{
				throw new ArgumentOutOfRangeException("principal", "nonnegative number required");
			}
			if (amountPaid < 0)
			{
				throw new ArgumentOutOfRangeException("amountPaid", "nonnegative number required");
			}
			IssuanceDate = issuanceDate;
			Principal = principal;
			AmountPaid = amountPaid;
		}

		public override string ToString()
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("Loan { ");
			stringBuilder.Append(string.Format("{0} = {1}, ", "IssuanceDate", IssuanceDate));
			stringBuilder.Append(string.Format("{0} = {1}, ", "Principal", Principal));
			stringBuilder.Append(string.Format("{0} = {1}", "AmountPaid", AmountPaid));
			stringBuilder.Append(" }");
			return stringBuilder.ToString();
		}

		[CompilerGenerated]
		protected virtual bool PrintMembers(StringBuilder builder)
		{
			RuntimeHelpers.EnsureSufficientExecutionStack();
			builder.Append("IssuanceDate = ");
			builder.Append(IssuanceDate.ToString());
			builder.Append(", DaysSinceIssuance = ");
			builder.Append(DaysSinceIssuance.ToString());
			builder.Append(", Principal = ");
			builder.Append(Principal.ToString());
			builder.Append(", Interest = ");
			builder.Append(Interest.ToString());
			builder.Append(", Total = ");
			builder.Append(Total.ToString());
			builder.Append(", AmountPaid = ");
			builder.Append(AmountPaid.ToString());
			builder.Append(", AmountUnpaid = ");
			builder.Append(AmountUnpaid.ToString());
			return true;
		}

		[CompilerGenerated]
		protected Loan(Loan original)
		{
			IssuanceDate = original.IssuanceDate;
			Principal = original.Principal;
			AmountPaid = original.AmountPaid;
		}
	}
}
namespace tesinormed.FAndCDaveCo.Bank.UI
{
	public class BankLoanGetTerminal : InteractiveTerminalApplication
	{
		protected override string Title => "F&C Dave Co. Bank: Get a loan";

		public override void Initialization()
		{
			if (!StartOfRound.Instance.inShipPhase || !GameNetworkManager.Instance.localPlayerController.isInHangarShipRoom)
			{
				LockedNotification((ITextElement)TextElement.Create("You can only get a loan while you are in orbit."));
				Plugin.Logger.LogDebug((object)"local player tried to get a loan when not in orbit");
				return;
			}
			if (StartOfRound.Instance.isChallengeFile)
			{
				LockedNotification((ITextElement)TextElement.Create("You cannot get a loan while doing a challenge moon."));
				Plugin.Logger.LogDebug((object)"local player tried to get a loan while doing a challenge moon");
				return;
			}
			if (Plugin.Instance.State.Loan.Principal != 0)
			{
				LockedNotification((ITextElement)TextElement.Create("You can only have one loan at a time."));
				Plugin.Logger.LogDebug((object)"local player tried to get a loan when there already was a loan");
				return;
			}
			if (TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled <= 0)
			{
				LockedNotification((ITextElement)TextElement.Create("Your quota is already fulfilled."));
				Plugin.Logger.LogDebug((object)"local player tried to get a loan when quota was already fulfilled");
				return;
			}
			int principal = TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled;
			Confirm(delegate
			{
				GetLoan(principal);
			}, (ITextElement)TextElement.Create($"Are you sure you want to get a loan for ${principal}? The total cost will be ${principal + Loan.CalculateInterest(principal)}."));
		}

		private void GetLoan(int principal)
		{
			CreditEvents.TakeOutLoan.InvokeServer();
			LockedNotification((ITextElement)TextElement.Create($"You have successfully taken out a loan for ${principal}."));
		}
	}
	public class BankLoanInformationTerminal : TerminalApplication
	{
		public override void Initialization()
		{
			List<ITextElement> list = new List<ITextElement>();
			if (Plugin.Instance.State.Loan.Principal == 0)
			{
				list.Add((ITextElement)(object)TextElement.Create("You do not currently have an unpaid loan."));
			}
			else
			{
				list.Add((ITextElement)(object)TextElement.Create($"You currently have an unpaid loan from {Plugin.Instance.State.Loan.DaysSinceIssuance} day(s) ago (day {Plugin.Instance.State.Loan.IssuanceDate})."));
				list.Add((ITextElement)(object)TextElement.Create($"The loan is for ${Plugin.Instance.State.Loan.Principal} with ${Plugin.Instance.State.Loan.Interest} added as interest."));
				list.Add((ITextElement)(object)TextElement.Create($"Amount paid: ${Plugin.Instance.State.Loan.AmountPaid}, amount left: ${Plugin.Instance.State.Loan.AmountUnpaid}, total: ${Plugin.Instance.State.Loan.Total}."));
				if (Plugin.Instance.State.Loan.DaysSinceIssuance >= SyncedEntry<int>.op_Implicit(Plugin.Instance.Config.PenaltyStartDaysFromIssuance))
				{
					list.Add((ITextElement)(object)TextElement.Create($"{(int)(SyncedEntry<double>.op_Implicit(Plugin.Instance.Config.PenaltyAmount) * 100.0)}% of your credits are currently being garnished each day."));
				}
			}
			BoxedScreen currentScreen = BoxedScreen.Create("F&C Dave Co. Bank: Loan information", list.ToArray());
			((TerminalApplication)this).currentScreen = (IScreen)(object)currentScreen;
		}
	}
	public class BankLoanPaymentTerminal : InteractiveTerminalApplication
	{
		protected override string Title => "F&C Dave Co. Bank: Submit loan payment";

		private CursorElement CreateCursorElement(double amount)
		{
			int cost = Math.Min((int)((double)Plugin.Instance.State.Loan.Total * amount), Plugin.Instance.State.Loan.AmountUnpaid);
			return CursorElement.Create($"{(int)(amount * 100.0)}% (${cost})", "", (Action)delegate
			{
				ConfirmPayLoan(cost);
			}, (Func<CursorElement, bool>)((CursorElement _) => ((TerminalApplication)this).terminal.groupCredits >= cost), true);
		}

		public override void Initialization()
		{
			if (Plugin.Instance.State.Loan.Principal == 0)
			{
				LockedNotification((ITextElement)TextElement.Create("You can only submit a loan payment if you have a loan."));
				Plugin.Logger.LogDebug((object)"local player tried to submit a loan payment when there was no loan");
				return;
			}
			(base.MainScreen, base.MainCursorMenu) = Selection("Pick an amount to pay towards the loan.", CreateCursorElement(0.1), CreateCursorElement(0.25), CreateCursorElement(0.5), CreateCursorElement(0.75), CreateCursorElement(1.0));
		}

		private void ConfirmPayLoan(int amount)
		{
			if (((TerminalApplication)this).terminal.groupCredits < amount)
			{
				Notification(base.PreviousScreenAction, (ITextElement)TextElement.Create($"You do not have enough credits to submit a payment of ${amount} for the loan."));
				return;
			}
			Confirm(delegate
			{
				PayLoan(amount);
			}, base.PreviousScreenAction, (ITextElement)TextElement.Create($"Are you sure you want to pay ${amount}?"));
		}

		private void PayLoan(int amount)
		{
			CreditEvents.DeductGroupCredits.SendServer(amount);
			if (Plugin.Instance.State.Loan.AmountUnpaid - amount == 0)
			{
				Plugin.Instance.State.Loan = Loan.None;
				Plugin.Logger.LogDebug((object)"loan paid off fully; removed");
				LockedNotification((ITextElement)TextElement.Create("You have paid off your loan fully."));
				return;
			}
			Plugin.Instance.State.MutateLoan(delegate(Loan loan)
			{
				loan.AmountPaid += amount;
			});
			Plugin.Logger.LogDebug((object)$"paid {amount} towards the current loan");
			LockedNotification((ITextElement)TextElement.Create($"You have paid ${amount}; ${Plugin.Instance.State.Loan.AmountUnpaid} must still be paid."));
		}
	}
	internal static class BankTerminal
	{
		internal const string Title = "F&C Dave Co. Bank";
	}
}
namespace System.Runtime.CompilerServices
{
	[ExcludeFromCodeCoverage]
	[DebuggerNonUserCode]
	internal static class IsExternalInit
	{
	}
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}