using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Core.Logging.Interpolation;
using BepInEx.Logging;
using BepInEx.Unity.IL2CPP;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.Reflection;
using Microsoft.CodeAnalysis;
using SOD.Common;
using SOD.Common.Helpers;
using SOD.Common.Helpers.DialogObjects;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Proprietor")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Proprietor")]
[assembly: AssemblyTitle("Proprietor")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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]
[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]
[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 Proprietor
{
internal static class Dialogs
{
private sealed class SellLogic : IDialogLogic
{
private readonly bool viaStaff;
public SellLogic(bool viaStaff)
{
this.viaStaff = viaStaff;
}
public bool IsDialogShown(DialogPreset preset, Citizen saysTo, SideJob jobRef)
{
return Returnable((Human)(object)saysTo, viaStaff) != null;
}
public ForceSuccess ShouldDialogSucceedOverride(DialogController instance, DialogOption dialog, Citizen saysTo, NewNode where, Actor saidBy)
{
if (Returnable((Human)(object)saysTo, viaStaff) != null)
{
return (ForceSuccess)1;
}
return (ForceSuccess)2;
}
public void OnDialogExecute(DialogController instance, Citizen saysTo, Interactable saysToInteractable, NewNode where, Actor saidBy, bool success, NewRoom roomRef, SideJob jobRef)
{
if (!success)
{
return;
}
try
{
Company val = Returnable((Human)(object)saysTo, viaStaff);
if (val != null)
{
Store.Sell(val, out var message);
Plugin.Message(message);
Plugin.Logger.LogInfo((object)message);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Selling failed: " + ex));
}
}
}
private sealed class BuyLogic : IDialogLogic
{
private readonly bool viaStaff;
public BuyLogic(bool viaStaff)
{
this.viaStaff = viaStaff;
}
public bool IsDialogShown(DialogPreset preset, Citizen saysTo, SideJob jobRef)
{
return ForSale((Human)(object)saysTo, viaStaff) != null;
}
public ForceSuccess ShouldDialogSucceedOverride(DialogController instance, DialogOption dialog, Citizen saysTo, NewNode where, Actor saidBy)
{
Company val = ForSale((Human)(object)saysTo, viaStaff);
if (val != null && GameplayController.Instance.money >= Store.Price(val))
{
return (ForceSuccess)1;
}
return (ForceSuccess)2;
}
public void OnDialogExecute(DialogController instance, Citizen saysTo, Interactable saysToInteractable, NewNode where, Actor saidBy, bool success, NewRoom roomRef, SideJob jobRef)
{
//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
//IL_00b1: Expected O, but got Unknown
if (!success)
{
return;
}
try
{
Company val = ForSale((Human)(object)saysTo, viaStaff);
if (val != null)
{
int num = Store.Price(val);
Store.Buy(val, num);
if (val.director.passcode != null)
{
GameplayController.Instance.AddPasscode(val.director.passcode, false);
}
Plugin.Message($"You now own {val.name}. Log in to its cruncher as {val.shortName}_Admin.");
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(62, 6, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Bought ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(val.name);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(" (company ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(val.companyID);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(") for ¢");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(": regulars ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(Store.Regulars(val), "0.#");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", ");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("land value ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(((Object)(object)val.address != (Object)null) ? val.address.normalizedLandValue : 0f, "0.00");
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral(", menu factor ");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<float>(Store.MenuFactor(val), "0.00");
}
logger.LogInfo(val2);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Buying failed: " + ex));
}
}
}
public const string BuyName = "Proprietor_Buy";
public const string SellName = "Proprietor_Sell";
public const string StaffBuyName = "Proprietor_BuyViaStaff";
public const string StaffSellName = "Proprietor_SellViaStaff";
public static void Register()
{
Lib.Dialogs.Builder("Proprietor_Buy").SetText("I'd like to buy your business.").SetDialogLogic((IDialogLogic)(object)new BuyLogic(viaStaff: false))
.ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset p)
{
p.cost = 1;
p.ranking = 5;
})
.AddResponse("You've got yourself a deal. I'll stay on and keep the place running for you. The office cruncher's yours too.", true, true)
.AddResponse("Come back when you've got the money.", false, true)
.CreateAndRegister();
Lib.Dialogs.Builder("Proprietor_BuyViaStaff").SetText("I'd like to buy this business. Can you get the owner on the phone?").SetDialogLogic((IDialogLogic)(object)new BuyLogic(viaStaff: true))
.ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset p)
{
p.cost = 1;
p.ranking = 5;
})
.AddResponse("Hang on, I'll call the boss... They say you've got a deal. They'll stay on and run the place for you.", true, true)
.AddResponse("The boss says come back when you've got the money.", false, true)
.CreateAndRegister();
Lib.Dialogs.Builder("Proprietor_SellViaStaff").SetText("Can you call the manager? I want to sell the business back to them.").SetDialogLogic((IDialogLogic)(object)new SellLogic(viaStaff: true))
.ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset p)
{
p.ranking = 4;
})
.AddResponse("One moment... They'll take it back. The money's on its way to you.", true, true)
.CreateAndRegister();
Lib.Dialogs.Builder("Proprietor_Sell").SetText("I'd like to sell the business back to you.").SetDialogLogic((IDialogLogic)(object)new SellLogic(viaStaff: false))
.ModifyDialogOptions((Action<DialogPreset>)delegate(DialogPreset p)
{
p.ranking = 4;
})
.AddResponse("If that's what you want. Here's your money; I'll take it from here.", true, true)
.CreateAndRegister();
}
public static Company SellerCompany(Human h)
{
if ((Object)(object)h == (Object)null || ((Actor)h).isPlayer)
{
return null;
}
Occupation job = h.job;
Company val = ((job != null) ? job.employer : null);
if (val != null && (Object)(object)val.director != (Object)null && val.director.humanID == h.humanID)
{
return val;
}
return null;
}
public static Company StaffOnShift(Human h)
{
if ((Object)(object)h == (Object)null || ((Actor)h).isPlayer || !((Actor)h).isAtWork)
{
return null;
}
Occupation job = h.job;
Company val = ((job != null) ? job.employer : null);
if (val == null || (Object)(object)val.address == (Object)null || (Object)(object)val.director == (Object)null || val.director.humanID == h.humanID)
{
return null;
}
NewGameLocation currentGameLocation = ((Actor)h).currentGameLocation;
NewAddress val2 = ((currentGameLocation != null) ? currentGameLocation.thisAsAddress : null);
if (!((Object)(object)val2 != (Object)null) || !(((Il2CppObjectBase)val2).Pointer == ((Il2CppObjectBase)val.address).Pointer))
{
return null;
}
return val;
}
public static Company ForSale(Human h, bool viaStaff)
{
Company val = (viaStaff ? StaffOnShift(h) : SellerCompany(h));
if (val == null || !Store.Sellable(val))
{
return null;
}
return val;
}
public static Company Returnable(Human h, bool viaStaff)
{
Company val = (viaStaff ? StaffOnShift(h) : ManagedForPlayer(h));
if (val == null || Store.Get(val) == null)
{
return null;
}
return val;
}
public static Company ManagedForPlayer(Human h)
{
if ((Object)(object)h == (Object)null || ((Actor)h).isPlayer)
{
return null;
}
Occupation job = h.job;
Company val = ((job != null) ? job.employer : null);
if (val == null || !((Object)(object)val.director != (Object)null) || val.director.humanID != h.humanID || Store.Get(val) == null)
{
return null;
}
return val;
}
}
[HarmonyPatch(typeof(DialogPreset), "GetCost")]
internal static class CostPatch
{
private static void Postfix(DialogPreset __instance, Actor talkingTo, ref int __result)
{
if ((SoCustomComparison)(object)__instance == (SoCustomComparison)null)
{
return;
}
string name = ((Object)__instance).name;
if (name != "Proprietor_Buy" && name != "Proprietor_BuyViaStaff")
{
return;
}
try
{
Company val = Dialogs.ForSale((talkingTo != null) ? ((Il2CppObjectBase)talkingTo).TryCast<Human>() : null, name == "Proprietor_BuyViaStaff");
if (val != null)
{
__result = Store.Price(val);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Price lookup failed: " + ex.Message));
}
}
}
[HarmonyPatch]
internal static class LedgerApp
{
private enum RowKind
{
Till,
Item,
Business,
Back
}
private sealed class Row
{
public RowKind Kind;
public string Item;
public int Price;
public int CompanyId;
}
public const string AppName = "BusinessLedger";
public const string Marker = "\u200b";
private const string Currency = "¢";
private static CruncherAppPreset preset;
private static readonly Dictionary<IntPtr, Row> rows = new Dictionary<IntPtr, Row>();
private static readonly Dictionary<IntPtr, int> viewing = new Dictionary<IntPtr, int>();
private static readonly Dictionary<IntPtr, List<CruncherAppPreset>> originals = new Dictionary<IntPtr, List<CruncherAppPreset>>();
private static bool AtHome(ComputerController cc)
{
object obj;
if (cc == null)
{
obj = null;
}
else
{
InteractableController ic = cc.ic;
if (ic == null)
{
obj = null;
}
else
{
Interactable interactable = ic.interactable;
if (interactable == null)
{
obj = null;
}
else
{
NewNode node = interactable.node;
if (node == null)
{
obj = null;
}
else
{
NewGameLocation gameLocation = node.gameLocation;
obj = ((gameLocation != null) ? gameLocation.thisAsAddress : null);
}
}
}
}
NewAddress val = (NewAddress)obj;
if ((Object)(object)val == (Object)null || (Object)(object)Player.Instance == (Object)null)
{
return false;
}
Enumerator<NewAddress> enumerator = Player.Instance.apartmentsOwned.GetEnumerator();
while (enumerator.MoveNext())
{
NewAddress current = enumerator.Current;
if ((Object)(object)current != (Object)null && ((Il2CppObjectBase)current).Pointer == ((Il2CppObjectBase)val).Pointer)
{
return true;
}
}
return false;
}
private static Company Shown(ComputerController cc)
{
Company val = CompanyAt(cc);
if (Store.Get(val) != null)
{
return val;
}
if (!AtHome(cc) || !viewing.TryGetValue(((Il2CppObjectBase)cc).Pointer, out var value))
{
return null;
}
return Store.FindCompany(value);
}
private static bool IsLedger(ComputerController cc)
{
if ((SoCustomComparison)(object)preset != (SoCustomComparison)null && (Object)(object)cc != (Object)null && (SoCustomComparison)(object)cc.currentApp != (SoCustomComparison)null)
{
return ((Il2CppObjectBase)cc.currentApp).Pointer == ((Il2CppObjectBase)preset).Pointer;
}
return false;
}
private static Company CompanyAt(ComputerController cc)
{
if (cc == null)
{
return null;
}
InteractableController ic = cc.ic;
if (ic == null)
{
return null;
}
Interactable interactable = ic.interactable;
if (interactable == null)
{
return null;
}
NewNode node = interactable.node;
if (node == null)
{
return null;
}
NewGameLocation gameLocation = node.gameLocation;
if (gameLocation == null)
{
return null;
}
NewAddress thisAsAddress = gameLocation.thisAsAddress;
if (thisAsAddress == null)
{
return null;
}
return thisAsAddress.company;
}
[HarmonyPatch(typeof(DesktopApp), "UpdateIcons")]
[HarmonyPrefix]
private static void Install(DesktopApp __instance)
{
try
{
ComputerController controller = ((CruncherAppContent)__instance).controller;
object obj;
if (controller == null)
{
obj = null;
}
else
{
InteractableController ic = controller.ic;
if (ic == null)
{
obj = null;
}
else
{
Interactable interactable = ic.interactable;
if (interactable == null)
{
obj = null;
}
else
{
InteractablePreset obj2 = interactable.preset;
obj = ((obj2 != null) ? obj2.additionalApps : null);
}
}
}
List<CruncherAppPreset> val = (List<CruncherAppPreset>)obj;
if (val == null)
{
return;
}
if ((SoCustomComparison)(object)preset == (SoCustomComparison)null)
{
Create();
}
if ((SoCustomComparison)(object)preset == (SoCustomComparison)null)
{
return;
}
if (!originals.TryGetValue(((Il2CppObjectBase)val).Pointer, out var value))
{
value = new List<CruncherAppPreset>();
Enumerator<CruncherAppPreset> enumerator = val.GetEnumerator();
while (enumerator.MoveNext())
{
CruncherAppPreset current = enumerator.Current;
if ((SoCustomComparison)(object)current != (SoCustomComparison)null && ((Il2CppObjectBase)current).Pointer != ((Il2CppObjectBase)preset).Pointer)
{
value.Add(current);
}
}
originals[((Il2CppObjectBase)val).Pointer] = value;
}
ComputerController controller2 = ((CruncherAppContent)__instance).controller;
bool flag = Store.Get(CompanyAt(controller2)) != null;
bool flag2 = !flag && Store.Owned.Count > 0 && AtHome(controller2);
val.Clear();
bool flag3 = false;
foreach (CruncherAppPreset item in value)
{
if (flag && !flag3 && IsWizcards(item))
{
val.Add(preset);
flag3 = true;
}
else
{
val.Add(item);
}
}
if ((flag || flag2) && !flag3)
{
val.Add(preset);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't set up the Business Ledger: " + ex));
}
}
private static bool IsWizcards(CruncherAppPreset app)
{
Enumerator<GameObject> enumerator = app.appContent.GetEnumerator();
while (enumerator.MoveNext())
{
GameObject current = enumerator.Current;
if ((Object)(object)current != (Object)null && (Object)(object)current.GetComponent<WizcardsApp>() != (Object)null)
{
return true;
}
}
return false;
}
private static void Create()
{
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ef: Expected O, but got Unknown
CruncherAppPreset val = null;
foreach (CruncherAppPreset item in Resources.FindObjectsOfTypeAll<CruncherAppPreset>())
{
if ((SoCustomComparison)(object)item != (SoCustomComparison)null && ((Object)item).name != "BusinessLedger" && IsSalesRecords(item))
{
val = item;
break;
}
}
if (!((SoCustomComparison)(object)val == (SoCustomComparison)null))
{
preset = Object.Instantiate<CruncherAppPreset>(val);
((Object)preset).name = "BusinessLedger";
preset.alwaysInstalled = true;
preset.companyOnly = false;
preset.salesRecordsOnly = false;
preset.onlyIfOwner = false;
preset.onlyIfResidential = false;
preset.onlyIfCorporateSabotageSkill = false;
preset.installationConditions = new List<AppAccess>();
preset.onlyInAddresses = new List<AddressPreset>();
Object.DontDestroyOnLoad((Object)(object)preset);
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val2 = new BepInExInfoLogInterpolatedStringHandler(39, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("Business Ledger program created from '");
((BepInExLogInterpolatedStringHandler)val2).AppendFormatted<string>(((Object)val).name);
((BepInExLogInterpolatedStringHandler)val2).AppendLiteral("'");
}
logger.LogInfo(val2);
}
}
private static bool IsSalesRecords(CruncherAppPreset app)
{
Enumerator<GameObject> enumerator = app.appContent.GetEnumerator();
while (enumerator.MoveNext())
{
GameObject current = enumerator.Current;
if ((Object)(object)current != (Object)null && (Object)(object)current.GetComponent<SalesRecordsApp>() != (Object)null)
{
return true;
}
}
return false;
}
[HarmonyPatch(typeof(DesktopIconController), "Setup")]
[HarmonyPostfix]
private static void IconName(DesktopIconController __instance, CruncherAppPreset newApp)
{
if ((SoCustomComparison)(object)preset != (SoCustomComparison)null && (SoCustomComparison)(object)newApp != (SoCustomComparison)null && ((Il2CppObjectBase)newApp).Pointer == ((Il2CppObjectBase)preset).Pointer)
{
((TMP_Text)__instance.iconText).text = "Business Ledger";
}
}
[HarmonyPatch(typeof(SalesRecordsApp), "UpdateEntries")]
[HarmonyPrefix]
private static bool Entries(SalesRecordsApp __instance)
{
if (!IsLedger(((CruncherAppContent)__instance).controller))
{
return true;
}
try
{
Fill(__instance);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Business Ledger couldn't list: " + ex));
}
return false;
}
private static void Fill(SalesRecordsApp app)
{
ComputerController controller = ((CruncherAppContent)app).controller;
bool flag = AtHome(controller) && Store.Get(CompanyAt(controller)) == null;
Company val = Shown(controller);
Business business = Store.Get(val);
rows.Clear();
List<OSMultiOption> val2 = new List<OSMultiOption>();
if (business == null && flag)
{
((TMP_Text)app.titleText).text = "MY BUSINESSES";
foreach (Business item in Store.Owned.Values.OrderBy((Business x) => x.Name))
{
val2.Add(Option(Summary(item), new Row
{
Kind = RowKind.Business,
CompanyId = item.CompanyId
}));
}
if (val2.Count == 0)
{
val2.Add(Option("You don't own any businesses.", null));
}
app.list.UpdateElements(val2);
app.UpdateSelected();
return;
}
((TMP_Text)app.titleText).text = ((val != null) ? val.name.ToUpperInvariant() : "BUSINESS LEDGER");
if (business == null)
{
val2.Add(Option("You don't own this business.", null));
app.list.UpdateElements(val2);
return;
}
if (flag)
{
val2.Add(Option("< ALL BUSINESSES\nBack to the list", new Row
{
Kind = RowKind.Back
}));
}
float now = SessionData.Instance.gameTime;
List<Sale> list = business.Sales.Where((Sale s) => now - s.Time <= 24f).ToList();
int num = val.companyRoster?.Count ?? 0;
int num2 = business.Transfers.Sum((Transfer t) => t.Amount);
val2.Add(Option($"TILL: {"¢"}{business.Till}" + ((num2 > 0) ? $"\n{"¢"}{num2} on its way to you" : "") + $"\n24 hours: {list.Count} customers, {"¢"}{list.Sum((Sale s) => s.Total)}\n" + $"Turned away: {business.TurnedAway}\nWages: {"¢"}{num * Plugin.WagePerStaff.Value}/day", new Row
{
Kind = RowKind.Till,
CompanyId = business.CompanyId
}));
foreach (KeyValuePair<InteractablePreset, int> item2 in Store.Menu(val))
{
string name = ((Object)item2.Key).name;
int value;
int num3 = (business.Stock.TryGetValue(name, out value) ? value : 0);
List<Order> list2 = business.Orders.Where((Order o) => o.Item == name).ToList();
string text = $"{Store.ItemName(name)}: {((num3 > 0) ? (num3 + " in stock") : "OUT OF STOCK")}\nPrice {"¢"}{item2.Value}\nCost {"¢"}{Store.UnitCost(item2.Value)}";
foreach (Order item3 in list2)
{
int num4 = Store.DaysUntil(item3.Arrives);
text += $"\n+{item3.Quantity} due {((num4 <= 0) ? "today" : ((num4 == 1) ? "tomorrow" : $"in {num4} days"))}";
}
val2.Add(Option(text, new Row
{
Kind = RowKind.Item,
Item = name,
Price = item2.Value,
CompanyId = business.CompanyId
}));
}
foreach (Sale item4 in business.Sales.Take(40))
{
string text2 = SessionData.Instance.TimeAndDate(item4.Time, false, true, true) + " " + item4.Customer;
string text3 = string.Join("\n", item4.Items.Select((SaleItem i) => "<align=\"left\">" + Store.ItemName(i.Item) + " <align=\"right\">¢" + i.Price));
val2.Add(Option(text2 + "\n" + text3, null));
}
app.list.UpdateElements(val2);
app.UpdateSelected();
}
private static string Summary(Business b)
{
float now = SessionData.Instance.gameTime;
List<Sale> list = b.Sales.Where((Sale s) => now - s.Time <= 24f).ToList();
int num = b.Stock.Count((KeyValuePair<string, int> kv) => kv.Value <= Plugin.LowStock.Value);
return $"{b.Name}\nTill {"¢"}{b.Till}\n24h: {list.Count} sales, {"¢"}{list.Sum((Sale s) => s.Total)}\n" + ((num > 0) ? $"LOW STOCK: {num} item{((num == 1) ? "" : "s")}" : "Stock OK") + ((b.Orders.Count > 0) ? $"\nOrders due: {b.Orders.Count}" : "");
}
private static OSMultiOption Option(string text, Row row)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
OSMultiOption val = new OSMultiOption("\u200b" + text, (Human)null);
if (row != null)
{
rows[((Il2CppObjectBase)val).Pointer] = row;
}
return val;
}
private static Row Selected(SalesRecordsApp app)
{
ComputerOSMultiSelect list = app.list;
object obj;
if (list == null)
{
obj = null;
}
else
{
ComputerOSMultiSelectElement selected = list.selected;
obj = ((selected != null) ? selected.option : null);
}
OSMultiOption val = (OSMultiOption)obj;
if (val == null || !rows.TryGetValue(((Il2CppObjectBase)val).Pointer, out var value))
{
return null;
}
return value;
}
[HarmonyPatch(typeof(ComputerOSMultiSelectElement), "Setup")]
[HarmonyPostfix]
private static void RowText(ComputerOSMultiSelectElement __instance, OSMultiOption newOpt)
{
string text = ((newOpt != null) ? newOpt.text : null);
if (text != null && text.StartsWith("\u200b"))
{
int num = text.IndexOf('\n');
((TMP_Text)__instance.elementText).text = ((num < 0) ? text : text.Substring(0, num)).Substring("\u200b".Length);
if ((Object)(object)__instance.elementText2 != (Object)null)
{
((TMP_Text)__instance.elementText2).text = ((num < 0) ? "" : text.Substring(num + 1));
}
}
}
[HarmonyPatch(typeof(SalesRecordsApp), "UpdateSelected")]
[HarmonyPostfix]
private static void ActionButton(SalesRecordsApp __instance)
{
if (!IsLedger(((CruncherAppContent)__instance).controller) || (Object)(object)__instance.printButton == (Object)null)
{
return;
}
try
{
Row row = Selected(__instance);
Business business = ((row != null) ? Store.Get(Store.FindCompany(row.CompanyId)) : null);
bool flag = Store.Get(CompanyAt(((CruncherAppContent)__instance).controller)) == null;
string text;
switch (row?.Kind)
{
case RowKind.Back:
text = "BACK";
break;
case RowKind.Business:
text = "OPEN";
break;
case RowKind.Till:
if (business != null && flag)
{
text = $"TRANSFER {"¢"}{Store.TransferNet(business.Till)}";
break;
}
if (business != null)
{
text = $"COLLECT {"¢"}{Math.Max(0, business.Till)}";
break;
}
goto default;
case RowKind.Item:
if (business != null)
{
text = $"ORDER {Plugin.OrderSize.Value} - {"¢"}{Store.UnitCost(row.Price) * Plugin.OrderSize.Value}";
break;
}
goto default;
default:
text = null;
break;
}
string text2 = text;
((Component)__instance.printButton).gameObject.SetActive(text2 != null);
TextMeshProUGUI val = ((text2 != null) ? Label(__instance) : null);
if ((Object)(object)val != (Object)null)
{
((TMP_Text)val).text = text2;
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Business Ledger button failed: " + ex.Message));
}
}
private static TextMeshProUGUI Label(SalesRecordsApp app)
{
TextMeshProUGUI componentInChildren = ((Component)app.printButton).GetComponentInChildren<TextMeshProUGUI>(true);
if ((Object)(object)componentInChildren == (Object)null)
{
return null;
}
ComputerAutoTextController component = ((Component)componentInChildren).GetComponent<ComputerAutoTextController>();
if ((Object)(object)component != (Object)null && ((Behaviour)component).enabled)
{
((Behaviour)component).enabled = false;
Widen(app.printButton, 2.5f);
((TMP_Text)componentInChildren).fontSizeMax = ((TMP_Text)componentInChildren).fontSize;
((TMP_Text)componentInChildren).fontSizeMin = ((TMP_Text)componentInChildren).fontSize * 0.6f;
((TMP_Text)componentInChildren).enableAutoSizing = true;
((TMP_Text)componentInChildren).enableWordWrapping = false;
((TMP_Text)componentInChildren).overflowMode = (TextOverflowModes)3;
((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)514;
}
return componentInChildren;
}
private static void Widen(RectTransform rect, float factor)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
//IL_0054: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
try
{
Rect rect2 = rect.rect;
float width = ((Rect)(ref rect2)).width;
float num = width * (factor - 1f);
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(47, 6, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Button] width ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(width);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", anchors ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector2>(rect.anchorMin);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("-");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector2>(rect.anchorMax);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", pivot ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector2>(rect.pivot);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", pos ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector2>(rect.anchoredPosition);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", size ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<Vector2>(rect.sizeDelta);
}
logger.LogInfo(val);
LayoutElement component = ((Component)rect).GetComponent<LayoutElement>();
if ((Object)(object)component != (Object)null)
{
if (component.preferredWidth > 0f)
{
component.preferredWidth = width * factor;
}
if (component.minWidth > 0f)
{
component.minWidth = width * factor;
}
}
rect.sizeDelta = new Vector2(rect.sizeDelta.x + num, rect.sizeDelta.y);
rect.anchoredPosition = new Vector2(rect.anchoredPosition.x - num * (1f - rect.pivot.x), rect.anchoredPosition.y);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't widen the button: " + ex.Message));
}
}
private static void LogHierarchy(Transform t, int depth)
{
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Expected O, but got Unknown
List<string> list = new List<string>();
foreach (Component component in ((Component)t).GetComponents<Component>())
{
list.Add(((MemberInfo)((Object)component).GetIl2CppType()).Name);
}
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(12, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Button] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(new string(' ', depth * 2));
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)t).name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", list));
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
}
logger.LogInfo(val);
for (int i = 0; i < t.childCount; i++)
{
LogHierarchy(t.GetChild(i), depth + 1);
}
}
[HarmonyPatch(typeof(SalesRecordsApp), "OnPrintEntry")]
[HarmonyPrefix]
private static bool Action(SalesRecordsApp __instance)
{
//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
//IL_01f1: Expected O, but got Unknown
//IL_0171: Unknown result type (might be due to invalid IL or missing references)
//IL_0178: Expected O, but got Unknown
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Expected O, but got Unknown
if (!IsLedger(((CruncherAppContent)__instance).controller))
{
return true;
}
try
{
Row row = Selected(__instance);
if (row == null)
{
return false;
}
ComputerController controller = ((CruncherAppContent)__instance).controller;
if (row.Kind == RowKind.Business || row.Kind == RowKind.Back)
{
if (row.Kind == RowKind.Business)
{
viewing[((Il2CppObjectBase)controller).Pointer] = row.CompanyId;
}
else
{
viewing.Remove(((Il2CppObjectBase)controller).Pointer);
}
Sound(controller, AudioControls.Instance.computerPrint);
__instance.list.page = 0;
Fill(__instance);
__instance.OnChangePage();
return false;
}
Business business = Store.Get(Store.FindCompany(row.CompanyId));
if (business == null)
{
return false;
}
bool flag = Store.Get(CompanyAt(controller)) == null;
bool flag2 = default(bool);
if (row.Kind == RowKind.Till)
{
if (business.Till <= 0)
{
Plugin.Message("The till is empty.", good: false);
Sound(controller, AudioControls.Instance.computerInvalidPasscode);
return false;
}
if (flag)
{
string text = Store.Transfer(business);
Plugin.Message(text);
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(2, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(business.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
}
logger.LogInfo(val);
}
else
{
GameplayController.Instance.AddMoney(business.Till, true, "proprietor_collect");
ManualLogSource logger2 = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(13, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(business.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": collected ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(business.Till);
}
logger2.LogInfo(val);
business.Till = 0;
}
Sound(controller, AudioControls.Instance.computerPrint);
}
else
{
string message;
bool flag3 = Store.PlaceOrder(business, row.Item, row.Price, out message);
Plugin.Message(message, flag3);
ManualLogSource logger3 = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(2, 2, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(business.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(message);
}
logger3.LogInfo(val);
Sound(controller, flag3 ? AudioControls.Instance.computerPrint : AudioControls.Instance.computerInvalidPasscode);
}
int page = __instance.list.page;
Fill(__instance);
if (page != __instance.list.page)
{
__instance.list.NextPage(page - __instance.list.page);
}
__instance.OnChangePage();
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Business Ledger action failed: " + ex));
}
return false;
}
private static void Sound(ComputerController cc, AudioEvent e)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
try
{
AudioController.Instance.PlayWorldOneShot(e, (Actor)(object)Player.Instance, cc.ic.interactable.node, cc.ic.interactable.wPos, (Interactable)null, (List<FMODParam>)null, 1f, (List<NewNode>)null, false, (SoundMaterialOverride)null, false);
}
catch
{
}
}
}
[HarmonyPatch(typeof(ComputerOSMultiSelect), "SpawnList")]
internal static class LedgerListPatch
{
private static bool Prefix(ComputerOSMultiSelect __instance)
{
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
List<OSMultiOption> allOptions = __instance.allOptions;
if (allOptions != null && allOptions.Count != 0)
{
OSMultiOption obj = allOptions[0];
if (((obj != null) ? obj.text : null) != null && allOptions[0].text.StartsWith("\u200b"))
{
try
{
Enumerator<ComputerOSMultiSelectElement> enumerator = __instance.options.GetEnumerator();
while (enumerator.MoveNext())
{
ComputerOSMultiSelectElement current = enumerator.Current;
if ((Object)(object)current != (Object)null)
{
Object.Destroy((Object)(object)((Component)current).gameObject);
}
}
__instance.options.Clear();
int num = (__instance.usePages ? (__instance.page * __instance.maxPerPage) : 0);
int num2 = (__instance.usePages ? (num + __instance.maxPerPage) : allOptions.Count);
float num3 = 0f;
for (int i = num; i < num2 && i < allOptions.Count; i++)
{
ComputerOSMultiSelectElement component = Object.Instantiate<GameObject>(__instance.elementPrefab, (Transform)(object)__instance.elementParent).GetComponent<ComputerOSMultiSelectElement>();
component.Setup(allOptions[i], __instance);
component.rect.anchoredPosition = new Vector2(0f, num3);
num3 -= component.rect.sizeDelta.y;
__instance.options.Add(component);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Business Ledger couldn't draw its list: " + ex.Message));
}
return false;
}
}
return true;
}
}
[BepInPlugin("sodmods.proprietor", "Under New Management", "1.0.0")]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class Plugin : BasePlugin
{
public const string Guid = "sodmods.proprietor";
internal static ManualLogSource Logger;
internal static ConfigEntry<int> BasePrice;
internal static ConfigEntry<int> PricePerRegular;
internal static ConfigEntry<int> StartingStock;
internal static ConfigEntry<int> OrderSize;
internal static ConfigEntry<int> WagePerStaff;
internal static ConfigEntry<int> MinDeliveryDays;
internal static ConfigEntry<int> MaxDeliveryDays;
internal static ConfigEntry<float> WholesaleShare;
internal static ConfigEntry<float> TransferFee;
internal static ConfigEntry<float> TransferHour;
internal static ConfigEntry<float> TypicalMenuPrice;
internal static ConfigEntry<float> SellBackShare;
internal static ConfigEntry<int> LowStock;
internal static ConfigEntry<bool> LogEachSale;
internal static ConfigEntry<bool> ProbeShops;
internal static ConfigEntry<int> TestStock;
internal static ConfigEntry<float> TestDeliveryHours;
public override void Load()
{
//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
Logger = ((BasePlugin)this).Log;
BasePrice = ((BasePlugin)this).Config.Bind<int>("Buying", "BasePrice", 1500, "Price of a business before its size is counted, in crows.");
PricePerRegular = ((BasePlugin)this).Config.Bind<int>("Buying", "PricePerRegular", 12, "Added to the price for each regular customer (citizens whose favourite place it is; a regular for meals counts fully, for snacks or coffee 0.6, for drinks 0.8).");
TypicalMenuPrice = ((BasePlugin)this).Config.Bind<float>("Buying", "TypicalMenuPrice", 4f, "Average menu price of an ordinary diner. Businesses with pricier menus cost more to buy (and less if cheaper).");
SellBackShare = ((BasePlugin)this).Config.Bind<float>("Buying", "SellBackShare", 0.6f, "Selling a business back to its manager returns this share of what you paid (0.6 = 60%), plus whatever is in the till.");
StartingStock = ((BasePlugin)this).Config.Bind<int>("Stock", "StartingStock", 20, "How many of each menu item a business has when you buy it.");
OrderSize = ((BasePlugin)this).Config.Bind<int>("Stock", "OrderSize", 10, "How many of an item one order brings.");
WholesaleShare = ((BasePlugin)this).Config.Bind<float>("Stock", "WholesaleShare", 0.3f, "What stock costs you, as a share of its menu price (0.3 = 30%).");
MinDeliveryDays = ((BasePlugin)this).Config.Bind<int>("Stock", "MinDeliveryDays", 2, "Fewest in-game days an order takes to arrive.");
MaxDeliveryDays = ((BasePlugin)this).Config.Bind<int>("Stock", "MaxDeliveryDays", 6, "Most in-game days an order takes to arrive.");
LowStock = ((BasePlugin)this).Config.Bind<int>("Stock", "LowStockWarning", 5, "The home ledger warns about items with this many or fewer left.");
TransferFee = ((BasePlugin)this).Config.Bind<float>("Remote", "TransferFee", 0.1f, "Share of the till a courier keeps when you send it home from your apartment's cruncher (0.1 = 10%). 0 = free.");
TransferHour = ((BasePlugin)this).Config.Bind<float>("Remote", "TransferArrivalHour", 8f, "Hour of the next morning the courier arrives with the money.");
WagePerStaff = ((BasePlugin)this).Config.Bind<int>("Running", "WagePerStaff", 8, "Paid out of the till every in-game day, per job at the business.");
LogEachSale = ((BasePlugin)this).Config.Bind<bool>("Debug", "LogEachSale", false, "Write every sale at a business to the log.");
ProbeShops = ((BasePlugin)this).Config.Bind<bool>("Debug", "ProbeShops", false, "Research: log the game's shopping goals and what citizens do inside businesses you own.");
TestStock = ((BasePlugin)this).Config.Bind<int>("Debug", "TestStock", -1, "Testing: when a save loads, set every item at your businesses to this many in stock. -1 = off.");
TestDeliveryHours = ((BasePlugin)this).Config.Bind<float>("Debug", "TestDeliveryHours", -1f, "Testing: orders arrive this many in-game hours after you place them (orders already on the way are brought forward when a save loads). -1 = off.");
Lib.SaveGame.OnAfterLoad += delegate(object? _, SaveGameArgs args)
{
Store.Load(args);
};
Lib.SaveGame.OnAfterSave += delegate(object? _, SaveGameArgs args)
{
Store.Save(args);
};
Lib.SaveGame.OnBeforeNewGame += delegate
{
Store.Clear();
};
Dialogs.Register();
new Harmony("sodmods.proprietor").PatchAll(typeof(Plugin).Assembly);
((BasePlugin)this).Log.LogInfo((object)"Under New Management loaded");
}
internal static void Message(string text, bool good = true)
{
//IL_001d: 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)
try
{
Lib.GameMessage.Broadcast(text, (GameMessageType)0, (Icon)17, (Color?)(good ? InterfaceControls.Instance.messageGreen : InterfaceControls.Instance.messageRed), 0f);
}
catch (Exception ex)
{
Logger.LogError((object)("Couldn't show message: " + ex.Message));
}
}
}
internal static class ShopProbe
{
public static void DumpGoals()
{
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Expected O, but got Unknown
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0133: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Expected O, but got Unknown
//IL_0284: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Expected O, but got Unknown
//IL_01e9: Unknown result type (might be due to invalid IL or missing references)
if (!Plugin.ProbeShops.Value)
{
return;
}
try
{
bool flag = default(bool);
foreach (AIGoalPreset item in from g in (IEnumerable<AIGoalPreset>)Resources.FindObjectsOfTypeAll<AIGoalPreset>()
where (SoCustomComparison)(object)g != (SoCustomComparison)null && ((int)g.locationOption == 6 || (int)g.locationOption == 3)
orderby ((Object)g).name
select g)
{
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(35, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Probe] goal '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)item).name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' location=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<LocationOption>(item.locationOption);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" category=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<CompanyCategory>(item.desireCategory);
}
logger.LogInfo(val);
}
foreach (Business value in Store.Owned.Values)
{
Company val2 = Store.FindCompany(value.CompanyId);
if (val2 == null)
{
continue;
}
List<string> list = new List<string>();
Enumerator<CompanyCategory> enumerator3 = val2.preset.companyCategories.GetEnumerator();
while (enumerator3.MoveNext())
{
list.Add(((object)enumerator3.Current/*cast due to .constrained prefix*/).ToString());
}
List<string> list2 = new List<string>();
Enumerator<InteractablePreset, int> enumerator4 = val2.prices.GetEnumerator();
while (enumerator4.MoveNext())
{
KeyValuePair<InteractablePreset, int> current3 = enumerator4.Current;
if ((SoCustomComparison)(object)current3.Key != (SoCustomComparison)null)
{
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(3, 3);
defaultInterpolatedStringHandler.AppendFormatted(((Object)current3.Key).name);
defaultInterpolatedStringHandler.AppendLiteral("=");
defaultInterpolatedStringHandler.AppendFormatted(current3.Value);
defaultInterpolatedStringHandler.AppendLiteral("(");
RetailItemPreset retailItem = current3.Key.retailItem;
defaultInterpolatedStringHandler.AppendFormatted((retailItem != null) ? new CompanyCategory?(retailItem.desireCategory) : ((CompanyCategory?)null));
defaultInterpolatedStringHandler.AppendLiteral(")");
list2.Add(defaultInterpolatedStringHandler.ToStringAndClear());
}
}
ManualLogSource logger2 = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(69, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Probe] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(val2.address.favouredCustomers.Count);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" regular customers (citizens whose favourite place this is)");
}
logger2.LogInfo(val);
ManualLogSource logger3 = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(56, 5, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Probe] ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": preset '");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)val2.preset).name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("' categories [");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", list));
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("] ");
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("records sales=");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<bool>(val2.preset.recordSalesData);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", menu: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(string.Join(", ", list2));
}
logger3.LogInfo(val);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Probe failed: " + ex.Message));
}
}
}
[HarmonyPatch(typeof(ActionController), "ExecuteAction")]
internal static class ShopActionProbe
{
private static readonly HashSet<string> seen = new HashSet<string>();
private static void Prefix(AIActionPreset action, Interactable what, NewNode where, Actor who)
{
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015d: Expected O, but got Unknown
if (!Plugin.ProbeShops.Value || (SoCustomComparison)(object)action == (SoCustomComparison)null || (Object)(object)who == (Object)null || who.isPlayer)
{
return;
}
try
{
object obj;
if (where == null)
{
obj = null;
}
else
{
NewGameLocation gameLocation = where.gameLocation;
if (gameLocation == null)
{
obj = null;
}
else
{
NewAddress thisAsAddress = gameLocation.thisAsAddress;
obj = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
}
Company val = (Company)obj;
Business business = Store.Get(val);
if (business == null)
{
return;
}
Human val2 = ((Il2CppObjectBase)who).TryCast<Human>();
object obj2;
if (val2 == null)
{
obj2 = null;
}
else
{
Occupation job = val2.job;
obj2 = ((job != null) ? job.employer : null);
}
bool flag = obj2 != null && val2.job.employer.companyID == val.companyID;
string item = $"{((val2 != null) ? new int?(val2.humanID) : ((int?)null))}|{((Object)action).name}|{Mathf.FloorToInt(SessionData.Instance.gameTime)}";
if (!seen.Add(item))
{
return;
}
object obj3;
if (val2 == null)
{
obj3 = null;
}
else
{
NewAIController ai = ((Actor)val2).ai;
if (ai == null)
{
obj3 = null;
}
else
{
NewAIGoal currentGoal = ai.currentGoal;
if (currentGoal == null)
{
obj3 = null;
}
else
{
AIGoalPreset preset = currentGoal.preset;
obj3 = ((preset != null) ? ((Object)preset).name : null);
}
}
}
string text = (string)obj3;
ManualLogSource logger = Plugin.Logger;
bool flag2 = default(bool);
BepInExInfoLogInterpolatedStringHandler val3 = new BepInExInfoLogInterpolatedStringHandler(34, 6, ref flag2);
if (flag2)
{
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("[Probe] ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(business.Name);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(flag ? "staff" : "visitor");
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((val2 != null) ? val2.GetCitizenName() : null);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral(" ");
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("did '");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(((Object)action).name);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' on '");
object obj4;
if (what == null)
{
obj4 = null;
}
else
{
InteractablePreset preset2 = what.preset;
obj4 = ((preset2 != null) ? ((Object)preset2).name : null);
}
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>((string)obj4);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("' (goal '");
((BepInExLogInterpolatedStringHandler)val3).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val3).AppendLiteral("')");
}
logger.LogInfo(val3);
}
catch
{
}
}
}
[HarmonyPatch]
internal static class PurchasePatch
{
private static Human buyer;
private static Company company;
private static Business business;
private static Vector3 where;
private static Sale sale;
private static bool anyHidden;
[HarmonyPatch(typeof(ActionController), "TakeConsumable")]
[HarmonyPrefix]
private static void Start(Interactable what, NewNode where, Actor who)
{
//IL_007e: Unknown result type (might be due to invalid IL or missing references)
End();
try
{
if ((Object)(object)who == (Object)null || who.isPlayer)
{
return;
}
Human val = ((Il2CppObjectBase)who).TryCast<Human>();
if ((Object)(object)val == (Object)null || what == null || (SoCustomComparison)(object)what.preset == (SoCustomComparison)null || (SoCustomComparison)(object)what.preset.menuOverride != (SoCustomComparison)null)
{
return;
}
object obj;
if (where == null)
{
obj = null;
}
else
{
NewGameLocation gameLocation = where.gameLocation;
if (gameLocation == null)
{
obj = null;
}
else
{
NewAddress thisAsAddress = gameLocation.thisAsAddress;
obj = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
}
Company val2 = (Company)obj;
if (val2 != null)
{
Begin(val, val2, what.wPos);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Purchase tracking failed: " + ex.Message));
}
}
internal static void Begin(Human human, Company c, Vector3 position)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
End();
buyer = human;
company = c;
business = Store.Get(c);
where = position;
}
[HarmonyPatch(typeof(ActionController), "TakeConsumable")]
[HarmonyFinalizer]
internal static void Finish()
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0039: Expected O, but got Unknown
try
{
if (business != null && sale == null && anyHidden)
{
business.TurnedAway++;
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(41, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(business.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
Human obj = buyer;
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>((obj != null) ? obj.GetCitizenName() : null);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" left, nothing they wanted was in stock");
}
logger.LogInfo(val);
}
}
catch
{
}
End();
}
private static void End()
{
buyer = null;
company = null;
business = null;
sale = null;
anyHidden = false;
}
[HarmonyPatch(typeof(Human), "PickConsumable")]
[HarmonyPrefix]
private static void HideOutOfStock(Human __instance, ref List<InteractablePreset> ignore)
{
if (business == null || (Object)(object)buyer == (Object)null || ((Il2CppObjectBase)__instance).Pointer != ((Il2CppObjectBase)buyer).Pointer)
{
return;
}
try
{
List<InteractablePreset> val = null;
Enumerator<InteractablePreset, int> enumerator = company.prices.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<InteractablePreset, int> current = enumerator.Current;
if ((SoCustomComparison)(object)current.Key == (SoCustomComparison)null || (business.Stock.TryGetValue(((Object)current.Key).name, out var value) && value > 0))
{
continue;
}
if (val == null)
{
val = new List<InteractablePreset>();
if (ignore != null)
{
Enumerator<InteractablePreset> enumerator2 = ignore.GetEnumerator();
while (enumerator2.MoveNext())
{
InteractablePreset current2 = enumerator2.Current;
val.Add(current2);
}
}
}
val.Add(current.Key);
}
if (val != null)
{
ignore = val;
anyHidden = true;
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Stock check failed: " + ex.Message));
}
}
[HarmonyPatch(typeof(Human), "PickConsumable")]
[HarmonyPostfix]
private static void Picked(Human __instance, InteractablePreset __result)
{
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Unknown result type (might be due to invalid IL or missing references)
//IL_014f: Expected O, but got Unknown
if ((Object)(object)buyer == (Object)null || (SoCustomComparison)(object)__result == (SoCustomComparison)null || ((Il2CppObjectBase)__instance).Pointer != ((Il2CppObjectBase)buyer).Pointer)
{
return;
}
try
{
int num = (company.prices.ContainsKey(__result) ? company.prices[__result] : 0);
Ledger.Count(company, where, num);
if (business == null)
{
return;
}
if (sale == null)
{
sale = new Sale
{
Time = SessionData.Instance.gameTime,
Customer = buyer.GetCitizenName()
};
Store.RecordSale(business, sale);
}
sale.Items.Add(new SaleItem
{
Item = ((Object)__result).name,
Price = num
});
business.Till += num;
business.TotalTaken += num;
if (business.Stock.TryGetValue(((Object)__result).name, out var value))
{
business.Stock[((Object)__result).name] = Math.Max(0, value - 1);
}
if (Plugin.LogEachSale.Value)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(16, 4, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(business.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(sale.Customer);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" bought ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(((Object)__result).name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
}
logger.LogInfo(val);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't record a sale: " + ex.Message));
}
}
}
internal static class Ledger
{
private static int hour = -1;
private static int count;
private static int money;
public static void Count(Company company, Vector3 where, int price)
{
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Expected O, but got Unknown
int num = Mathf.FloorToInt(SessionData.Instance.gameTime);
if (num != hour)
{
if (hour >= 0)
{
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(47, 3, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("[Ledger] Hour ending ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(SessionData.Instance.GameTimeToClock24String((float)num, false));
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(count);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" items sold city-wide, ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(money);
}
logger.LogInfo(val);
}
hour = num;
count = (money = 0);
}
count++;
money += price;
}
}
[HarmonyPatch(typeof(Player), "Update")]
internal static class TickPatch
{
private static float next;
private static void Postfix()
{
if (Time.unscaledTime < next)
{
return;
}
next = Time.unscaledTime + 0.5f;
try
{
if ((Object)(object)SessionData.Instance != (Object)null && SessionData.Instance.startedGame)
{
Store.Tick();
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Business tick failed: " + ex.Message));
}
}
}
[HarmonyPatch]
internal static class OwnerAccessPatch
{
[HarmonyPatch(typeof(Human), "IsTrespassing")]
[HarmonyPostfix]
private static void General(Human __instance, NewRoom room, ref int trespassEscalation, ref bool __result)
{
if (((Actor)__instance).isPlayer)
{
Clear(__instance, room, ref trespassEscalation, ref __result);
}
}
[HarmonyPatch(typeof(Player), "IsTrespassing")]
[HarmonyPostfix]
private static void PlayerCheck(Player __instance, NewRoom room, ref int trespassEscalation, ref bool __result)
{
Clear((Human)(object)__instance, room, ref trespassEscalation, ref __result);
}
private static void Clear(Human who, NewRoom room, ref int trespassEscalation, ref bool result)
{
if (((Actor)who).inAirVent)
{
return;
}
object c;
if (room == null)
{
c = null;
}
else
{
NewGameLocation gameLocation = room.gameLocation;
if (gameLocation == null)
{
c = null;
}
else
{
NewAddress thisAsAddress = gameLocation.thisAsAddress;
c = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
}
if (Store.Get((Company)c) != null)
{
result = false;
trespassEscalation = 0;
}
}
}
[HarmonyPatch(typeof(NewAIController), "IsMuggingValid")]
internal static class NoMuggingAtHomePatch
{
private static void Postfix(Human target, ref bool __result)
{
if (!__result || (Object)(object)target == (Object)null || !((Actor)target).isPlayer)
{
return;
}
NewRoom currentRoom = ((Actor)target).currentRoom;
object c;
if (currentRoom == null)
{
c = null;
}
else
{
NewGameLocation gameLocation = currentRoom.gameLocation;
if (gameLocation == null)
{
c = null;
}
else
{
NewAddress thisAsAddress = gameLocation.thisAsAddress;
c = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
}
if (Store.Get((Company)c) != null)
{
__result = false;
}
}
}
[HarmonyPatch(typeof(UpgradeEffectController), "GetUpgradeEffect")]
internal static class NoLoiteringPatch
{
private static void Postfix(Effect effect, ref float __result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Invalid comparison between Unknown and I4
if ((int)effect != 69 || __result >= 1f)
{
return;
}
try
{
Player instance = Player.Instance;
object c;
if (instance == null)
{
c = null;
}
else
{
NewGameLocation currentGameLocation = ((Actor)instance).currentGameLocation;
if (currentGameLocation == null)
{
c = null;
}
else
{
NewAddress thisAsAddress = currentGameLocation.thisAsAddress;
c = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
}
if (Store.Get((Company)c) != null)
{
__result = 1f;
}
}
catch
{
}
}
}
public class Sale
{
public float Time { get; set; }
public string Customer { get; set; }
public List<SaleItem> Items { get; set; } = new List<SaleItem>();
public int Total => Items.Sum((SaleItem i) => i.Price);
}
public class SaleItem
{
public string Item { get; set; }
public int Price { get; set; }
}
public class Transfer
{
public int Amount { get; set; }
public float Arrives { get; set; }
}
public class Order
{
public string Item { get; set; }
public int Quantity { get; set; }
public float Arrives { get; set; }
}
public class Business
{
public int CompanyId { get; set; }
public string Name { get; set; }
public int PricePaid { get; set; }
public float BoughtAt { get; set; }
public int Till { get; set; }
public int TotalTaken { get; set; }
public int TurnedAway { get; set; }
public Dictionary<string, int> Stock { get; set; } = new Dictionary<string, int>();
public List<Order> Orders { get; set; } = new List<Order>();
public List<Transfer> Transfers { get; set; } = new List<Transfer>();
public List<Sale> Sales { get; set; } = new List<Sale>();
}
internal static class Store
{
private const string FileName = "proprietor.json";
private const int MaxSales = 150;
public static Dictionary<int, Business> Owned = new Dictionary<int, Business>();
private static int lastDay = -1;
private static readonly (CompanyCategory Category, float Weight)[] CustomerCategories = new(CompanyCategory, float)[4]
{
((CompanyCategory)0, 1f),
((CompanyCategory)1, 0.6f),
((CompanyCategory)2, 0.6f),
((CompanyCategory)6, 0.8f)
};
private const string Currency = "¢";
public static Business Get(Company c)
{
if (c == null || !Owned.TryGetValue(c.companyID, out var value))
{
return null;
}
return value;
}
public static void Clear()
{
Owned = new Dictionary<int, Business>();
lastDay = -1;
}
public static void Load(SaveGameArgs args)
{
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Expected O, but got Unknown
//IL_0279: Unknown result type (might be due to invalid IL or missing references)
//IL_027f: Expected O, but got Unknown
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016b: Expected O, but got Unknown
Clear();
try
{
string saveGameDataPath = Lib.SaveGame.GetSaveGameDataPath(args, "proprietor.json");
if (File.Exists(saveGameDataPath))
{
Owned = JsonSerializer.Deserialize<List<Business>>(File.ReadAllText(saveGameDataPath)).ToDictionary((Business b) => b.CompanyId);
}
ManualLogSource logger = Plugin.Logger;
bool flag = default(bool);
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(32, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Save loaded: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Owned.Count);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" business(es) owned");
}
logger.LogInfo(val);
foreach (Business value in Owned.Values)
{
GiveKeys(FindCompany(value.CompanyId), message: false);
}
ShopProbe.DumpGoals();
if (Plugin.TestStock.Value >= 0)
{
foreach (Business value2 in Owned.Values)
{
foreach (string item in value2.Stock.Keys.ToList())
{
value2.Stock[item] = Plugin.TestStock.Value;
}
ManualLogSource logger2 = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(33, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Test: ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value2.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" stock set to ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(Plugin.TestStock.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" of each item");
}
logger2.LogInfo(val);
}
}
if (!(Plugin.TestDeliveryHours.Value >= 0f))
{
return;
}
float num = SessionData.Instance.gameTime + Plugin.TestDeliveryHours.Value;
foreach (Business value3 in Owned.Values)
{
foreach (Order order in value3.Orders)
{
if (order.Arrives > num)
{
order.Arrives = num;
}
}
}
ManualLogSource logger3 = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(48, 1, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("Test: orders on the way now arrive within ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<float>(Plugin.TestDeliveryHours.Value);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" hours");
}
logger3.LogInfo(val);
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't load owned businesses: " + ex));
}
}
public static void Save(SaveGameArgs args)
{
try
{
string saveGameDataPath = Lib.SaveGame.GetSaveGameDataPath(args, "proprietor.json");
if (Owned.Count == 0)
{
if (File.Exists(saveGameDataPath))
{
File.Delete(saveGameDataPath);
}
}
else
{
File.WriteAllText(saveGameDataPath, JsonSerializer.Serialize(Owned.Values.ToList(), new JsonSerializerOptions
{
WriteIndented = true
}));
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't save owned businesses: " + ex));
}
}
public static bool Sellable(Company c)
{
if (c != null && (Object)(object)c.director != (Object)null && !((Actor)c.director).isPlayer && c.prices != null && c.prices.Count > 0 && (Object)(object)c.address != (Object)null && !Owned.ContainsKey(c.companyID))
{
return HasCustomers(c);
}
return false;
}
public static bool HasCustomers(Company c)
{
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002e: Unknown result type (might be due to invalid IL or missing references)
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
CompanyPreset preset = c.preset;
List<CompanyCategory> val = ((preset != null) ? preset.companyCategories : null);
if (val == null)
{
return false;
}
(CompanyCategory, float)[] customerCategories = CustomerCategories;
for (int i = 0; i < customerCategories.Length; i++)
{
CompanyCategory item = customerCategories[i].Item1;
if (val.Contains(item))
{
return true;
}
}
return false;
}
public static float Regulars(Company c)
{
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
NewAddress address = c.address;
if ((Object)(object)address == (Object)null)
{
return 0f;
}
float num = 0f;
Enumerator<Human> enumerator = address.favouredCustomers.GetEnumerator();
NewAddress val2 = default(NewAddress);
while (enumerator.MoveNext())
{
Human current = enumerator.Current;
if ((Object)(object)current == (Object)null)
{
continue;
}
(CompanyCategory, float)[] customerCategories = CustomerCategories;
for (int i = 0; i < customerCategories.Length; i++)
{
var (val, num2) = customerCategories[i];
if (current.favouritePlaces.TryGetValue(val, ref val2) && (Object)(object)val2 != (Object)null && ((Il2CppObjectBase)val2).Pointer == ((Il2CppObjectBase)address).Pointer)
{
num += num2;
}
}
}
return num;
}
public static int Price(Company c)
{
NewAddress address = c.address;
float num = Mathf.Clamp01((address != null) ? address.normalizedLandValue : 0.5f);
float num2 = ((float)Plugin.BasePrice.Value + (float)Plugin.PricePerRegular.Value * Regulars(c)) * (0.7f + 0.8f * num) * MenuFactor(c);
return Mathf.Max(50, Mathf.RoundToInt(num2 / 50f) * 50);
}
public static float MenuFactor(Company c)
{
List<KeyValuePair<InteractablePreset, int>> list = Menu(c);
if (list.Count == 0)
{
return 1f;
}
return Mathf.Clamp(Mathf.Sqrt((float)list.Average((KeyValuePair<InteractablePreset, int> kv) => kv.Value) / Plugin.TypicalMenuPrice.Value), 0.7f, 2f);
}
public static Business Buy(Company c, int price)
{
Business business = new Business
{
CompanyId = c.companyID,
Name = c.name,
PricePaid = price,
BoughtAt = SessionData.Instance.gameTime
};
foreach (KeyValuePair<InteractablePreset, int> item in Menu(c))
{
business.Stock[((Object)item.Key).name] = Plugin.StartingStock.Value;
}
Owned[c.companyID] = business;
GiveKeys(c, message: true);
return business;
}
public static int Sell(Company c, out string message)
{
Business business = Get(c);
int num = Mathf.RoundToInt((float)business.PricePaid * Plugin.SellBackShare.Value);
int num2 = Math.Max(0, num + business.Till + business.Transfers.Sum((Transfer t) => t.Amount));
Owned.Remove(business.CompanyId);
if (num2 > 0)
{
GameplayController.Instance.AddMoney(num2, true, "proprietor_sell");
}
message = $"You sold {business.Name} for {"¢"}{num2}" + ((num2 > num) ? $" ({"¢"}{num} for the business, plus {"¢"}{num2 - num} from the till)" : ((num2 < num) ? $" ({"¢"}{num} for the business, less {"¢"}{num - num2} the till owed)" : ""));
return num2;
}
public static void GiveKeys(Company c, bool message)
{
try
{
if ((Object)(object)((c != null) ? c.address : null) != (Object)null && (Object)(object)Player.Instance != (Object)null)
{
((Actor)Player.Instance).AddToKeyring(c.address, message);
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Couldn't hand over the keys: " + ex.Message));
}
}
public static List<KeyValuePair<InteractablePreset, int>> Menu(Company c)
{
List<KeyValuePair<InteractablePreset, int>> list = new List<KeyValuePair<InteractablePreset, int>>();
Enumerator<InteractablePreset, int> enumerator = c.prices.GetEnumerator();
while (enumerator.MoveNext())
{
KeyValuePair<InteractablePreset, int> current = enumerator.Current;
if ((SoCustomComparison)(object)current.Key != (SoCustomComparison)null)
{
list.Add(new KeyValuePair<InteractablePreset, int>(current.Key, current.Value));
}
}
return list.OrderBy((KeyValuePair<InteractablePreset, int> kv) => ItemName(((Object)kv.Key).name)).ToList();
}
public static string ItemName(string preset)
{
return Strings.Get("evidence.names", preset, (Casing)0, false, false, false, (Human)null);
}
public static int UnitCost(int price)
{
return Mathf.Max(1, Mathf.CeilToInt((float)price * Plugin.WholesaleShare.Value));
}
public static void RecordSale(Business b, Sale sale)
{
b.Sales.Insert(0, sale);
if (b.Sales.Count > 150)
{
b.Sales.RemoveAt(b.Sales.Count - 1);
}
}
public static bool PlaceOrder(Business b, string item, int price, out string message)
{
int value = Plugin.OrderSize.Value;
int num = UnitCost(price) * value;
int num2 = Math.Min(b.Till, num);
int num3 = num - num2;
if (num3 > GameplayController.Instance.money)
{
message = $"Not enough money: the order costs ¢{num}";
return false;
}
b.Till -= num2;
if (num3 > 0)
{
GameplayController.Instance.AddMoney(-num3, true, "proprietor_order");
}
int num4 = Random.Range(Plugin.MinDeliveryDays.Value, Plugin.MaxDeliveryDays.Value + 1);
float arrives = TodayMidnight() + (float)num4 * 24f + Random.Range(7f, 11f);
if (Plugin.TestDeliveryHours.Value >= 0f)
{
arrives = SessionData.Instance.gameTime + Plugin.TestDeliveryHours.Value;
num4 = 0;
}
b.Orders.Add(new Order
{
Item = item,
Quantity = value,
Arrives = arrives
});
message = $"Ordered {value} {ItemName(item)} for ¢{num}" + ((num3 > 0) ? $" (¢{num3} from your wallet)" : "") + ((num4 > 0) ? $", arriving in {num4} days" : ", arriving soon (test setting)");
return true;
}
public static int TransferNet(int till)
{
return Math.Max(0, till - Mathf.RoundToInt((float)Math.Max(0, till) * Plugin.TransferFee.Value));
}
public static string Transfer(Business b)
{
int num = TransferNet(b.Till);
int num2 = b.Till - num;
b.Transfers.Add(new Transfer
{
Amount = num,
Arrives = TodayMidnight() + 24f + Plugin.TransferHour.Value
});
b.Till = 0;
return $"Courier booked: {"¢"}{num} arrives tomorrow morning" + ((num2 > 0) ? $" ({"¢"}{num2} fee)" : "");
}
public static void Tick()
{
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Expected O, but got Unknown
//IL_0275: Unknown result type (might be due to invalid IL or missing references)
//IL_027c: Expected O, but got Unknown
if (Owned.Count == 0 || (Object)(object)SessionData.Instance == (Object)null)
{
return;
}
float now = SessionData.Instance.gameTime;
bool flag = default(bool);
foreach (Business value2 in Owned.Values)
{
BepInExInfoLogInterpolatedStringHandler val;
foreach (Transfer item in value2.Transfers.Where((Transfer t) => t.Arrives <= now).ToList())
{
GameplayController.Instance.AddMoney(item.Amount, true, "proprietor_transfer");
value2.Transfers.Remove(item);
Plugin.Message($"{value2.Name}: courier delivered {"¢"}{item.Amount}");
ManualLogSource logger = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(25, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value2.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": transfer of ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(item.Amount);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" delivered");
}
logger.LogInfo(val);
}
List<Order> list = value2.Orders.Where((Order o) => o.Arrives <= now).ToList();
if (list.Count == 0)
{
continue;
}
foreach (Order item2 in list)
{
value2.Stock[item2.Item] = (value2.Stock.TryGetValue(item2.Item, out var value) ? value : 0) + item2.Quantity;
value2.Orders.Remove(item2);
}
string text = string.Join(", ", list.Select((Order o) => o.Quantity + " " + ItemName(o.Item)));
Plugin.Message(value2.Name + ": delivery arrived (" + text + ")");
ManualLogSource logger2 = Plugin.Logger;
val = new BepInExInfoLogInterpolatedStringHandler(21, 2, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value2.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": delivery arrived (");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(text);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(")");
}
logger2.LogInfo(val);
}
int num = DayNumber();
if (lastDay < 0)
{
lastDay = num;
}
else if (num != lastDay)
{
for (int num2 = lastDay; num2 < num; num2++)
{
PayWages();
}
lastDay = num;
}
}
private static void PayWages()
{
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01cb: Expected O, but got Unknown
bool flag = default(bool);
foreach (Business value in Owned.Values)
{
Company obj = FindCompany(value.CompanyId);
int valueOrDefault = ((obj == null) ? ((int?)null) : obj.companyRoster?.Count).GetValueOrDefault();
int num = valueOrDefault * Plugin.WagePerStaff.Value;
int num2 = Math.Min(Math.Max(0, value.Till), num);
int num3 = Math.Min(num - num2, Math.Max(0, GameplayController.Instance.money));
int num4 = num - num2 - num3;
value.Till -= num2 + num4;
if (num3 > 0)
{
GameplayController.Instance.AddMoney(-num3, false, "proprietor_wages");
}
string text = ((num3 > 0) ? $" (¢{num3} from your wallet)" : "");
if (num4 > 0)
{
text += $", ¢{num4} owed from the till";
}
Plugin.Message($"{value.Name}: paid ¢{num} in wages{text}. Till: ¢{value.Till}", num4 == 0);
ManualLogSource logger = Plugin.Logger;
BepInExInfoLogInterpolatedStringHandler val = new BepInExInfoLogInterpolatedStringHandler(60, 7, ref flag);
if (flag)
{
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<string>(value.Name);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(": wages ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" for ");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(valueOrDefault);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(" staff: till ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num2);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", wallet ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num3);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral(", unpaid ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(num4);
((BepInExLogInterpolatedStringHandler)val).AppendLiteral("; till now ¢");
((BepInExLogInterpolatedStringHandler)val).AppendFormatted<int>(value.Till);
}
logger.LogInfo(val);
}
}
public static float TodayMidnight()
{
return SessionData.Instance.gameTime - SessionData.Instance.decimalClock;
}
public static int DayNumber()
{
return Mathf.RoundToInt(TodayMidnight() / 24f);
}
public static int DaysUntil(float time)
{
return Mathf.FloorToInt((time - TodayMidnight()) / 24f);
}
public static Company FindCompany(int id)
{
Enumerator<Company> enumerator = CityData.Instance.companyDirectory.GetEnumerator();
while (enumerator.MoveNext())
{
Company current = enumerator.Current;
if (current != null && current.companyID == id)
{
return current;
}
}
return null;
}
}
[HarmonyPatch(typeof(ActionController), "ExecuteAction")]
internal static class SupermarketPatch
{
private static readonly Dictionary<int, float> lastBought = new Dictionary<int, float>();
private static void Postfix(AIActionPreset action, Interactable what, NewNode where, Actor who)
{
//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
if ((SoCustomComparison)(object)action == (SoCustomComparison)null || (Object)(object)who == (Object)null || who.isPlayer || ((Object)action).name != "ShopForGroceries")
{
return;
}
try
{
object obj;
if (where == null)
{
obj = null;
}
else
{
NewGameLocation gameLocation = where.gameLocation;
if (gameLocation == null)
{
obj = null;
}
else
{
NewAddress thisAsAddress = gameLocation.thisAsAddress;
obj = ((thisAsAddress != null) ? thisAsAddress.company : null);
}
}
Company val = (Company)obj;
if (Store.Get(val) == null)
{
return;
}
Human val2 = ((Il2CppObjectBase)who).TryCast<Human>();
if ((Object)(object)val2 == (Object)null)
{
return;
}
float gameTime = SessionData.Instance.gameTime;
if (lastBought.TryGetValue(val2.humanID, out var value) && gameTime - value < 1f)
{
return;
}
lastBought[val2.humanID] = gameTime;
PurchasePatch.Begin(val2, val, (what != null) ? what.wPos : ((Component)val2).transform.position);
try
{
Dictionary<InteractablePreset, int> prices = val.prices;
List<InteractablePreset> val3 = new List<InteractablePreset>();
int num = Random.Range(1, 4);
int num2 = default(int);
for (int i = 0; i < num; i++)
{
InteractablePreset val4 = val2.PickConsumable(ref prices, ref num2, val3);
if (!((SoCustomComparison)(object)val4 == (SoCustomComparison)null))
{
val3.Add(val4);
continue;
}
break;
}
}
finally
{
PurchasePatch.Finish();
}
}
catch (Exception ex)
{
Plugin.Logger.LogError((object)("Supermarket purchase failed: " + ex.Message));
}
}
}
}