using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Attributes;
using LethalModDataLib.Base;
using LethalModDataLib.Events;
using LethalNetworkAPI;
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: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("tesinormed.FAndCDaveCo")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.4.2.0")]
[assembly: AssemblyInformationalVersion("1.4.2+d24323540fc75b59040a1f529092f9be9d56ec09")]
[assembly: AssemblyProduct("FAndCDaveCo")]
[assembly: AssemblyTitle("tesinormed.FAndCDaveCo")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.4.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Microsoft.CodeAnalysis.Embedded]
[AttributeUsage(AttributeTargets.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", "1.4.2")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency("com.sigurd.csync", "5.0.0")]
[LobbyCompatibility(/*Could not decode attribute arguments.*/)]
public class Plugin : BaseUnityPlugin
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static Action<Policy> <>9__32_0;
public static Action<Dictionary<int, PolicyClaim>> <>9__32_1;
public static Action<Loan> <>9__32_2;
public static PostSaveGameEventHandler <>9__33_0;
public static PostLoadGameEventHandler <>9__33_1;
public static PostDeleteSaveEventHandler <>9__33_2;
public static PostResetSavedGameValuesEventHandler <>9__33_3;
internal void <InitNetworkVariables>b__32_0(Policy data)
{
PolicyState.Policy = data;
Logger.LogDebug((object)$"synced policy state policy {data}");
}
internal void <InitNetworkVariables>b__32_1(Dictionary<int, PolicyClaim> data)
{
PolicyState.Claims = data;
Logger.LogDebug((object)("synced policy state claims [" + string.Join(", ", data) + "]"));
}
internal void <InitNetworkVariables>b__32_2(Loan data)
{
BankState.Loan = data;
Logger.LogDebug((object)$"synced bank state loan {data}");
}
internal void <InitState>b__33_0(bool _, string _)
{
((ModDataContainer)PolicyState).Save();
((ModDataContainer)BankState).Save();
}
internal void <InitState>b__33_1(bool _, string _)
{
((ModDataContainer)PolicyState).Load();
((ModDataContainer)BankState).Load();
}
internal void <InitState>b__33_2(string _)
{
PolicyState.ResetAndSync();
BankState.ResetAndSync();
HUDManagerEvents.QueuedHudTips.Clear();
}
internal void <InitState>b__33_3()
{
PolicyState.ResetAndSync();
BankState.ResetAndSync();
HUDManagerEvents.QueuedHudTips.Clear();
((ModDataContainer)PolicyState).Save();
((ModDataContainer)BankState).Save();
}
}
public static readonly LethalNetworkVariable<Policy> SyncedPolicy = new LethalNetworkVariable<Policy>("Policy");
public static readonly LethalNetworkVariable<Dictionary<int, PolicyClaim>> SyncedClaims = new LethalNetworkVariable<Dictionary<int, PolicyClaim>>("Claims");
public static readonly LethalNetworkVariable<Loan> SyncedLoan = new LethalNetworkVariable<Loan>("Loan");
internal static ManualLogSource Logger { get; private set; } = null;
public static Plugin Instance { get; private set; } = null;
internal static Config Config { get; private set; } = null;
internal static Harmony? Harmony { get; set; }
public static Terminal Terminal { get; set; } = null;
public static PolicyState PolicyState { get; private set; } = null;
public static BankState BankState { get; private set; } = null;
private void Awake()
{
Logger = ((BaseUnityPlugin)this).Logger;
Instance = this;
Config = new Config(((BaseUnityPlugin)this).Config);
InitNetworkVariables();
InitState();
RegisterTerminal();
NetworkVariableEvents.Init();
CreditEvents.Init();
HUDManagerEvents.Init();
Patch();
Logger.LogInfo((object)"tesinormed.FAndCDaveCo (FAndCDaveCo) version 1.4.2 loaded");
}
private void InitNetworkVariables()
{
SyncedPolicy.OnValueChanged += delegate(Policy data)
{
PolicyState.Policy = data;
Logger.LogDebug((object)$"synced policy state policy {data}");
};
SyncedClaims.OnValueChanged += delegate(Dictionary<int, PolicyClaim> data)
{
PolicyState.Claims = data;
Logger.LogDebug((object)("synced policy state claims [" + string.Join(", ", data) + "]"));
};
SyncedLoan.OnValueChanged += delegate(Loan data)
{
BankState.Loan = data;
Logger.LogDebug((object)$"synced bank state loan {data}");
};
}
private void InitState()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Expected O, but got Unknown
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Expected O, but got Unknown
PolicyState = new PolicyState();
BankState = new BankState();
object obj = <>c.<>9__33_0;
if (obj == null)
{
PostSaveGameEventHandler val = delegate
{
((ModDataContainer)PolicyState).Save();
((ModDataContainer)BankState).Save();
};
<>c.<>9__33_0 = val;
obj = (object)val;
}
SaveLoadEvents.PostSaveGameEvent += (PostSaveGameEventHandler)obj;
object obj2 = <>c.<>9__33_1;
if (obj2 == null)
{
PostLoadGameEventHandler val2 = delegate
{
((ModDataContainer)PolicyState).Load();
((ModDataContainer)BankState).Load();
};
<>c.<>9__33_1 = val2;
obj2 = (object)val2;
}
SaveLoadEvents.PostLoadGameEvent += (PostLoadGameEventHandler)obj2;
object obj3 = <>c.<>9__33_2;
if (obj3 == null)
{
PostDeleteSaveEventHandler val3 = delegate
{
PolicyState.ResetAndSync();
BankState.ResetAndSync();
HUDManagerEvents.QueuedHudTips.Clear();
};
<>c.<>9__33_2 = val3;
obj3 = (object)val3;
}
SaveLoadEvents.PostDeleteSaveEvent += (PostDeleteSaveEventHandler)obj3;
object obj4 = <>c.<>9__33_3;
if (obj4 == null)
{
PostResetSavedGameValuesEventHandler val4 = delegate
{
PolicyState.ResetAndSync();
BankState.ResetAndSync();
HUDManagerEvents.QueuedHudTips.Clear();
((ModDataContainer)PolicyState).Save();
((ModDataContainer)BankState).Save();
};
<>c.<>9__33_3 = val4;
obj4 = (object)val4;
}
SaveLoadEvents.PostResetSavedGameValuesEvent += (PostResetSavedGameValuesEventHandler)obj4;
}
private void RegisterTerminal()
{
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" });
}
internal static void Patch()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Expected O, but got Unknown
if (Harmony == null)
{
Harmony = new Harmony("tesinormed.FAndCDaveCo");
}
Logger.LogDebug((object)"patching in progress");
Harmony.PatchAll(Assembly.GetExecutingAssembly());
Logger.LogDebug((object)"finished patching");
}
internal static void Unpatch()
{
Logger.LogDebug((object)"unpatching in progress");
Harmony? harmony = Harmony;
if (harmony != null)
{
harmony.UnpatchSelf();
}
Logger.LogDebug((object)"finished unpatching");
}
}
public static class MyPluginInfo
{
public const string PLUGIN_GUID = "tesinormed.FAndCDaveCo";
public const string PLUGIN_NAME = "FAndCDaveCo";
public const string PLUGIN_VERSION = "1.4.2";
}
}
namespace tesinormed.FAndCDaveCo.Patches
{
[HarmonyPatch(typeof(RoundManager), "DespawnPropsAtEndOfRound")]
public static class RoundManager_DespawnPropsAtEndOfRound_Patch
{
public static void Prefix(ref RoundManager __instance)
{
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
if (!((NetworkBehaviour)__instance).IsServer || !StartOfRound.Instance.allPlayersDead || Plugin.PolicyState.Policy.Tier == PolicyTier.None)
{
return;
}
int lootValue = (from grabbableObject in GameObject.Find("/Environment/HangarShip").GetComponentsInChildren<GrabbableObject>()
where grabbableObject.itemProperties.isScrap && !(grabbableObject is RagdollGrabbableObject)
select grabbableObject).Sum((GrabbableObject grabbableObject) => grabbableObject.scrapValue);
if (lootValue > 0)
{
Plugin.PolicyState.UpdateAndSyncClaims(delegate(Dictionary<int, PolicyClaim> claims)
{
claims[StartOfRound.Instance.gameStats.daysSpent - 1] = new PolicyClaim(lootValue);
});
Plugin.Logger.LogInfo((object)$"crew all dead, recording pending claim with value of {lootValue} for day {StartOfRound.Instance.gameStats.daysSpent - 1}");
new LethalServerEvent("ClaimAvailable", (Action<ulong>)null).InvokeAllClients(true);
}
}
}
[HarmonyPatch(typeof(StartOfRound), "EndOfGame")]
public static class StartOfRound_EndOfGame_Patch
{
public static void Prefix(ref StartOfRound __instance)
{
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
StartOfRound val = __instance;
if (val == null || !((NetworkBehaviour)val).IsServer || val.isChallengeFile)
{
return;
}
foreach (KeyValuePair<int, PolicyClaim> keyValuePair in Plugin.PolicyState.Claims.Where<KeyValuePair<int, PolicyClaim>>((KeyValuePair<int, PolicyClaim> pair) => StartOfRound.Instance.gameStats.daysSpent - pair.Key > SyncedEntry<int>.op_Implicit(Plugin.Config.ClaimRetentionDays)))
{
Plugin.PolicyState.UpdateAndSyncClaims(delegate(Dictionary<int, PolicyClaim> claims)
{
claims.Remove(keyValuePair.Key);
});
Plugin.Logger.LogInfo((object)$"deleted old claim from day {keyValuePair.Key}: {keyValuePair.Value}");
}
if (Plugin.PolicyState.Policy != Policy.None)
{
if (Plugin.Terminal.groupCredits >= Plugin.PolicyState.TotalPremium)
{
new LethalClientMessage<int>("DeductGroupCredits", (Action<int>)null, (Action<int, ulong>)null).SendServer(Plugin.PolicyState.TotalPremium);
new LethalServerMessage<int>("InsuranceRenewalSuccess", (Action<int, ulong>)null).SendAllClients(Plugin.PolicyState.TotalPremium, true);
Plugin.Logger.LogDebug((object)$"insurance successfully renewed with premium of {Plugin.PolicyState.TotalPremium}");
}
else
{
Plugin.PolicyState.SetAndSyncPolicy(Policy.None);
new LethalServerEvent("InsuranceRenewalFail", (Action<ulong>)null).InvokeAllClients(true);
Plugin.Logger.LogDebug((object)"insurance failed to renew");
}
}
if (Plugin.BankState.Loan.AmountUnpaid <= 0 || Plugin.BankState.Loan.DaysSinceIssuance < SyncedEntry<int>.op_Implicit(Plugin.Config.PenaltyStartDaysFromIssuance))
{
return;
}
int amountGarnished = Math.Min((int)((double)Plugin.Terminal.groupCredits * SyncedEntry<double>.op_Implicit(Plugin.Config.PenaltyAmount)), Plugin.BankState.Loan.AmountUnpaid);
new LethalClientMessage<int>("DeductGroupCredits", (Action<int>)null, (Action<int, ulong>)null).SendServer(amountGarnished);
Plugin.Logger.LogDebug((object)$"garnished ${amountGarnished} from group credits due to loan nonpayment");
if (Plugin.BankState.Loan.AmountUnpaid - amountGarnished == 0)
{
Plugin.BankState.SetAndSyncLoan(Loan.None);
Plugin.Logger.LogDebug((object)"loan fully paid off due to garnishment");
}
else
{
Plugin.BankState.UpdateAndSyncLoan(delegate(Loan loan)
{
loan.AmountPaid += amountGarnished;
});
Plugin.Logger.LogDebug((object)$"loan amount paid increased by {amountGarnished}");
}
new LethalServerMessage<int>("BankLoanCreditsGarnished", (Action<int, ulong>)null).SendAllClients(amountGarnished, true);
}
[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(PolicyState), "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))
{
new LethalServerEvent("RunQueuedHudTips", (Action<ulong>)null).InvokeAllClients(true);
}
}
}
[HarmonyPatch(typeof(Terminal), "Awake")]
public static class Terminal_Awake_Patch
{
public static void Postfix(ref Terminal __instance)
{
Plugin.Terminal = __instance;
}
}
}
namespace tesinormed.FAndCDaveCo.Network
{
public static class CreditEvents
{
public const string DeductGroupCreditsIdentifier = "DeductGroupCredits";
public const string SpawnGoldBarIdentifier = "SpawnGoldBar";
public const string SyncItemScrapValue = "SyncItemScrapValue";
public const string TakeOutLoan = "TakeOutLoan";
public static void Init()
{
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
new LethalServerMessage<int>("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");
}
});
new LethalServerMessage<int>("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_010a: 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)}");
new LethalServerMessage<Tuple<NetworkObjectReference, int>>("SyncItemScrapValue", (Action<Tuple<NetworkObjectReference, int>, ulong>)null).SendAllClients(new Tuple<NetworkObjectReference, int>(NetworkObjectReference.op_Implicit(val2.GetComponent<NetworkObject>()), value), true);
}
});
new LethalClientMessage<Tuple<NetworkObjectReference, int>>("SyncItemScrapValue", (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);
new LethalServerEvent("TakeOutLoan", (Action<ulong>)delegate
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
Loan loan = new Loan(StartOfRound.Instance.gameStats.daysSpent, TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled);
Plugin.BankState.SetAndSyncLoan(loan);
Plugin.Logger.LogDebug((object)$"took out a loan for {loan.Principal}");
TimeOfDay.Instance.quotaFulfilled = TimeOfDay.Instance.profitQuota;
new LethalServerEvent("TakeOutLoan", (Action<ulong>)null).InvokeAllClients(true);
});
new LethalClientEvent("TakeOutLoan", (Action)delegate
{
TimeOfDay.Instance.quotaFulfilled = TimeOfDay.Instance.profitQuota;
TimeOfDay.Instance.UpdateProfitQuotaCurrentTime();
StartOfRound.Instance.AutoSaveShipData();
}, (Action<ulong>)null);
}
}
public static class HUDManagerEvents
{
public const string InsuranceRenewalSuccessIdentifier = "InsuranceRenewalSuccess";
public const string InsuranceRenewalFailIdentifier = "InsuranceRenewalFail";
public const string InsuranceClaimAvailableIdentifier = "ClaimAvailable";
public const string BankLoanCreditsGarnishedIdentifier = "BankLoanCreditsGarnished";
public const string RunQueuedHudTipsIdentifier = "RunQueuedHudTips";
internal static readonly List<Action> QueuedHudTips = new List<Action>();
public static void Init()
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
new LethalClientMessage<int>("InsuranceRenewalSuccess", (Action<int>)delegate(int value)
{
QueuedHudTips.Add(delegate
{
HUDManager.Instance.DisplayTip("Insurance renewed", $"▮{value} has been deducted.", false, false, "LC_Tip1");
});
Plugin.Logger.LogDebug((object)"queued insurance renewal success on HUD");
}, (Action<int, ulong>)null);
new LethalClientEvent("InsuranceRenewalFail", (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);
new LethalClientEvent("ClaimAvailable", (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);
new LethalClientMessage<int>("BankLoanCreditsGarnished", (Action<int>)delegate(int value)
{
QueuedHudTips.Add(delegate
{
HUDManager.Instance.DisplayTip("Credits garnished", $"Due to loan nonpayment, {(int)(SyncedEntry<double>.op_Implicit(Plugin.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);
new LethalClientEvent("RunQueuedHudTips", (Action)delegate
{
((MonoBehaviour)HUDManager.Instance).StartCoroutine(RunQueuedHudTips());
}, (Action<ulong>)null);
}
private static IEnumerator RunQueuedHudTips()
{
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 static class NetworkVariableEvents
{
public const string UpdatePolicyIdentifier = "UpdatePolicy";
public const string UpdateClaimsIdentifier = "UpdateClaims";
public const string UpdateLoanIdentifier = "UpdateLoan";
public static void Init()
{
new LethalServerMessage<Policy>("UpdatePolicy", (Action<Policy, ulong>)delegate(Policy value, ulong _)
{
Plugin.SyncedPolicy.Value = value;
});
new LethalServerMessage<Dictionary<int, PolicyClaim>>("UpdateClaims", (Action<Dictionary<int, PolicyClaim>, ulong>)delegate(Dictionary<int, PolicyClaim> value, ulong _)
{
Plugin.SyncedClaims.Value = value;
});
new LethalServerMessage<Loan>("UpdateLoan", (Action<Loan, ulong>)delegate(Loan value, ulong _)
{
Plugin.SyncedLoan.Value = value;
});
}
}
}
namespace tesinormed.FAndCDaveCo.Insurance
{
[ES3Serializable]
public record Policy
{
[ES3NonSerializable]
public int BasePremium => Tier switch
{
PolicyTier.HighDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.EconomicBasePremium)),
PolicyTier.LowDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.StandardBasePremium)),
PolicyTier.NoDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.BespokeBasePremium)),
_ => 0,
};
[ES3NonSerializable]
public double DeductiblePercent => Tier switch
{
PolicyTier.HighDeductible => SyncedEntry<double>.op_Implicit(Plugin.Config.EconomicDeductible),
PolicyTier.LowDeductible => SyncedEntry<double>.op_Implicit(Plugin.Config.StandardDeductible),
_ => 0.0,
};
[ES3NonSerializable]
public int DeductibleMinimum => Tier switch
{
PolicyTier.HighDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.EconomicDeductibleMinimum)),
PolicyTier.LowDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.StandardDeductibleMinimum)),
_ => 0,
};
[ES3NonSerializable]
public int DeductibleMaximum => Tier switch
{
PolicyTier.HighDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.EconomicDeductibleMaximum)),
PolicyTier.LowDeductible => (int)Math.Floor((double)Coverage * SyncedEntry<double>.op_Implicit(Plugin.Config.StandardDeductibleMaximum)),
_ => 0,
};
[ES3NonSerializable]
public static readonly Policy None = new Policy(PolicyTier.None, 0);
public int Coverage;
public PolicyTier Tier;
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);
}
[CompilerGenerated]
protected virtual bool PrintMembers(StringBuilder builder)
{
RuntimeHelpers.EnsureSufficientExecutionStack();
builder.Append("Coverage = ");
builder.Append(Coverage.ToString());
builder.Append(", Tier = ");
builder.Append(Tier.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)
{
Coverage = original.Coverage;
Tier = original.Tier;
}
}
public static class PolicyExtensions
{
public static Policy CreatePolicy(this PolicyTier policyTier, int coverage)
{
return new Policy(policyTier, coverage);
}
}
[ES3Serializable]
public record PolicyClaim
{
public bool Claimed;
public int Value;
public PolicyClaim(int value, bool claimed = false)
{
if (value < 0)
{
throw new ArgumentOutOfRangeException("value", "nonnegative number required");
}
Value = value;
Claimed = claimed;
}
}
public class PolicyState : ModDataContainer
{
public Policy Policy { get; set; } = tesinormed.FAndCDaveCo.Insurance.Policy.None;
public Dictionary<int, PolicyClaim> Claims { get; set; } = new Dictionary<int, PolicyClaim>();
[ModDataIgnore(/*Could not decode attribute arguments.*/)]
public Dictionary<int, PolicyClaim> ClaimedClaims => Claims.Where<KeyValuePair<int, PolicyClaim>>((KeyValuePair<int, PolicyClaim> pair) => pair.Value.Claimed).ToDictionary();
[ModDataIgnore(/*Could not decode attribute arguments.*/)]
public Dictionary<int, PolicyClaim> UnclaimedClaims => Claims.Where<KeyValuePair<int, PolicyClaim>>((KeyValuePair<int, PolicyClaim> pair) => !pair.Value.Claimed).ToDictionary();
[ModDataIgnore(/*Could not decode attribute arguments.*/)]
public double FractionalPremiumIncrease => (double)ClaimedClaims.Count * SyncedEntry<double>.op_Implicit(Plugin.Config.ClaimPremiumIncrease);
[ModDataIgnore(/*Could not decode attribute arguments.*/)]
public int TotalPremium => (int)((double)Policy.BasePremium * (1.0 + FractionalPremiumIncrease));
public static bool DisableDeathCreditPenalty
{
get
{
if (Plugin.PolicyState.Policy.Tier == PolicyTier.None)
{
return false;
}
return SyncedEntry<bool>.op_Implicit(Plugin.Config.GameDisableDeathCreditPenalty);
}
}
protected override void PostSave()
{
Plugin.Logger.LogDebug((object)$"saved policy state {this}");
}
protected override void PostLoad()
{
Plugin.Logger.LogDebug((object)$"loaded policy state {this}");
Plugin.SyncedPolicy.Value = Policy;
Plugin.SyncedClaims.Value = Claims;
}
public void SetAndSyncPolicy(Policy policy)
{
Policy = policy;
new LethalClientMessage<Policy>("UpdatePolicy", (Action<Policy>)null, (Action<Policy, ulong>)null).SendServer(policy);
}
public void UpdateAndSyncClaims(Action<Dictionary<int, PolicyClaim>> action)
{
action(Claims);
new LethalClientMessage<Dictionary<int, PolicyClaim>>("UpdateClaims", (Action<Dictionary<int, PolicyClaim>>)null, (Action<Dictionary<int, PolicyClaim>, ulong>)null).SendServer(Claims);
}
public void ResetAndSync()
{
SetAndSyncPolicy(tesinormed.FAndCDaveCo.Insurance.Policy.None);
UpdateAndSyncClaims(delegate(Dictionary<int, PolicyClaim> claims)
{
claims.Clear();
});
}
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.Append("PolicyState(");
stringBuilder.Append($"policy: {Policy}");
if (Claims.Count > 0)
{
stringBuilder.Append(", claims: [" + string.Join(", ", Claims) + "]");
}
stringBuilder.Append(")");
return stringBuilder.ToString();
}
}
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, PolicyClaim claim)
{
PolicyClaim 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.PolicyState.Policy.Tier == PolicyTier.None)
{
LockedNotification((ITextElement)TextElement.Create("You do not have an active insurance policy."));
return;
}
if (Plugin.PolicyState.UnclaimedClaims.Count == 0)
{
LockedNotification((ITextElement)TextElement.Create("You do not have any claims."));
return;
}
CursorElement[] seed = Array.Empty<CursorElement>();
seed = Plugin.PolicyState.UnclaimedClaims.Aggregate<KeyValuePair<int, PolicyClaim>, CursorElement[]>(seed, delegate(CursorElement[] current, KeyValuePair<int, PolicyClaim> 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, PolicyClaim claim)
{
PolicyClaim claim2 = claim;
int deductible = Plugin.PolicyState.Policy.CalculateDeductible(claim2.Value);
int payout = Plugin.PolicyState.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.PolicyState.UpdateAndSyncClaims(delegate(Dictionary<int, PolicyClaim> 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, PolicyClaim claim)
{
PolicyClaim 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.PolicyState.UpdateAndSyncClaims(delegate(Dictionary<int, PolicyClaim> claims)
{
claims[day] = new PolicyClaim(claim2.Value, claimed: true);
});
new LethalClientMessage<int>("DeductGroupCredits", (Action<int>)null, (Action<int, ulong>)null).SendServer(deductible);
new LethalClientMessage<int>("SpawnGoldBar", (Action<int>)null, (Action<int, ulong>)null).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.PolicyState.FractionalPremiumIncrease * 100.0)}%."));
}
}
public class PolicyInformationTerminal : TerminalApplication
{
public override void Initialization()
{
List<ITextElement> list = new List<ITextElement>();
if (Plugin.PolicyState.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.PolicyState.Policy.Tier.ToFriendlyString()} policy (${Plugin.PolicyState.Policy.Coverage})."));
list.Add((ITextElement)(object)TextElement.Create($"You have made {Plugin.PolicyState.ClaimedClaims.Count} claim(s) recently (within {Plugin.Config.ClaimRetentionDays.Value} days)."));
list.Add((ITextElement)(object)((Plugin.PolicyState.FractionalPremiumIncrease == 0.0) ? TextElement.Create($"You pay ${Plugin.PolicyState.TotalPremium} per day.") : TextElement.Create($"You pay ${Plugin.PolicyState.TotalPremium} (+{(int)(Plugin.PolicyState.FractionalPremiumIncrease * 100.0)}%) per day.")));
list.Add((ITextElement)(object)((Plugin.PolicyState.Policy.DeductiblePercent != 0.0) ? TextElement.Create($"Your deductible is currently {(int)(Plugin.PolicyState.Policy.DeductiblePercent * 100.0)}% (minimum: ${Plugin.PolicyState.Policy.DeductibleMinimum}, maximum: ${Plugin.PolicyState.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)
{
PolicyState policyState = new PolicyState
{
Policy = policy,
Claims = Plugin.PolicyState.Claims
};
return CursorElement.Create($"${policy.Coverage}", "", (Action)delegate
{
ConfirmEverything(policyState);
}, (Func<CursorElement, bool>)((CursorElement _) => ((TerminalApplication)this).terminal.groupCredits >= policyState.TotalPremium), 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.PolicyState.Policy.Tier != PolicyTier.None), true));
}
private void ConfirmCancelPolicy()
{
if (Plugin.PolicyState.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.PolicyState.Policy.Tier.ToFriendlyString()} (${Plugin.PolicyState.Policy.Coverage})."));
}
}
private void CancelPolicy()
{
Plugin.PolicyState.SetAndSyncPolicy(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.Config.CoverageOption00))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption01))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption02))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption03))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption04))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption05))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption06))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption07))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption08))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption09))), CreateCoverageCursorElement(policyTier.CreatePolicy(SyncedEntry<int>.op_Implicit(Plugin.Config.CoverageOption10))));
}
private void ConfirmEverything(PolicyState state)
{
PolicyState state2 = state;
if (state2.Policy == Plugin.PolicyState.Policy)
{
Notification(base.PreviousScreenAction, (ITextElement)TextElement.Create("You already have this policy."));
return;
}
if (((TerminalApplication)this).terminal.groupCredits < state2.TotalPremium)
{
Notification(base.PreviousScreenAction, (ITextElement)TextElement.Create("You do not have enough credits to purchase this policy."));
return;
}
Confirm(delegate
{
SetEverything(state2.Policy, state2.TotalPremium);
}, base.PreviousScreenAction, (ITextElement)TextElement.Create($"Are you sure you want to pick {state2.Policy.Tier.ToFriendlyString()} (${state2.Policy.Coverage})?"), (ITextElement)TextElement.Create((state2.Policy.DeductiblePercent == 0.0) ? "This policy has no deductibles." : $"The deductibles are {(int)(state2.Policy.DeductiblePercent * 100.0)}%, with a minimum of ${state2.Policy.DeductibleMinimum} and a maximum of ${state2.Policy.DeductibleMaximum}."), (ITextElement)TextElement.Create($"You will be charged ${state2.TotalPremium}."));
}
private void SetEverything(Policy policy, int cost)
{
Plugin.PolicyState.SetAndSyncPolicy(policy);
new LethalClientMessage<int>("DeductGroupCredits", (Action<int>)null, (Action<int, ulong>)null).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, PreviousCursorMenu, 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
{
public class BankState : ModDataContainer
{
public Loan Loan { get; set; } = tesinormed.FAndCDaveCo.Bank.Loan.None;
protected override void PostSave()
{
Plugin.Logger.LogDebug((object)$"saved bank state {this}");
}
protected override void PostLoad()
{
Plugin.Logger.LogDebug((object)$"loaded bank state {this}");
Plugin.SyncedLoan.Value = Loan;
}
public void SetAndSyncLoan(Loan loan)
{
Loan = loan;
new LethalClientMessage<Loan>("UpdateLoan", (Action<Loan>)null, (Action<Loan, ulong>)null).SendServer(loan);
}
public void UpdateAndSyncLoan(Action<Loan> action)
{
action(Loan);
new LethalClientMessage<Loan>("UpdateLoan", (Action<Loan>)null, (Action<Loan, ulong>)null).SendServer(Loan);
}
public void ResetAndSync()
{
SetAndSyncLoan(tesinormed.FAndCDaveCo.Bank.Loan.None);
}
public override string ToString()
{
return $"BankState(loan: {Loan})";
}
}
[ES3Serializable]
public record Loan
{
[ES3NonSerializable]
public int DaysSinceIssuance => StartOfRound.Instance.gameStats.daysSpent - IssuanceDate;
[ES3NonSerializable]
public int Interest => (int)((double)Principal * SyncedEntry<double>.op_Implicit(Plugin.Config.InterestAmount));
[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 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;
}
[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. Banking: 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.BankState.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;
}
Loan loan = new Loan(0, TimeOfDay.Instance.profitQuota - TimeOfDay.Instance.quotaFulfilled);
Confirm(delegate
{
GetLoan(loan);
}, (ITextElement)TextElement.Create($"Are you sure you want to get a loan for ${loan.Principal}? The total cost will be ${loan.Total}."));
}
private void GetLoan(Loan loan)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
new LethalClientEvent("TakeOutLoan", (Action)null, (Action<ulong>)null).InvokeServer();
LockedNotification((ITextElement)TextElement.Create($"You have successfully taken out a loan for ${loan.Principal}."));
}
}
public class BankLoanInformationTerminal : TerminalApplication
{
public override void Initialization()
{
List<ITextElement> list = new List<ITextElement>();
if (Plugin.BankState.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.BankState.Loan.DaysSinceIssuance} day(s) ago."));
list.Add((ITextElement)(object)TextElement.Create($"The loan is for ${Plugin.BankState.Loan.Principal} with ${Plugin.BankState.Loan.Interest} added as interest."));
list.Add((ITextElement)(object)TextElement.Create($"Amount paid: ${Plugin.BankState.Loan.AmountPaid}, amount left: ${Plugin.BankState.Loan.AmountUnpaid}, total: ${Plugin.BankState.Loan.Total}."));
if (Plugin.BankState.Loan.DaysSinceIssuance >= SyncedEntry<int>.op_Implicit(Plugin.Config.PenaltyStartDaysFromIssuance))
{
list.Add((ITextElement)(object)TextElement.Create($"{(int)(SyncedEntry<double>.op_Implicit(Plugin.Config.PenaltyAmount) * 100.0)}% of your credits are currently being garnished each day."));
}
}
BoxedScreen currentScreen = BoxedScreen.Create("F&C Dave Co. Banking: Loan information", list.ToArray());
((TerminalApplication)this).currentScreen = (IScreen)(object)currentScreen;
}
}
public class BankLoanPaymentTerminal : InteractiveTerminalApplication
{
protected override string Title => "F&C Dave Co. Banking: Submit loan payment";
private CursorElement CreateCursorElement(double amount)
{
int cost = Math.Min((int)((double)Plugin.BankState.Loan.Total * amount), Plugin.BankState.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.BankState.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)
{
new LethalClientMessage<int>("DeductGroupCredits", (Action<int>)null, (Action<int, ulong>)null).SendServer(amount);
if (Plugin.BankState.Loan.AmountUnpaid - amount == 0)
{
Plugin.BankState.SetAndSyncLoan(Loan.None);
Plugin.Logger.LogDebug((object)"loan paid off fully; removed");
LockedNotification((ITextElement)TextElement.Create("You have paid off your loan fully."));
return;
}
Plugin.BankState.UpdateAndSyncLoan(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.BankState.Loan.AmountUnpaid} must still be paid."));
}
}
internal static class BankTerminal
{
internal const string Title = "F&C Dave Co. Banking";
}
}