

using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using HarmonyLib;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppNewtonsoft.Json.Linq;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Dialogue;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Money;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.Persistence;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Quests;
using Il2CppScheduleOne.UI;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppSystem.IO;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using NPCLaunderers;
using NPCLaunderers.LaundererSaveManager;
using NPCLaunderers.NPCScripts;
using NPCLaunderers.UI;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "NPCLaunderers", "1.0.4", "weedeej", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: IgnoresAccessChecksTo("")]
[assembly: AssemblyCompany("NPCLaunderers_IL2CPP")]
[assembly: AssemblyConfiguration("IL2CPP")]
[assembly: AssemblyFileVersion("1.0.3")]
[assembly: AssemblyInformationalVersion("1.0.0+682c2e2e6d9bf095bafdd6deb7abc6058e71655c")]
[assembly: AssemblyProduct("NPCLaunderers_IL2CPP")]
[assembly: AssemblyTitle("NPCLaunderers_IL2CPP")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace NPCLaunderers
{
public class Core : MelonMod
{
[CompilerGenerated]
private sealed class <DelayedStart>d__3 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedStart>d__3(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSecondsRealtime(5f);
<>1__state = 1;
return true;
case 1:
{
<>1__state = -1;
Action action = delegate
{
foreach (Launderer item in Object.FindObjectsOfType<Launderer>())
{
item.laundererData.Save();
}
};
Action action2 = delegate
{
foreach (Launderer item2 in Object.FindObjectsOfType<Launderer>())
{
item2.WeekPass();
}
};
Action action3 = delegate
{
foreach (Launderer item3 in Object.FindObjectsOfType<Launderer>())
{
item3.DayPass();
}
};
Singleton<SaveManager>.Instance.onSaveStart.AddListener(UnityAction.op_Implicit(action));
TimeManager instance = NetworkSingleton<TimeManager>.Instance;
instance.onWeekPass += Action.op_Implicit(action2);
TimeManager instance2 = NetworkSingleton<TimeManager>.Instance;
instance2.onDayPass += Action.op_Implicit(action3);
return false;
}
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private Il2CppAssetBundle bundle;
public override void OnInitializeMelon()
{
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Expected O, but got Unknown
MelonPreferences.CreateCategory("NPCLaunderers", "NPCLaunderers Settings");
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableEnvy", true, "Enable Envy", "Allows your launderers to get envy of what you earn and request more cut.", false, false, (ValueValidator)null);
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableCutDecreaseEvent", true, "Enable Request Product", "Allows your launderers to request a product to reduce cut", false, false, (ValueValidator)null);
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableNPCInvestment", true, "Enable NPC Investment", "Allows your launderers to invest in your business if you are on a streak with them. You will earn money, and they will too.", false, false, (ValueValidator)null);
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableDividendAlerts", true, "Enable Dividends Alert", "[Works only with NPCInvestment ON]\nReceive daily notification for dividends you earned if you have very good relationship with launderers.", false, false, (ValueValidator)null);
MelonPreferences.Save();
ClassInjector.RegisterTypeInIl2Cpp<Launderer>();
ClassInjector.RegisterTypeInIl2Cpp<LaundererData>();
try
{
Stream manifestResourceStream = ((MelonBase)this).MelonAssembly.Assembly.GetManifestResourceStream("NPCLaunderers.Assets.launderers.assetbundle");
if (manifestResourceStream == null)
{
((MelonBase)this).Unregister("AssetBundle stream not found", false);
return;
}
byte[] array;
using (MemoryStream memoryStream = new MemoryStream())
{
manifestResourceStream.CopyTo(memoryStream);
array = memoryStream.ToArray();
}
Stream val = (Stream)new MemoryStream(Il2CppStructArray<byte>.op_Implicit(array));
bundle = Il2CppAssetBundleManager.LoadFromStream(val);
}
catch (Exception value)
{
((MelonBase)this).Unregister($"Failed to load AssetBundle. Please report to dev: {value}", false);
return;
}
((MelonBase)this).LoggerInstance.Msg("Initialized.");
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName);
if (sceneName == "Main")
{
MelonCoroutines.Start(DelayedStart());
}
}
[IteratorStateMachine(typeof(<DelayedStart>d__3))]
private IEnumerator DelayedStart()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedStart>d__3(0);
}
}
}
namespace NPCLaunderers.UI
{
public class LaundererUI
{
private bool isOpen;
private Launderer launderer;
public GameObject gameObject;
private Il2CppAssetBundle bundle;
public LaundererUI(Launderer launderer)
{
this.launderer = launderer;
Il2CppAssetBundle[] array = Il2CppAssetBundleManager.GetAllLoadedAssetBundles().ToArray();
if (array.Length == 1)
{
bundle = array[0];
return;
}
Il2CppAssetBundle[] array2 = array;
foreach (Il2CppAssetBundle val in array2)
{
if (val.Contains("assets/laundererui.prefab"))
{
bundle = val;
break;
}
}
}
public void SetLaunderer(Launderer launderer)
{
this.launderer = launderer;
}
public void Open()
{
if (!isOpen)
{
Show();
isOpen = true;
}
}
public void Close()
{
if (isOpen)
{
Hide();
isOpen = false;
}
}
private void Show()
{
gameObject = bundle.LoadAsset<GameObject>("assets/laundererui.prefab");
gameObject = Object.Instantiate<GameObject>(gameObject);
VisualElement val = UQueryExtensions.Q<VisualElement>(gameObject.GetComponent<UIDocument>().rootVisualElement, "LaundererContent", (string)null);
((TextElement)UQueryExtensions.Q<Label>(UQueryExtensions.Q<VisualElement>(val, "Header", (string)null), "Version", (string)null)).text = ((MelonBase)MelonAssembly.FindMelonInstance<Core>()).Info.Version;
VisualElement obj = UQueryExtensions.Q<VisualElement>(val, "buttons", (string)null);
Button val2 = UQueryExtensions.Q<Button>(obj, "btn_close", (string)null);
Button obj2 = UQueryExtensions.Q<Button>(obj, "btn_submit", (string)null);
IntegerField amountField = UQueryExtensions.Q<IntegerField>(val, "NumberInput", (string)null);
Label obj3 = UQueryExtensions.Q<Label>((VisualElement)(object)amountField, "NpcName", (string)null);
((BaseField<int>)(object)amountField).label = ((BaseField<int>)(object)amountField).label.Replace("<MaxLaunder>", $"{launderer.laundererData.InstanceMaxLaunderAmount}");
((TextElement)obj3).text = ((TextElement)obj3).text.Replace("<NPCNAME>", launderer.nPC.fullName);
((CallbackEventHandler)obj2).RegisterCallback<ClickEvent>(EventCallback<ClickEvent>.op_Implicit((Action<ClickEvent>)delegate
{
MoneyManager instance = NetworkSingleton<MoneyManager>.Instance;
try
{
float num = ((BaseField<int>)(object)amountField).value;
if (!(num < 1f))
{
if (instance.cashBalance < num)
{
MelonLogger.Error($"Input value {num} exceeds cash balance {instance.cashBalance}");
Singleton<NotificationsManager>.Instance.SendNotification(launderer.nPC.FirstName, "<color=#f54c4c>You don't have enough money</color>", launderer.nPC.MugshotSprite, 5f, true);
}
else if (num > launderer.laundererData.InstanceMaxLaunderAmount)
{
MelonLogger.Error($"Input value {num} exceeds max launder amount {launderer.laundererData.InstanceMaxLaunderAmount}");
Singleton<NotificationsManager>.Instance.SendNotification(launderer.nPC.FirstName, $"<color=#f54c4c>Max of ${launderer.laundererData.InstanceMaxLaunderAmount}</color>", launderer.nPC.MugshotSprite, 5f, true);
}
else
{
instance.ChangeCashBalance(0f - num, true, true);
launderer.laundererData.CurrentLaunderAmount = num;
launderer.laundererData.CurrentTimeLeftSeconds = 720f;
string text = $"Laundering <color=#16F01C>${num}</color>.I will transfer <color=#6b9cff>${launderer.laundererData.ReturnLaunderAmount}</color> to your account in 12 hours.";
launderer.nPC.SendTextMessage(text);
Close();
}
}
}
catch (Exception ex)
{
MelonLogger.Error($"Failed to load LaundererUI: {ex}");
if (ex is FormatException)
{
Singleton<NotificationsManager>.Instance.SendNotification(launderer.nPC.FirstName, "<color=#f54c4c>Invalid input value</color>", launderer.nPC.MugshotSprite, 5f, true);
}
}
}), (TrickleDown)0);
((CallbackEventHandler)val2).RegisterCallback<ClickEvent>(EventCallback<ClickEvent>.op_Implicit((Action<ClickEvent>)delegate
{
Close();
}), (TrickleDown)0);
PlayerSingleton<PlayerCamera>.Instance.AddActiveUIElement(((Object)gameObject).name);
Player.Deactivate(true);
}
private void Hide()
{
PlayerSingleton<PlayerCamera>.Instance.RemoveActiveUIElement(((Object)gameObject).name);
Player.Activate();
Object.Destroy((Object)(object)gameObject);
}
}
}
namespace NPCLaunderers.LaundererSaveManager
{
[Serializable]
public class LaundererData : Object
{
public NPC NPC;
public float MinLaunderAmount;
public float MaxLaunderAmount;
public LaundererTier LaundererTier;
public double CutPercentage;
public bool isUnlocked;
public float CurrentTimeLeftSeconds;
public float CurrentLaunderAmount;
public float WeekLaunderReturn;
public float WeekCutAmount;
public string RequiredProductID;
public float InstanceMaxLaunderAmount;
public float TotalInvestment;
private string SaveFilePath;
public float ReturnLaunderAmount => Mathf.Floor(CurrentLaunderAmount - CurrentLaunderAmount * (float)(CutPercentage / 100.0));
public float CutAmount => Mathf.Floor(CurrentLaunderAmount * (float)(CutPercentage / 100.0));
public LaundererData(IntPtr ptr)
: base(ptr)
{
}
public LaundererData(NPC nPC)
{
NPC = nPC;
LaundererTier = Launderers.TierOf[nPC.FirstName];
float[] array = Launderers.LaunderAmountRanges[LaundererTier];
MinLaunderAmount = array[0];
MaxLaunderAmount = array[1];
WeekLaunderReturn = 0f;
WeekCutAmount = 0f;
CurrentLaunderAmount = 0f;
CurrentTimeLeftSeconds = 0f;
isUnlocked = false;
InstanceMaxLaunderAmount = 0f;
RequiredProductID = "";
CutPercentage = 10.0;
TotalInvestment = 0f;
string loadedGameFolderPath = Singleton<LoadManager>.Instance.LoadedGameFolderPath;
int startIndex = loadedGameFolderPath.IndexOf("Saves\\") + 5;
string[] array2 = loadedGameFolderPath.Substring(startIndex).Split(new char[1] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
SaveFilePath = Path.Combine(MelonEnvironment.UserDataDirectory, "Launderers", $"{array2[0]}_{array2[1]}_{nPC.ID}.json");
if (!Directory.Exists(Path.Combine(MelonEnvironment.UserDataDirectory, "Launderers")))
{
Directory.CreateDirectory(Path.Combine(MelonEnvironment.UserDataDirectory, "Launderers"));
}
}
public void Save()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Expected O, but got Unknown
//IL_005c: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
//IL_0082: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Expected O, but got Unknown
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: Expected O, but got Unknown
//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Expected O, but got Unknown
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f8: Expected O, but got Unknown
//IL_0109: Unknown result type (might be due to invalid IL or missing references)
//IL_0113: Expected O, but got Unknown
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Expected O, but got Unknown
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
//IL_0149: Expected O, but got Unknown
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_0164: Expected O, but got Unknown
//IL_0175: Unknown result type (might be due to invalid IL or missing references)
//IL_017f: Expected O, but got Unknown
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_019a: Expected O, but got Unknown
//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Expected O, but got Unknown
JObject val = new JObject();
((JContainer)val).Add((Object)new JProperty("FirstName", Object.op_Implicit(NPC.FirstName)));
((JContainer)val).Add((Object)new JProperty("LastName", Object.op_Implicit(NPC.LastName)));
((JContainer)val).Add((Object)new JProperty("ID", Object.op_Implicit(NPC.ID)));
((JContainer)val).Add((Object)new JProperty("Tier", Object.op_Implicit(LaundererTier.ToString())));
((JContainer)val).Add((Object)new JProperty("MinLaunderAmount", Object.op_Implicit(MinLaunderAmount)));
((JContainer)val).Add((Object)new JProperty("MaxLaunderAmount", Object.op_Implicit(MaxLaunderAmount)));
((JContainer)val).Add((Object)new JProperty("isUnlocked", Object.op_Implicit(isUnlocked)));
((JContainer)val).Add((Object)new JProperty("CutPercentage", Object.op_Implicit(CutPercentage)));
((JContainer)val).Add((Object)new JProperty("CurrentTimeLeftSeconds", Object.op_Implicit(CurrentTimeLeftSeconds)));
((JContainer)val).Add((Object)new JProperty("CurrentLaunderAmount", Object.op_Implicit(CurrentLaunderAmount)));
((JContainer)val).Add((Object)new JProperty("WeekLaunderReturn", Object.op_Implicit(WeekLaunderReturn)));
((JContainer)val).Add((Object)new JProperty("WeekCutAmount", Object.op_Implicit(WeekCutAmount)));
((JContainer)val).Add((Object)new JProperty("RequiredProductID", Object.op_Implicit(RequiredProductID)));
((JContainer)val).Add((Object)new JProperty("InstanceMaxLaunderAmount", Object.op_Implicit(InstanceMaxLaunderAmount)));
((JContainer)val).Add((Object)new JProperty("TotalInvestment", Object.op_Implicit(TotalInvestment)));
File.WriteAllText(SaveFilePath, ((Object)val).ToString());
Debug.Log(Object.op_Implicit(NPC.FirstName + " - Saved to: " + SaveFilePath));
}
public LaundererData Load()
{
if (!File.Exists(SaveFilePath))
{
return this;
}
JObject val = JObject.Parse(File.ReadAllText(SaveFilePath));
MinLaunderAmount = ((JToken)val).Value<float>(Object.op_Implicit("MinLaunderAmount"));
MaxLaunderAmount = ((JToken)val).Value<float>(Object.op_Implicit("MaxLaunderAmount"));
CutPercentage = ((JToken)val).Value<double>(Object.op_Implicit("CutPercentage"));
isUnlocked = ((JToken)val).Value<bool>(Object.op_Implicit("isUnlocked"));
CurrentTimeLeftSeconds = ((JToken)val).Value<float>(Object.op_Implicit("CurrentTimeLeftSeconds"));
CurrentLaunderAmount = ((JToken)val).Value<float>(Object.op_Implicit("CurrentLaunderAmount"));
LaundererTier = (LaundererTier)Enum.Parse(typeof(LaundererTier), ((JToken)val).Value<string>(Object.op_Implicit("Tier")));
WeekLaunderReturn = ((JToken)val).Value<float>(Object.op_Implicit("WeekLaunderReturn"));
WeekCutAmount = ((JToken)val).Value<float>(Object.op_Implicit("WeekCutAmount"));
InstanceMaxLaunderAmount = ((JToken)val).Value<float>(Object.op_Implicit("InstanceMaxLaunderAmount"));
RequiredProductID = ((JToken)val).Value<string>(Object.op_Implicit("RequiredProductID"));
TotalInvestment = ((JToken)val).Value<float>(Object.op_Implicit("TotalInvestment"));
return this;
}
}
public enum LaundererTier
{
Low,
Medium,
High,
Highest
}
public static class Launderers
{
public static Dictionary<string, LaundererTier> TierOf = new Dictionary<string, LaundererTier>
{
{
"Donna",
LaundererTier.Low
},
{
"Dean",
LaundererTier.Low
},
{
"Jeff",
LaundererTier.Medium
},
{
"Marco",
LaundererTier.Medium
},
{
"Jeremy",
LaundererTier.High
},
{
"Fiona",
LaundererTier.High
},
{
"Ray",
LaundererTier.Highest
},
{
"Herbert",
LaundererTier.Highest
}
};
public static Dictionary<LaundererTier, float[]> LaunderAmountRanges = new Dictionary<LaundererTier, float[]>
{
{
LaundererTier.Low,
new float[2] { 1000f, 3500f }
},
{
LaundererTier.Medium,
new float[2] { 5500f, 7500f }
},
{
LaundererTier.High,
new float[2] { 9500f, 11000f }
},
{
LaundererTier.Highest,
new float[2] { 11500f, 13500f }
}
};
}
}
namespace NPCLaunderers.Patches
{
[HarmonyPatch(typeof(NPC))]
internal class NPCPatch
{
[HarmonyPostfix]
[HarmonyPatch("Start")]
public static void AddComponent(NPC __instance)
{
if (Launderers.TierOf.ContainsKey(__instance.FirstName))
{
((Component)__instance).gameObject.AddComponent<Launderer>();
}
}
}
}
namespace NPCLaunderers.NPCScripts
{
public class Launderer : MonoBehaviour
{
[CompilerGenerated]
private sealed class <>c__DisplayClass23_0
{
public Launderer <>4__this;
public Contract contract;
internal void <AddContractListener>b__0(EQuestState result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected I4, but got Unknown
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
switch (result - 2)
{
case 2:
{
double num2 = Mathf.Floor((float)Random.Range(1, 10));
string text;
if (<>4__this.laundererData.CutPercentage >= 60.0)
{
text = ".";
<>4__this.nPC.SendTextMessage(text);
break;
}
while (<>4__this.laundererData.CutPercentage + num2 > 60.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
<>4__this.laundererData.CutPercentage += num2;
<>4__this.laundererData.RequiredProductID = "";
text = $"Ignoring me huh. I'm increasing my cut to <color=#ff6b6b>{<>4__this.laundererData.CutPercentage}%</color>";
<>4__this.nPC.SendTextMessage(text);
break;
}
case 1:
{
double num2 = Mathf.Floor((float)Random.Range(1, 5));
string text;
if (<>4__this.laundererData.CutPercentage >= 60.0)
{
text = "Sometimes, I don't feel like working with you at all.";
<>4__this.nPC.SendTextMessage(text);
break;
}
while (<>4__this.laundererData.CutPercentage + num2 > 60.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
<>4__this.laundererData.CutPercentage += num2;
<>4__this.laundererData.RequiredProductID = "";
text = $"I don't like the way you acted earlier. I'm increasing my cut to <color=#ff6b6b>{<>4__this.laundererData.CutPercentage}%</color>";
<>4__this.nPC.SendTextMessage(text);
break;
}
case 0:
{
double num = Mathf.Floor((float)Random.Range(1, 10));
string text;
if (<>4__this.laundererData.CutPercentage == 5.0)
{
text = "Thanks!";
<>4__this.nPC.SendTextMessage(text);
break;
}
while (<>4__this.laundererData.CutPercentage - num < 5.0)
{
num = Mathf.Floor((float)Random.Range(1, 10));
}
<>4__this.laundererData.CutPercentage -= num;
<>4__this.laundererData.RequiredProductID = "";
text = $"Hey, I appreciate you bringing me the goods. I'll reduce my cut to <color=#ff6b6b>{<>4__this.laundererData.CutPercentage}%</color>.";
<>4__this.nPC.SendTextMessage(text);
break;
}
default:
MelonLogger.Msg((object)result);
break;
}
<>4__this.laundererData.RequiredProductID = "";
((UnityEventBase)((Quest)contract).onQuestEnd).RemoveAllListeners();
<>4__this.withContract = false;
}
}
[CompilerGenerated]
private sealed class <AddContractListener>d__23 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
public Contract contract;
private <>c__DisplayClass23_0 <>8__1;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <AddContractListener>d__23(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>8__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>8__1 = new <>c__DisplayClass23_0();
<>8__1.<>4__this = <>4__this;
<>8__1.contract = contract;
<>2__current = (object)new WaitForSecondsRealtime(3f);
<>1__state = 1;
return true;
case 1:
{
<>1__state = -1;
if (launderer.withContract)
{
return false;
}
_ = "Deal for " + launderer.nPC.FirstName;
Action<EQuestState> action = delegate(EQuestState result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected I4, but got Unknown
//IL_02fd: Unknown result type (might be due to invalid IL or missing references)
switch (result - 2)
{
case 2:
{
double num3 = Mathf.Floor((float)Random.Range(1, 10));
if (<>8__1.<>4__this.laundererData.CutPercentage >= 60.0)
{
string text = ".";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
else
{
while (<>8__1.<>4__this.laundererData.CutPercentage + num3 > 60.0)
{
num3 = Mathf.Floor((float)Random.Range(1, 10));
}
<>8__1.<>4__this.laundererData.CutPercentage += num3;
<>8__1.<>4__this.laundererData.RequiredProductID = "";
string text = $"Ignoring me huh. I'm increasing my cut to <color=#ff6b6b>{<>8__1.<>4__this.laundererData.CutPercentage}%</color>";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
break;
}
case 1:
{
double num3 = Mathf.Floor((float)Random.Range(1, 5));
if (<>8__1.<>4__this.laundererData.CutPercentage >= 60.0)
{
string text = "Sometimes, I don't feel like working with you at all.";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
else
{
while (<>8__1.<>4__this.laundererData.CutPercentage + num3 > 60.0)
{
num3 = Mathf.Floor((float)Random.Range(1, 10));
}
<>8__1.<>4__this.laundererData.CutPercentage += num3;
<>8__1.<>4__this.laundererData.RequiredProductID = "";
string text = $"I don't like the way you acted earlier. I'm increasing my cut to <color=#ff6b6b>{<>8__1.<>4__this.laundererData.CutPercentage}%</color>";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
break;
}
case 0:
{
double num2 = Mathf.Floor((float)Random.Range(1, 10));
if (<>8__1.<>4__this.laundererData.CutPercentage == 5.0)
{
string text = "Thanks!";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
else
{
while (<>8__1.<>4__this.laundererData.CutPercentage - num2 < 5.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
<>8__1.<>4__this.laundererData.CutPercentage -= num2;
<>8__1.<>4__this.laundererData.RequiredProductID = "";
string text = $"Hey, I appreciate you bringing me the goods. I'll reduce my cut to <color=#ff6b6b>{<>8__1.<>4__this.laundererData.CutPercentage}%</color>.";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
break;
}
default:
MelonLogger.Msg((object)result);
break;
}
<>8__1.<>4__this.laundererData.RequiredProductID = "";
((UnityEventBase)((Quest)<>8__1.contract).onQuestEnd).RemoveAllListeners();
<>8__1.<>4__this.withContract = false;
};
((Quest)<>8__1.contract).onQuestEnd.AddListener(UnityAction<EQuestState>.op_Implicit(action));
launderer.withContract = true;
QuestHUDUI hudUI = ((Quest)<>8__1.contract).hudUI;
if (!((TMP_Text)hudUI.MainLabel).text.Contains("EVENT"))
{
((TMP_Text)hudUI.MainLabel).text = "<color=#16F01C>[EVENT]</color> " + ((TMP_Text)hudUI.MainLabel).text;
}
MelonLogger.Msg(launderer.nPC.FirstName + ": Added active contract listner");
return false;
}
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <StartDialougeCheck>d__30 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StartDialougeCheck>d__30(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isCheckingDialouge = true;
<>2__current = (object)new WaitForSecondsRealtime(1f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if ((Object)(object)launderer.dialogueController == (Object)null)
{
launderer.dialogueController = ((Component)launderer.nPC.DialogueHandler).GetComponent<DialogueController>();
}
if (!launderer.laundererData.isUnlocked && !launderer.isDialogueInitReady && launderer.isFriendly)
{
launderer.nPC.SendTextMessage("Hey, Let me know if you need a partnership.");
launderer.upfrontInstance = Mathf.Floor(Random.Range(launderer.laundererData.MinLaunderAmount, launderer.laundererData.MaxLaunderAmount));
launderer.AddInitChoice();
}
if (launderer.laundererData.isUnlocked && !launderer.isMainDialogueReady && launderer.isFriendly)
{
launderer.SetupLaunderDialog();
}
launderer.isCheckingDialouge = false;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <StartLaundryCheck>d__29 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StartLaundryCheck>d__29(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isCheckingLaundry = true;
<>2__current = (object)new WaitForSecondsRealtime(1f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if (launderer.laundererData.isUnlocked && launderer.laundererData.CurrentLaunderAmount > 0f)
{
if (launderer.laundererData.CurrentTimeLeftSeconds > 0f)
{
launderer.laundererData.CurrentTimeLeftSeconds -= 1f;
launderer.isCheckingLaundry = false;
return false;
}
launderer.GiveLaunderedPay();
}
launderer.isCheckingLaundry = false;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <StartSavedLaundryCheck>d__31 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StartSavedLaundryCheck>d__31(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isCheckingSavedLaundry = true;
<>2__current = (object)new WaitForSecondsRealtime(3f);
<>1__state = 1;
return true;
case 1:
{
<>1__state = -1;
bool entryValue = MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableCutDecreaseEvent");
if (launderer.laundererData.isUnlocked && launderer.laundererData.RequiredProductID != "" && !launderer.withContract && entryValue)
{
launderer.LoadLaundererData();
}
launderer.isCheckingSavedLaundry = false;
return false;
}
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <UpdateFriendlyState>d__32 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <UpdateFriendlyState>d__32(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isUpdatingFriendly = true;
<>2__current = (object)new WaitForSecondsRealtime(5f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
launderer.isFriendly = launderer.nPC.RelationData.RelationDelta >= 4f;
launderer.isUpdatingFriendly = false;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public LaundererData laundererData;
public bool isMainDialogueReady;
public bool isDialogueInitReady;
public NPC nPC;
public DialogueController dialogueController;
private LaundererUI laundererUI;
private float upfrontInstance;
public bool withContract;
private bool isCheckingLaundry;
private bool isCheckingDialouge;
private bool isCheckingSavedLaundry;
private bool isUpdatingFriendly;
private bool isFriendly;
private Il2CppArrayBase<DeliveryLocation> locations;
public Launderer(IntPtr pointer)
: base(pointer)
{
}
public void Awake()
{
NPC component = ((Component)this).GetComponent<NPC>();
locations = Object.FindObjectsOfType<DeliveryLocation>();
if ((Object)(object)component == (Object)null)
{
MelonLogger.Error("Launderer component is not attached to an NPC.");
return;
}
laundererData = new LaundererData(component).Load();
nPC = component;
}
private void AddInitChoice()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
DialogueChoice newChoice = new DialogueChoice
{
Enabled = true,
ChoiceText = "How about a partnership?"
};
DialogueNodeData val = NPCUtilities.CreateDialogueInitNodeData(laundererData.MinLaunderAmount, laundererData.MaxLaunderAmount, laundererData.CutPercentage, upfrontInstance, this);
List<DialogueNodeData> val2 = new List<DialogueNodeData>();
val2.Add(val);
newChoice.Conversation = ScriptableObject.CreateInstance<DialogueContainer>();
((Object)newChoice.Conversation).name = "LAUNDER_INIT_CONTAINER";
newChoice.Conversation.DialogueNodeData = val2;
newChoice.onChoosen.AddListener(UnityAction.op_Implicit((Action)delegate
{
nPC.DialogueHandler.InitializeDialogue(newChoice.Conversation, true, "LAUNDER_INIT_NODE");
nPC.DialogueHandler.onDialogueChoiceChosen.AddListener(UnityAction<string>.op_Implicit((Action<string>)delegate(string label)
{
if (label == "ACCEPT_LAUNDER_TERMS")
{
laundererData.isUnlocked = true;
dialogueController.Choices.Remove(newChoice);
laundererData.CutPercentage = 10.0;
SendInitialMessage();
}
}));
}));
dialogueController.AddDialogueChoice(newChoice, 0);
isDialogueInitReady = true;
}
private void SendInitialMessage()
{
if (!((Object)(object)nPC == (Object)null) && !((Object)(object)dialogueController == (Object)null) && laundererData.isUnlocked)
{
string text = $"I can help you launder your money. I'll take a cut of <color=#ff6b6b>{laundererData.CutPercentage}%</color> of the amount for this week.";
nPC.SendTextMessage(text);
SetupLaunderDialog();
}
}
private void SetupLaunderDialog()
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked)
{
return;
}
if (laundererUI == null)
{
laundererUI = new LaundererUI(this);
}
DialogueChoice val = new DialogueChoice
{
Enabled = true,
ChoiceText = "Launder Dirties"
};
val.onChoosen.AddListener(UnityAction.op_Implicit((Action)delegate
{
if (laundererData.CurrentLaunderAmount > 0f || laundererData.CurrentTimeLeftSeconds > 0f)
{
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, $"Laundering <color=#16F01C>${laundererData.CurrentLaunderAmount}</color>", nPC.MugshotSprite, 5f, true);
}
else
{
laundererData.InstanceMaxLaunderAmount = Mathf.Floor(Random.Range(laundererData.MinLaunderAmount, laundererData.MaxLaunderAmount));
laundererUI.Open();
}
}));
dialogueController.AddDialogueChoice(val, 0);
isMainDialogueReady = true;
}
public void GiveLaunderedPay()
{
if (!((Object)(object)nPC == (Object)null) && !((Object)(object)dialogueController == (Object)null) && laundererData.isUnlocked)
{
NetworkSingleton<MoneyManager>.Instance.CreateOnlineTransaction($"Launderer_${nPC.FirstName}_${laundererData.CurrentLaunderAmount}_${laundererData.CutPercentage}", laundererData.ReturnLaunderAmount, 1f, "");
string text = $"Hey, I sent <color=#2e75d9>${laundererData.ReturnLaunderAmount}</color> to your bank. \n\nMy Cut: <color=#eb4034>${laundererData.CutAmount}</color>";
nPC.SendTextMessage(text);
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, $"<color=#16F01C>${laundererData.CurrentLaunderAmount}</color> Laundered", nPC.MugshotSprite, 5f, true);
laundererData.WeekLaunderReturn += laundererData.ReturnLaunderAmount;
laundererData.WeekCutAmount += laundererData.CutAmount;
laundererData.CurrentLaunderAmount = 0f;
laundererData.CurrentTimeLeftSeconds = 0f;
laundererData.InstanceMaxLaunderAmount = 0f;
}
}
public void RandomizeCut()
{
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked)
{
return;
}
double num = Random.Range(0f, 100f);
if (laundererData.WeekLaunderReturn - laundererData.WeekCutAmount > Mathf.Floor(Random.Range(laundererData.MinLaunderAmount, laundererData.MaxLaunderAmount)) && num < 30.0 && laundererData.CutPercentage <= 30.0)
{
double num2 = Mathf.Floor((float)Random.Range(1, 10));
while (laundererData.CutPercentage + num2 > 60.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
laundererData.CutPercentage += num2;
string text = $"Hey, You seem to be doing so well. To make things fair, I'm changing my cut to <color=#ff6b6b>{laundererData.CutPercentage}%</color>.";
nPC.SendTextMessage(text);
}
}
public void WeeklyInvestment()
{
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked || !(laundererData.WeekLaunderReturn >= laundererData.MinLaunderAmount * 7f))
{
return;
}
if (laundererData.CutPercentage <= 5.0)
{
double num = (double)laundererData.WeekCutAmount * 0.2;
nPC.SendTextMessage("I want to invest in your shady business, whatever that is.\n\nMore profit for you, More work for me. I just sent it to your bank.");
NetworkSingleton<MoneyManager>.Instance.CreateOnlineTransaction("Launderer_$" + nPC.FirstName + "_INVESTMENT", (float)num, 1f, nPC.FirstName + "_INVESTMENT");
laundererData.TotalInvestment += (float)num;
return;
}
double num2 = Mathf.Floor((float)Random.Range(1, 10));
while (laundererData.CutPercentage - num2 < 5.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
laundererData.CutPercentage -= num2;
string text = $"FOR OUR FUTURE TRANSACTIONS! Decreasing my cut to <color=#16F01C>{laundererData.CutPercentage}%</color>.";
nPC.SendTextMessage(text);
}
public void RequireMix(string productId = null, int amount = 3, string customMessage = "Hey, I wanna strengthen our partnership. How about we do a session.")
{
//IL_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Invalid comparison between Unknown and I4
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: 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_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0137: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0146: Expected O, but got Unknown
//IL_014e: 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)
//IL_017e: Unknown result type (might be due to invalid IL or missing references)
//IL_0183: Unknown result type (might be due to invalid IL or missing references)
//IL_0191: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Expected O, but got Unknown
//IL_01c0: Expected O, but got Unknown
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Expected O, but got Unknown
//IL_0227: Unknown result type (might be due to invalid IL or missing references)
//IL_0231: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked)
{
return;
}
ProductDefinition val;
if (productId == null)
{
int num = Random.Range(0, ProductManager.DiscoveredProducts.Count - 1);
val = ProductManager.DiscoveredProducts._items[num];
}
else
{
val = ((IEnumerable<ProductDefinition>)ProductManager.DiscoveredProducts._items).FirstOrDefault((Func<ProductDefinition, bool>)((ProductDefinition p) => ((ItemDefinition)p).ID == productId));
if ((Object)(object)val == (Object)null)
{
MelonLogger.Error("Product with ID " + productId + " not found.");
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, "<color=#f54c4c>Product not found. Launderers Mod disabled</color>", nPC.MugshotSprite, 5f, true);
MelonBase.FindMelon("NPCLaunderers", "weedeej").Unregister("Product not found. Launderers Mod disabled", false);
return;
}
}
laundererData.RequiredProductID = ((ItemDefinition)val).ID;
List<Entry> val2 = new List<Entry>();
EQuality quality = (EQuality)((laundererData.LaundererTier <= LaundererTier.Medium) ? 2 : (((int)val.DrugType == 1) ? 3 : 4));
Entry val3 = new Entry
{
ProductID = ((ItemDefinition)val).ID,
Quality = quality,
Quantity = amount
};
val2.Add(val3);
new ProductList().entries = val2;
DeliveryLocation val4 = locations[Random.Range(0, locations.Length)];
ContractInfo val5 = new ContractInfo(0f, new ProductList
{
entries = val2
}, val4.StaticGUID, new QuestWindowConfig
{
WindowStartTime = 600,
WindowEndTime = 1200,
IsEnabled = true
}, false, 1300, 0, false);
NetworkSingleton<QuestManager>.Instance.CreateContract_Networked(Player.Local.Connection, "Deal for " + nPC.FirstName, "Your launderer, " + nPC.FirstName + " wants to strengthen your partnership.", Guid.NewGuid().ToString(), true, ((NetworkBehaviour)nPC).NetworkObject, val5, new GameDateTime(1300), NetworkSingleton<TimeManager>.Instance.GetDateTime(), (NetworkObject)null);
string text = $"{customMessage}\n\nI need you to bring me <color=#6b9cff>3x {((ItemDefinition)val).Name}</color> in <b>BEST</b> quality you can get at <color=#6b9cff>6:00am to 12:00pm</color>.\nMeet me <color=#6b9cff>{val4.LocationDescription}</color>.";
nPC.SendTextMessage(text);
}
[IteratorStateMachine(typeof(<AddContractListener>d__23))]
private IEnumerator AddContractListener(Contract contract)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <AddContractListener>d__23(0)
{
<>4__this = this,
contract = contract
};
}
public void WeekPass()
{
if (!((Object)(object)nPC == (Object)null) && !((Object)(object)dialogueController == (Object)null) && laundererData.isUnlocked)
{
if (MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableEnvy"))
{
RandomizeCut();
}
if (MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableNPCInvestment"))
{
WeeklyInvestment();
}
int num = Random.Range(0, 100);
bool entryValue = MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableCutDecreaseEvent");
if (num >= 60 && entryValue)
{
RequireMix();
}
}
}
public void OnDestroy()
{
laundererData = null;
isMainDialogueReady = false;
isDialogueInitReady = false;
nPC = null;
dialogueController = null;
laundererUI = null;
upfrontInstance = 0f;
withContract = false;
}
public void DayPass()
{
if (!MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableNPCInvestment"))
{
return;
}
float[] array = Launderers.LaunderAmountRanges[LaundererTier.Low];
switch (laundererData.LaundererTier)
{
case LaundererTier.Low:
if (laundererData.TotalInvestment >= array[1])
{
PromoteTo(LaundererTier.Medium);
}
break;
case LaundererTier.Medium:
array = Launderers.LaunderAmountRanges[LaundererTier.Medium];
if (laundererData.TotalInvestment >= array[1])
{
PromoteTo(LaundererTier.High);
}
break;
case LaundererTier.High:
array = Launderers.LaunderAmountRanges[LaundererTier.High];
if (laundererData.TotalInvestment >= array[1])
{
PromoteTo(LaundererTier.Highest);
}
break;
case LaundererTier.Highest:
if (laundererData.TotalInvestment >= array[0])
{
float num = ((laundererData.TotalInvestment >= 13500f) ? 405f : (laundererData.TotalInvestment * 0.03f));
NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(num, true, false);
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, $"Dividends are being sent out <color=#16F01C>${num}</color>", nPC.MugshotSprite, 2f, true);
}
break;
}
}
public void PromoteTo(LaundererTier tier, bool silent = false)
{
float[] array = Launderers.LaunderAmountRanges[LaundererTier.High];
laundererData.LaundererTier = LaundererTier.High;
laundererData.MinLaunderAmount = array[0];
laundererData.MaxLaunderAmount = array[1];
laundererData.TotalInvestment = 0f;
if (!silent)
{
string text = $"Thanks to you I grew my business, I can now wash <color=#16F01C>${array[0]}</color> - <color=#16F01C>${array[1]}</color>";
nPC.SendTextMessage(text);
}
}
private void Update()
{
if (!isCheckingLaundry)
{
MelonCoroutines.Start(StartLaundryCheck());
}
if (!isCheckingDialouge)
{
MelonCoroutines.Start(StartDialougeCheck());
}
if (!isCheckingSavedLaundry)
{
MelonCoroutines.Start(StartSavedLaundryCheck());
}
if (!isUpdatingFriendly)
{
MelonCoroutines.Start(UpdateFriendlyState());
}
}
[IteratorStateMachine(typeof(<StartLaundryCheck>d__29))]
private IEnumerator StartLaundryCheck()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StartLaundryCheck>d__29(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<StartDialougeCheck>d__30))]
private IEnumerator StartDialougeCheck()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StartDialougeCheck>d__30(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<StartSavedLaundryCheck>d__31))]
private IEnumerator StartSavedLaundryCheck()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StartSavedLaundryCheck>d__31(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<UpdateFriendlyState>d__32))]
private IEnumerator UpdateFriendlyState()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <UpdateFriendlyState>d__32(0)
{
<>4__this = this
};
}
private void LoadLaundererData()
{
if (laundererData != null && !(laundererData.RequiredProductID == ""))
{
Contract val = ((IEnumerable<Contract>)Object.FindObjectsOfType<Contract>()).FirstOrDefault((Contract c) => (int)((Quest)c).State == 1 && ((Quest)c).GetQuestTitle().Contains(nPC.FirstName), null);
if ((Object)(object)val != (Object)null && !withContract && ((IEnumerable<Entry>)val.ProductList.entries._items).Any((Entry e) => e.ProductID == laundererData.RequiredProductID))
{
MelonCoroutines.Start(AddContractListener(val));
}
if ((Object)(object)val == (Object)null && !withContract && laundererData.RequiredProductID != "")
{
RequireMix(laundererData.RequiredProductID);
}
}
}
}
public static class NPCUtilities
{
public static DialogueNodeData CreateDialogueInitNodeData(float amount_min, float amount_max, double cut, float upfront, Launderer launderer)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00ab: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Expected O, but got Unknown
DialogueNodeData val = new DialogueNodeData();
val.DialogueNodeLabel = "LAUNDER_INIT_NODE";
val.DialogueText = $"Alright, I can wash around <color=#16F01C>${amount_min} - ${amount_max}</color> of your dirties. But there will be some cuts, of course. I'll let you know how much every week. But for now, Let us start with <color=#6b9cff>{cut}%</color> and an upfront of <color=#16F01C>${upfront}</color>";
DialogueChoiceData[] array = (DialogueChoiceData[])(object)new DialogueChoiceData[2]
{
new DialogueChoiceData
{
ChoiceLabel = "ACCEPT_LAUNDER_TERMS",
ChoiceText = "Sure, Let's do it."
},
new DialogueChoiceData
{
ChoiceLabel = "DECLINE_LAUNDER_TERMS",
ChoiceText = "Nevermind"
}
};
val.choices = Il2CppReferenceArray<DialogueChoiceData>.op_Implicit(array);
return val;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
internal IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using FishNet.Object;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using NPCLaunderers;
using NPCLaunderers.LaundererSaveManager;
using NPCLaunderers.NPCScripts;
using NPCLaunderers.UI;
using Newtonsoft.Json.Linq;
using ScheduleOne.DevUtilities;
using ScheduleOne.Dialogue;
using ScheduleOne.Economy;
using ScheduleOne.GameTime;
using ScheduleOne.ItemFramework;
using ScheduleOne.Money;
using ScheduleOne.NPCs;
using ScheduleOne.Persistence;
using ScheduleOne.PlayerScripts;
using ScheduleOne.Product;
using ScheduleOne.Quests;
using ScheduleOne.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UIElements;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "NPCLaunderers", "1.0.4", "weedeej", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("NPCLaunderers_MONO")]
[assembly: AssemblyConfiguration("MONO")]
[assembly: AssemblyFileVersion("1.0.3")]
[assembly: AssemblyInformationalVersion("1.0.0+682c2e2e6d9bf095bafdd6deb7abc6058e71655c")]
[assembly: AssemblyProduct("NPCLaunderers_MONO")]
[assembly: AssemblyTitle("NPCLaunderers_MONO")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.3.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.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace NPCLaunderers
{
public class Core : MelonMod
{
[Serializable]
[CompilerGenerated]
private sealed class <>c
{
public static readonly <>c <>9 = new <>c();
public static UnityAction <>9__3_0;
public static Action <>9__3_1;
public static Action <>9__3_2;
internal void <DelayedStart>b__3_0()
{
Launderer[] array = Object.FindObjectsOfType<Launderer>();
for (int i = 0; i < array.Length; i++)
{
array[i].laundererData.Save();
}
}
internal void <DelayedStart>b__3_1()
{
Launderer[] array = Object.FindObjectsOfType<Launderer>();
for (int i = 0; i < array.Length; i++)
{
array[i].WeekPass();
}
}
internal void <DelayedStart>b__3_2()
{
Launderer[] array = Object.FindObjectsOfType<Launderer>();
for (int i = 0; i < array.Length; i++)
{
array[i].DayPass();
}
}
}
[CompilerGenerated]
private sealed class <DelayedStart>d__3 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <DelayedStart>d__3(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Expected O, but got Unknown
//IL_004b: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
switch (<>1__state)
{
default:
return false;
case 0:
<>1__state = -1;
<>2__current = (object)new WaitForSecondsRealtime(5f);
<>1__state = 1;
return true;
case 1:
{
<>1__state = -1;
object obj = <>c.<>9__3_0;
if (obj == null)
{
UnityAction val = delegate
{
Launderer[] array3 = Object.FindObjectsOfType<Launderer>();
for (int k = 0; k < array3.Length; k++)
{
array3[k].laundererData.Save();
}
};
<>c.<>9__3_0 = val;
obj = (object)val;
}
UnityAction val2 = (UnityAction)obj;
Action b = delegate
{
Launderer[] array2 = Object.FindObjectsOfType<Launderer>();
for (int j = 0; j < array2.Length; j++)
{
array2[j].WeekPass();
}
};
Action b2 = delegate
{
Launderer[] array = Object.FindObjectsOfType<Launderer>();
for (int i = 0; i < array.Length; i++)
{
array[i].DayPass();
}
};
Singleton<SaveManager>.Instance.onSaveStart.AddListener(val2);
TimeManager instance = NetworkSingleton<TimeManager>.Instance;
instance.onWeekPass = (Action)Delegate.Combine(instance.onWeekPass, b);
TimeManager instance2 = NetworkSingleton<TimeManager>.Instance;
instance2.onDayPass = (Action)Delegate.Combine(instance2.onDayPass, b2);
return false;
}
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
private AssetBundle bundle;
public override void OnInitializeMelon()
{
MelonPreferences.CreateCategory("NPCLaunderers", "NPCLaunderers Settings");
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableEnvy", true, "Enable Envy", "Allows your launderers to get envy of what you earn and request more cut.", false, false, (ValueValidator)null);
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableCutDecreaseEvent", true, "Enable Request Product", "Allows your launderers to request a product to reduce cut", false, false, (ValueValidator)null);
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableNPCInvestment", true, "Enable NPC Investment", "Allows your launderers to invest in your business if you are on a streak with them. You will earn money, and they will too.", false, false, (ValueValidator)null);
MelonPreferences.CreateEntry<bool>("NPCLaunderers", "EnableDividendAlerts", true, "Enable Dividends Alert", "[Works only with NPCInvestment ON]\nReceive daily notification for dividends you earned if you have very good relationship with launderers.", false, false, (ValueValidator)null);
MelonPreferences.Save();
try
{
Stream manifestResourceStream = ((MelonBase)this).MelonAssembly.Assembly.GetManifestResourceStream("NPCLaunderers.Assets.launderers.assetbundle");
if (manifestResourceStream == null)
{
((MelonBase)this).Unregister("AssetBundle stream not found", false);
return;
}
bundle = AssetBundle.LoadFromStream(manifestResourceStream);
}
catch (Exception arg)
{
((MelonBase)this).Unregister($"Failed to load AssetBundle. Please report to dev: {arg}", false);
return;
}
((MelonBase)this).LoggerInstance.Msg("Initialized.");
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
((MelonMod)this).OnSceneWasLoaded(buildIndex, sceneName);
if (sceneName == "Main")
{
MelonCoroutines.Start(DelayedStart());
}
}
[IteratorStateMachine(typeof(<DelayedStart>d__3))]
private IEnumerator DelayedStart()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <DelayedStart>d__3(0);
}
}
}
namespace NPCLaunderers.UI
{
public class LaundererUI
{
private bool isOpen;
private Launderer launderer;
public GameObject gameObject;
private AssetBundle bundle;
public LaundererUI(Launderer launderer)
{
this.launderer = launderer;
List<AssetBundle> list = AssetBundle.GetAllLoadedAssetBundles().ToList();
if (list.Count == 1)
{
bundle = list[0];
return;
}
foreach (AssetBundle item in list)
{
if (((Object)item).name == "launderers.assetbundle")
{
bundle = item;
break;
}
}
}
public void SetLaunderer(Launderer launderer)
{
this.launderer = launderer;
}
public void Open()
{
if (!isOpen)
{
Show();
isOpen = true;
}
}
public void Close()
{
if (isOpen)
{
Hide();
isOpen = false;
}
}
private void Show()
{
gameObject = bundle.LoadAsset<GameObject>("assets/laundererui.prefab");
gameObject = Object.Instantiate<GameObject>(gameObject);
VisualElement val = UQueryExtensions.Q<VisualElement>(gameObject.GetComponent<UIDocument>().rootVisualElement, "LaundererContent", (string)null);
((TextElement)UQueryExtensions.Q<Label>(UQueryExtensions.Q<VisualElement>(val, "Header", (string)null), "Version", (string)null)).text = ((MelonBase)MelonAssembly.FindMelonInstance<Core>()).Info.Version;
VisualElement obj = UQueryExtensions.Q<VisualElement>(val, "buttons", (string)null);
Button val2 = UQueryExtensions.Q<Button>(obj, "btn_close", (string)null);
Button obj2 = UQueryExtensions.Q<Button>(obj, "btn_submit", (string)null);
IntegerField amountField = UQueryExtensions.Q<IntegerField>(val, "NumberInput", (string)null);
Label obj3 = UQueryExtensions.Q<Label>((VisualElement)(object)amountField, "NpcName", (string)null);
((BaseField<int>)(object)amountField).label = ((BaseField<int>)(object)amountField).label.Replace("<MaxLaunder>", $"{launderer.laundererData.InstanceMaxLaunderAmount}");
((TextElement)obj3).text = ((TextElement)obj3).text.Replace("<NPCNAME>", launderer.nPC.fullName);
((CallbackEventHandler)obj2).RegisterCallback<ClickEvent>((EventCallback<ClickEvent>)delegate
{
MoneyManager instance = NetworkSingleton<MoneyManager>.Instance;
try
{
float num = ((BaseField<int>)(object)amountField).value;
if (!(num < 1f))
{
if (instance.cashBalance < num)
{
MelonLogger.Error($"Input value {num} exceeds cash balance {instance.cashBalance}");
Singleton<NotificationsManager>.Instance.SendNotification(launderer.nPC.FirstName, "<color=#f54c4c>You don't have enough money</color>", launderer.nPC.MugshotSprite, 5f, true);
}
else if (num > launderer.laundererData.InstanceMaxLaunderAmount)
{
MelonLogger.Error($"Input value {num} exceeds max launder amount {launderer.laundererData.InstanceMaxLaunderAmount}");
Singleton<NotificationsManager>.Instance.SendNotification(launderer.nPC.FirstName, $"<color=#f54c4c>Max of ${launderer.laundererData.InstanceMaxLaunderAmount}</color>", launderer.nPC.MugshotSprite, 5f, true);
}
else
{
instance.ChangeCashBalance(0f - num, true, true);
launderer.laundererData.CurrentLaunderAmount = num;
launderer.laundererData.CurrentTimeLeftSeconds = 720f;
string text = $"Laundering <color=#16F01C>${num}</color>.I will transfer <color=#6b9cff>${launderer.laundererData.ReturnLaunderAmount}</color> to your account in 12 hours.";
launderer.nPC.SendTextMessage(text);
Close();
}
}
}
catch (Exception ex)
{
MelonLogger.Error($"Failed to load LaundererUI: {ex}");
if (ex is FormatException)
{
Singleton<NotificationsManager>.Instance.SendNotification(launderer.nPC.FirstName, "<color=#f54c4c>Invalid input value</color>", launderer.nPC.MugshotSprite, 5f, true);
}
}
}, (TrickleDown)0);
((CallbackEventHandler)val2).RegisterCallback<ClickEvent>((EventCallback<ClickEvent>)delegate
{
Close();
}, (TrickleDown)0);
PlayerSingleton<PlayerCamera>.Instance.AddActiveUIElement(((Object)gameObject).name);
Player.Deactivate(true);
}
private void Hide()
{
PlayerSingleton<PlayerCamera>.Instance.RemoveActiveUIElement(((Object)gameObject).name);
Player.Activate();
Object.Destroy((Object)(object)gameObject);
}
}
}
namespace NPCLaunderers.LaundererSaveManager
{
[Serializable]
public class LaundererData
{
public NPC NPC;
public float MinLaunderAmount;
public float MaxLaunderAmount;
public LaundererTier LaundererTier;
public double CutPercentage;
public bool isUnlocked;
public float CurrentTimeLeftSeconds;
public float CurrentLaunderAmount;
public float WeekLaunderReturn;
public float WeekCutAmount;
public string RequiredProductID;
public float InstanceMaxLaunderAmount;
public float TotalInvestment;
private string SaveFilePath;
public float ReturnLaunderAmount => Mathf.Floor(CurrentLaunderAmount - CurrentLaunderAmount * (float)(CutPercentage / 100.0));
public float CutAmount => Mathf.Floor(CurrentLaunderAmount * (float)(CutPercentage / 100.0));
public LaundererData(NPC nPC)
{
NPC = nPC;
LaundererTier = Launderers.TierOf[nPC.FirstName];
float[] array = Launderers.LaunderAmountRanges[LaundererTier];
MinLaunderAmount = array[0];
MaxLaunderAmount = array[1];
WeekLaunderReturn = 0f;
WeekCutAmount = 0f;
CurrentLaunderAmount = 0f;
CurrentTimeLeftSeconds = 0f;
isUnlocked = false;
InstanceMaxLaunderAmount = 0f;
RequiredProductID = "";
CutPercentage = 10.0;
TotalInvestment = 0f;
string loadedGameFolderPath = Singleton<LoadManager>.Instance.LoadedGameFolderPath;
int startIndex = loadedGameFolderPath.IndexOf("Saves\\") + 5;
string[] array2 = loadedGameFolderPath.Substring(startIndex).Split(new char[1] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
SaveFilePath = Path.Combine(MelonEnvironment.UserDataDirectory, "Launderers", array2[0] + "_" + array2[1] + "_" + nPC.ID + ".json");
if (!Directory.Exists(Path.Combine(MelonEnvironment.UserDataDirectory, "Launderers")))
{
Directory.CreateDirectory(Path.Combine(MelonEnvironment.UserDataDirectory, "Launderers"));
}
}
public void Save()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Expected O, but got Unknown
//IL_006e: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Expected O, but got Unknown
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0093: Expected O, but got Unknown
//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Expected O, but got Unknown
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00c9: Expected O, but got Unknown
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00ff: Expected O, but got Unknown
//IL_0110: Unknown result type (might be due to invalid IL or missing references)
//IL_011a: Expected O, but got Unknown
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Expected O, but got Unknown
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Expected O, but got Unknown
//IL_015c: Unknown result type (might be due to invalid IL or missing references)
//IL_0166: Expected O, but got Unknown
//IL_0177: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Expected O, but got Unknown
//IL_0192: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Expected O, but got Unknown
JObject val = new JObject();
((JContainer)val).Add((object)new JProperty("FirstName", (object)NPC.FirstName));
((JContainer)val).Add((object)new JProperty("LastName", (object)NPC.LastName));
((JContainer)val).Add((object)new JProperty("ID", (object)NPC.ID));
((JContainer)val).Add((object)new JProperty("Tier", (object)LaundererTier.ToString()));
((JContainer)val).Add((object)new JProperty("MinLaunderAmount", (object)MinLaunderAmount));
((JContainer)val).Add((object)new JProperty("MaxLaunderAmount", (object)MaxLaunderAmount));
((JContainer)val).Add((object)new JProperty("isUnlocked", (object)isUnlocked));
((JContainer)val).Add((object)new JProperty("CutPercentage", (object)CutPercentage));
((JContainer)val).Add((object)new JProperty("CurrentTimeLeftSeconds", (object)CurrentTimeLeftSeconds));
((JContainer)val).Add((object)new JProperty("CurrentLaunderAmount", (object)CurrentLaunderAmount));
((JContainer)val).Add((object)new JProperty("WeekLaunderReturn", (object)WeekLaunderReturn));
((JContainer)val).Add((object)new JProperty("WeekCutAmount", (object)WeekCutAmount));
((JContainer)val).Add((object)new JProperty("RequiredProductID", (object)RequiredProductID));
((JContainer)val).Add((object)new JProperty("InstanceMaxLaunderAmount", (object)InstanceMaxLaunderAmount));
((JContainer)val).Add((object)new JProperty("TotalInvestment", (object)TotalInvestment));
File.WriteAllText(SaveFilePath, ((object)val).ToString());
Debug.Log((object)(NPC.FirstName + " - Saved to: " + SaveFilePath));
}
public LaundererData Load()
{
if (!File.Exists(SaveFilePath))
{
return this;
}
JObject val = JObject.Parse(File.ReadAllText(SaveFilePath));
MinLaunderAmount = ((JToken)val).Value<float>((object)"MinLaunderAmount");
MaxLaunderAmount = ((JToken)val).Value<float>((object)"MaxLaunderAmount");
CutPercentage = ((JToken)val).Value<double>((object)"CutPercentage");
isUnlocked = ((JToken)val).Value<bool>((object)"isUnlocked");
CurrentTimeLeftSeconds = ((JToken)val).Value<float>((object)"CurrentTimeLeftSeconds");
CurrentLaunderAmount = ((JToken)val).Value<float>((object)"CurrentLaunderAmount");
LaundererTier = (LaundererTier)Enum.Parse(typeof(LaundererTier), ((JToken)val).Value<string>((object)"Tier"));
WeekLaunderReturn = ((JToken)val).Value<float>((object)"WeekLaunderReturn");
WeekCutAmount = ((JToken)val).Value<float>((object)"WeekCutAmount");
InstanceMaxLaunderAmount = ((JToken)val).Value<float>((object)"InstanceMaxLaunderAmount");
RequiredProductID = ((JToken)val).Value<string>((object)"RequiredProductID");
TotalInvestment = ((JToken)val).Value<float>((object)"TotalInvestment");
return this;
}
}
public enum LaundererTier
{
Low,
Medium,
High,
Highest
}
public static class Launderers
{
public static Dictionary<string, LaundererTier> TierOf = new Dictionary<string, LaundererTier>
{
{
"Donna",
LaundererTier.Low
},
{
"Dean",
LaundererTier.Low
},
{
"Jeff",
LaundererTier.Medium
},
{
"Marco",
LaundererTier.Medium
},
{
"Jeremy",
LaundererTier.High
},
{
"Fiona",
LaundererTier.High
},
{
"Ray",
LaundererTier.Highest
},
{
"Herbert",
LaundererTier.Highest
}
};
public static Dictionary<LaundererTier, float[]> LaunderAmountRanges = new Dictionary<LaundererTier, float[]>
{
{
LaundererTier.Low,
new float[2] { 1000f, 3500f }
},
{
LaundererTier.Medium,
new float[2] { 5500f, 7500f }
},
{
LaundererTier.High,
new float[2] { 9500f, 11000f }
},
{
LaundererTier.Highest,
new float[2] { 11500f, 13500f }
}
};
}
}
namespace NPCLaunderers.Patches
{
[HarmonyPatch(typeof(NPC))]
internal class NPCPatch
{
[HarmonyPostfix]
[HarmonyPatch("Start")]
public static void AddComponent(NPC __instance)
{
if (Launderers.TierOf.ContainsKey(__instance.FirstName))
{
((Component)__instance).gameObject.AddComponent<Launderer>();
}
}
}
}
namespace NPCLaunderers.NPCScripts
{
public class Launderer : MonoBehaviour
{
[CompilerGenerated]
private sealed class <>c__DisplayClass22_0
{
public Launderer <>4__this;
public Contract contract;
internal void <AddContractListener>b__0(EQuestState result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected I4, but got Unknown
//IL_029a: Unknown result type (might be due to invalid IL or missing references)
switch (result - 2)
{
case 2:
{
double num2 = Mathf.Floor((float)Random.Range(1, 10));
string text;
if (<>4__this.laundererData.CutPercentage >= 60.0)
{
text = ".";
<>4__this.nPC.SendTextMessage(text);
break;
}
while (<>4__this.laundererData.CutPercentage + num2 > 60.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
<>4__this.laundererData.CutPercentage += num2;
<>4__this.laundererData.RequiredProductID = "";
text = $"Ignoring me huh. I'm increasing my cut to <color=#ff6b6b>{<>4__this.laundererData.CutPercentage}%</color>";
<>4__this.nPC.SendTextMessage(text);
break;
}
case 1:
{
double num2 = Mathf.Floor((float)Random.Range(1, 5));
string text;
if (<>4__this.laundererData.CutPercentage >= 60.0)
{
text = "Sometimes, I don't feel like working with you at all.";
<>4__this.nPC.SendTextMessage(text);
break;
}
while (<>4__this.laundererData.CutPercentage + num2 > 60.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
<>4__this.laundererData.CutPercentage += num2;
<>4__this.laundererData.RequiredProductID = "";
text = $"I don't like the way you acted earlier. I'm increasing my cut to <color=#ff6b6b>{<>4__this.laundererData.CutPercentage}%</color>";
<>4__this.nPC.SendTextMessage(text);
break;
}
case 0:
{
double num = Mathf.Floor((float)Random.Range(1, 10));
string text;
if (<>4__this.laundererData.CutPercentage == 5.0)
{
text = "Thanks!";
<>4__this.nPC.SendTextMessage(text);
break;
}
while (<>4__this.laundererData.CutPercentage - num < 5.0)
{
num = Mathf.Floor((float)Random.Range(1, 10));
}
<>4__this.laundererData.CutPercentage -= num;
<>4__this.laundererData.RequiredProductID = "";
text = $"Hey, I appreciate you bringing me the goods. I'll reduce my cut to <color=#ff6b6b>{<>4__this.laundererData.CutPercentage}%</color>.";
<>4__this.nPC.SendTextMessage(text);
break;
}
default:
MelonLogger.Msg((object)result);
break;
}
<>4__this.laundererData.RequiredProductID = "";
((UnityEventBase)((Quest)contract).onQuestEnd).RemoveAllListeners();
<>4__this.withContract = false;
}
}
[CompilerGenerated]
private sealed class <AddContractListener>d__22 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
public Contract contract;
private <>c__DisplayClass22_0 <>8__1;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <AddContractListener>d__22(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>8__1 = null;
<>1__state = -2;
}
private bool MoveNext()
{
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
<>8__1 = new <>c__DisplayClass22_0();
<>8__1.<>4__this = <>4__this;
<>8__1.contract = contract;
<>2__current = (object)new WaitForSecondsRealtime(3f);
<>1__state = 1;
return true;
case 1:
{
<>1__state = -1;
if (launderer.withContract)
{
return false;
}
_ = "Deal for " + launderer.nPC.FirstName;
UnityAction<EQuestState> val = delegate(EQuestState result)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected I4, but got Unknown
//IL_029a: Unknown result type (might be due to invalid IL or missing references)
switch (result - 2)
{
case 2:
{
double num3 = Mathf.Floor((float)Random.Range(1, 10));
if (<>8__1.<>4__this.laundererData.CutPercentage >= 60.0)
{
string text = ".";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
else
{
while (<>8__1.<>4__this.laundererData.CutPercentage + num3 > 60.0)
{
num3 = Mathf.Floor((float)Random.Range(1, 10));
}
<>8__1.<>4__this.laundererData.CutPercentage += num3;
<>8__1.<>4__this.laundererData.RequiredProductID = "";
string text = $"Ignoring me huh. I'm increasing my cut to <color=#ff6b6b>{<>8__1.<>4__this.laundererData.CutPercentage}%</color>";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
break;
}
case 1:
{
double num3 = Mathf.Floor((float)Random.Range(1, 5));
if (<>8__1.<>4__this.laundererData.CutPercentage >= 60.0)
{
string text = "Sometimes, I don't feel like working with you at all.";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
else
{
while (<>8__1.<>4__this.laundererData.CutPercentage + num3 > 60.0)
{
num3 = Mathf.Floor((float)Random.Range(1, 10));
}
<>8__1.<>4__this.laundererData.CutPercentage += num3;
<>8__1.<>4__this.laundererData.RequiredProductID = "";
string text = $"I don't like the way you acted earlier. I'm increasing my cut to <color=#ff6b6b>{<>8__1.<>4__this.laundererData.CutPercentage}%</color>";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
break;
}
case 0:
{
double num2 = Mathf.Floor((float)Random.Range(1, 10));
if (<>8__1.<>4__this.laundererData.CutPercentage == 5.0)
{
string text = "Thanks!";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
else
{
while (<>8__1.<>4__this.laundererData.CutPercentage - num2 < 5.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
<>8__1.<>4__this.laundererData.CutPercentage -= num2;
<>8__1.<>4__this.laundererData.RequiredProductID = "";
string text = $"Hey, I appreciate you bringing me the goods. I'll reduce my cut to <color=#ff6b6b>{<>8__1.<>4__this.laundererData.CutPercentage}%</color>.";
<>8__1.<>4__this.nPC.SendTextMessage(text);
}
break;
}
default:
MelonLogger.Msg((object)result);
break;
}
<>8__1.<>4__this.laundererData.RequiredProductID = "";
((UnityEventBase)((Quest)<>8__1.contract).onQuestEnd).RemoveAllListeners();
<>8__1.<>4__this.withContract = false;
};
((Quest)<>8__1.contract).onQuestEnd.AddListener(val);
launderer.withContract = true;
QuestHUDUI hudUI = ((Quest)<>8__1.contract).hudUI;
if (!((TMP_Text)hudUI.MainLabel).text.Contains("EVENT"))
{
((TMP_Text)hudUI.MainLabel).text = "<color=#16F01C>[EVENT]</color> " + ((TMP_Text)hudUI.MainLabel).text;
}
MelonLogger.Msg(launderer.nPC.FirstName + ": Added active contract listner");
return false;
}
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <StartDialougeCheck>d__29 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StartDialougeCheck>d__29(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isCheckingDialouge = true;
<>2__current = (object)new WaitForSecondsRealtime(1f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if ((Object)(object)launderer.dialogueController == (Object)null)
{
launderer.dialogueController = ((Component)launderer.nPC.DialogueHandler).GetComponent<DialogueController>();
}
if (!launderer.laundererData.isUnlocked && !launderer.isDialogueInitReady && launderer.isFriendly)
{
launderer.nPC.SendTextMessage("Hey, Let me know if you need a partnership.");
launderer.upfrontInstance = Mathf.Floor(Random.Range(launderer.laundererData.MinLaunderAmount, launderer.laundererData.MaxLaunderAmount));
launderer.AddInitChoice();
}
if (launderer.laundererData.isUnlocked && !launderer.isMainDialogueReady && launderer.isFriendly)
{
launderer.SetupLaunderDialog();
}
launderer.isCheckingDialouge = false;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <StartLaundryCheck>d__28 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StartLaundryCheck>d__28(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isCheckingLaundry = true;
<>2__current = (object)new WaitForSecondsRealtime(1f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
if (launderer.laundererData.isUnlocked && launderer.laundererData.CurrentLaunderAmount > 0f)
{
if (launderer.laundererData.CurrentTimeLeftSeconds > 0f)
{
launderer.laundererData.CurrentTimeLeftSeconds -= 1f;
launderer.isCheckingLaundry = false;
return false;
}
launderer.GiveLaunderedPay();
}
launderer.isCheckingLaundry = false;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <StartSavedLaundryCheck>d__30 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <StartSavedLaundryCheck>d__30(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isCheckingSavedLaundry = true;
<>2__current = (object)new WaitForSecondsRealtime(3f);
<>1__state = 1;
return true;
case 1:
{
<>1__state = -1;
bool entryValue = MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableCutDecreaseEvent");
if (launderer.laundererData.isUnlocked && launderer.laundererData.RequiredProductID != "" && !launderer.withContract && entryValue)
{
launderer.LoadLaundererData();
}
launderer.isCheckingSavedLaundry = false;
return false;
}
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
[CompilerGenerated]
private sealed class <UpdateFriendlyState>d__31 : IEnumerator<object>, IEnumerator, IDisposable
{
private int <>1__state;
private object <>2__current;
public Launderer <>4__this;
object IEnumerator<object>.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
object IEnumerator.Current
{
[DebuggerHidden]
get
{
return <>2__current;
}
}
[DebuggerHidden]
public <UpdateFriendlyState>d__31(int <>1__state)
{
this.<>1__state = <>1__state;
}
[DebuggerHidden]
void IDisposable.Dispose()
{
<>1__state = -2;
}
private bool MoveNext()
{
//IL_002b: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Expected O, but got Unknown
int num = <>1__state;
Launderer launderer = <>4__this;
switch (num)
{
default:
return false;
case 0:
<>1__state = -1;
launderer.isUpdatingFriendly = true;
<>2__current = (object)new WaitForSecondsRealtime(5f);
<>1__state = 1;
return true;
case 1:
<>1__state = -1;
launderer.isFriendly = launderer.nPC.RelationData.RelationDelta >= 4f;
launderer.isUpdatingFriendly = false;
return false;
}
}
bool IEnumerator.MoveNext()
{
//ILSpy generated this explicit interface implementation from .override directive in MoveNext
return this.MoveNext();
}
[DebuggerHidden]
void IEnumerator.Reset()
{
throw new NotSupportedException();
}
}
public LaundererData laundererData;
public bool isMainDialogueReady;
public bool isDialogueInitReady;
public NPC nPC;
public DialogueController dialogueController;
private LaundererUI laundererUI;
private float upfrontInstance;
public bool withContract;
private bool isCheckingLaundry;
private bool isCheckingDialouge;
private bool isCheckingSavedLaundry;
private bool isUpdatingFriendly;
private bool isFriendly;
private DeliveryLocation[] locations;
public void Awake()
{
NPC component = ((Component)this).GetComponent<NPC>();
locations = Object.FindObjectsOfType<DeliveryLocation>();
if ((Object)(object)component == (Object)null)
{
MelonLogger.Error("Launderer component is not attached to an NPC.");
return;
}
laundererData = new LaundererData(component).Load();
nPC = component;
}
private void AddInitChoice()
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0013: Unknown result type (might be due to invalid IL or missing references)
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b7: Expected O, but got Unknown
DialogueChoice newChoice = new DialogueChoice
{
Enabled = true,
ChoiceText = "How about a partnership?"
};
DialogueNodeData item = NPCUtilities.CreateDialogueInitNodeData(laundererData.MinLaunderAmount, laundererData.MaxLaunderAmount, laundererData.CutPercentage, upfrontInstance, this);
List<DialogueNodeData> list = new List<DialogueNodeData>();
list.Add(item);
newChoice.Conversation = ScriptableObject.CreateInstance<DialogueContainer>();
((Object)newChoice.Conversation).name = "LAUNDER_INIT_CONTAINER";
newChoice.Conversation.DialogueNodeData = list;
newChoice.onChoosen.AddListener((UnityAction)delegate
{
nPC.DialogueHandler.InitializeDialogue(newChoice.Conversation, true, "LAUNDER_INIT_NODE");
nPC.DialogueHandler.onDialogueChoiceChosen.AddListener((UnityAction<string>)delegate(string label)
{
if (label == "ACCEPT_LAUNDER_TERMS")
{
NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(0f - upfrontInstance, true, true);
laundererData.isUnlocked = true;
dialogueController.Choices.Remove(newChoice);
laundererData.CutPercentage = 10.0;
SendInitialMessage();
}
});
});
dialogueController.AddDialogueChoice(newChoice, 0);
isDialogueInitReady = true;
}
private void SendInitialMessage()
{
if (!((Object)(object)nPC == (Object)null) && !((Object)(object)dialogueController == (Object)null) && laundererData.isUnlocked)
{
string text = $"I can help you launder your money. I'll take a cut of <color=#ff6b6b>{laundererData.CutPercentage}%</color> of the amount for this week.";
nPC.SendTextMessage(text);
SetupLaunderDialog();
}
}
private void SetupLaunderDialog()
{
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Expected O, but got Unknown
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked)
{
return;
}
if (laundererUI == null)
{
laundererUI = new LaundererUI(this);
}
DialogueChoice val = new DialogueChoice
{
Enabled = true,
ChoiceText = "Launder Dirties"
};
val.onChoosen.AddListener((UnityAction)delegate
{
if (laundererData.CurrentLaunderAmount > 0f || laundererData.CurrentTimeLeftSeconds > 0f)
{
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, $"Laundering <color=#16F01C>${laundererData.CurrentLaunderAmount}</color>", nPC.MugshotSprite, 5f, true);
}
else
{
laundererData.InstanceMaxLaunderAmount = Mathf.Floor(Random.Range(laundererData.MinLaunderAmount, laundererData.MaxLaunderAmount));
laundererUI.Open();
}
});
dialogueController.AddDialogueChoice(val, 0);
isMainDialogueReady = true;
}
public void GiveLaunderedPay()
{
if (!((Object)(object)nPC == (Object)null) && !((Object)(object)dialogueController == (Object)null) && laundererData.isUnlocked)
{
NetworkSingleton<MoneyManager>.Instance.CreateOnlineTransaction($"Launderer_${nPC.FirstName}_${laundererData.CurrentLaunderAmount}_${laundererData.CutPercentage}", laundererData.ReturnLaunderAmount, 1f, "");
string text = $"Hey, I sent <color=#2e75d9>${laundererData.ReturnLaunderAmount}</color> to your bank. \n\nMy Cut: <color=#eb4034>${laundererData.CutAmount}</color>";
nPC.SendTextMessage(text);
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, $"<color=#16F01C>${laundererData.CurrentLaunderAmount}</color> Laundered", nPC.MugshotSprite, 5f, true);
laundererData.WeekLaunderReturn += laundererData.ReturnLaunderAmount;
laundererData.WeekCutAmount += laundererData.CutAmount;
laundererData.CurrentLaunderAmount = 0f;
laundererData.CurrentTimeLeftSeconds = 0f;
laundererData.InstanceMaxLaunderAmount = 0f;
}
}
public void RandomizeCut()
{
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked)
{
return;
}
double num = Random.Range(0f, 100f);
if (laundererData.WeekLaunderReturn - laundererData.WeekCutAmount > Mathf.Floor(Random.Range(laundererData.MinLaunderAmount, laundererData.MaxLaunderAmount)) && num < 30.0 && laundererData.CutPercentage <= 30.0)
{
double num2 = Mathf.Floor((float)Random.Range(1, 10));
while (laundererData.CutPercentage + num2 > 60.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
laundererData.CutPercentage += num2;
string text = $"Hey, You seem to be doing so well. To make things fair, I'm changing my cut to <color=#ff6b6b>{laundererData.CutPercentage}%</color>.";
nPC.SendTextMessage(text);
}
}
public void WeeklyInvestment()
{
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked || !(laundererData.WeekLaunderReturn >= laundererData.MinLaunderAmount * 7f))
{
return;
}
if (laundererData.CutPercentage <= 5.0)
{
double num = (double)laundererData.WeekCutAmount * 0.2;
nPC.SendTextMessage("I want to invest in your shady business, whatever that is.\n\nMore profit for you, More work for me. I just sent it to your bank.");
NetworkSingleton<MoneyManager>.Instance.CreateOnlineTransaction("Launderer_$" + nPC.FirstName + "_INVESTMENT", (float)num, 1f, nPC.FirstName + "_INVESTMENT");
laundererData.TotalInvestment += (float)num;
return;
}
double num2 = Mathf.Floor((float)Random.Range(1, 10));
while (laundererData.CutPercentage - num2 < 5.0)
{
num2 = Mathf.Floor((float)Random.Range(1, 10));
}
laundererData.CutPercentage -= num2;
string text = $"FOR OUR FUTURE TRANSACTIONS! Decreasing my cut to <color=#16F01C>{laundererData.CutPercentage}%</color>.";
nPC.SendTextMessage(text);
}
public void RequireMix(string productId = null, int amount = 3, string customMessage = "Hey, I wanna strengthen our partnership. How about we do a session.")
{
//IL_010e: Unknown result type (might be due to invalid IL or missing references)
//IL_0114: Invalid comparison between Unknown and I4
//IL_011a: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: 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_012d: 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_013c: Expected O, but got Unknown
//IL_0144: 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_016d: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
//IL_0180: Unknown result type (might be due to invalid IL or missing references)
//IL_0185: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_019b: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Expected O, but got Unknown
//IL_01af: Expected O, but got Unknown
//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
//IL_01b1: Expected O, but got Unknown
//IL_0216: Unknown result type (might be due to invalid IL or missing references)
//IL_0220: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)nPC == (Object)null || (Object)(object)dialogueController == (Object)null || !laundererData.isUnlocked)
{
return;
}
ProductDefinition val;
if (productId == null)
{
int index = Random.Range(0, ProductManager.DiscoveredProducts.Count - 1);
val = ProductManager.DiscoveredProducts[index];
}
else
{
val = ProductManager.DiscoveredProducts.Find((ProductDefinition p) => ((ItemDefinition)p).ID == productId);
if ((Object)(object)val == (Object)null)
{
MelonLogger.Error("Product with ID " + productId + " not found.");
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, "<color=#f54c4c>Product not found. Launderers Mod disabled</color>", nPC.MugshotSprite, 5f, true);
MelonBase.FindMelon("NPCLaunderers", "weedeej").Unregister("Product not found. Launderers Mod disabled", false);
return;
}
}
laundererData.RequiredProductID = ((ItemDefinition)val).ID;
List<Entry> list = new List<Entry>();
EQuality quality = (EQuality)((laundererData.LaundererTier <= LaundererTier.Medium) ? 2 : (((int)val.DrugType == 1) ? 3 : 4));
Entry item = new Entry
{
ProductID = ((ItemDefinition)val).ID,
Quality = quality,
Quantity = amount
};
list.Add(item);
new ProductList().entries = list;
DeliveryLocation val2 = locations[Random.Range(0, locations.Length)];
ContractInfo val3 = new ContractInfo(0f, new ProductList
{
entries = list
}, val2.StaticGUID, new QuestWindowConfig
{
WindowStartTime = 600,
WindowEndTime = 1200,
IsEnabled = true
}, false, 1300, 0, false);
NetworkSingleton<QuestManager>.Instance.CreateContract_Networked(Player.Local.Connection, "Deal for " + nPC.FirstName, "Your launderer, " + nPC.FirstName + " wants to strengthen your partnership.", Guid.NewGuid().ToString(), true, ((NetworkBehaviour)nPC).NetworkObject, val3, new GameDateTime(1300), NetworkSingleton<TimeManager>.Instance.GetDateTime(), (NetworkObject)null);
string text = customMessage + "\n\nI need you to bring me <color=#6b9cff>3x " + ((ItemDefinition)val).Name + "</color> in <b>BEST</b> quality you can get at <color=#6b9cff>6:00am to 12:00pm</color>.\nMeet me <color=#6b9cff>" + val2.LocationDescription + "</color>.";
nPC.SendTextMessage(text);
}
[IteratorStateMachine(typeof(<AddContractListener>d__22))]
private IEnumerator AddContractListener(Contract contract)
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <AddContractListener>d__22(0)
{
<>4__this = this,
contract = contract
};
}
public void WeekPass()
{
if (!((Object)(object)nPC == (Object)null) && !((Object)(object)dialogueController == (Object)null) && laundererData.isUnlocked)
{
if (MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableEnvy"))
{
RandomizeCut();
}
if (MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableNPCInvestment"))
{
WeeklyInvestment();
}
int num = Random.Range(0, 100);
bool entryValue = MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableCutDecreaseEvent");
if (num >= 60 && entryValue)
{
RequireMix();
}
}
}
public void OnDestroy()
{
laundererData = null;
isMainDialogueReady = false;
isDialogueInitReady = false;
nPC = null;
dialogueController = null;
laundererUI = null;
upfrontInstance = 0f;
withContract = false;
}
public void DayPass()
{
if (!MelonPreferences.GetEntryValue<bool>("NPCLaunderers", "EnableNPCInvestment"))
{
return;
}
float[] array = Launderers.LaunderAmountRanges[LaundererTier.Low];
switch (laundererData.LaundererTier)
{
case LaundererTier.Low:
if (laundererData.TotalInvestment >= array[1])
{
PromoteTo(LaundererTier.Medium);
}
break;
case LaundererTier.Medium:
array = Launderers.LaunderAmountRanges[LaundererTier.Medium];
if (laundererData.TotalInvestment >= array[1])
{
PromoteTo(LaundererTier.High);
}
break;
case LaundererTier.High:
array = Launderers.LaunderAmountRanges[LaundererTier.High];
if (laundererData.TotalInvestment >= array[1])
{
PromoteTo(LaundererTier.Highest);
}
break;
case LaundererTier.Highest:
if (laundererData.TotalInvestment >= array[0])
{
float num = ((laundererData.TotalInvestment >= 13500f) ? 405f : (laundererData.TotalInvestment * 0.03f));
NetworkSingleton<MoneyManager>.Instance.ChangeCashBalance(num, true, false);
Singleton<NotificationsManager>.Instance.SendNotification(nPC.fullName, $"Dividends are being sent out <color=#16F01C>${num}</color>", nPC.MugshotSprite, 2f, true);
}
break;
}
}
public void PromoteTo(LaundererTier tier, bool silent = false)
{
float[] array = Launderers.LaunderAmountRanges[LaundererTier.High];
laundererData.LaundererTier = LaundererTier.High;
laundererData.MinLaunderAmount = array[0];
laundererData.MaxLaunderAmount = array[1];
laundererData.TotalInvestment = 0f;
if (!silent)
{
string text = $"Thanks to you I grew my business, I can now wash <color=#16F01C>${array[0]}</color> - <color=#16F01C>${array[1]}</color>";
nPC.SendTextMessage(text);
}
}
private void Update()
{
if (!isCheckingLaundry)
{
MelonCoroutines.Start(StartLaundryCheck());
}
if (!isCheckingDialouge)
{
MelonCoroutines.Start(StartDialougeCheck());
}
if (!isCheckingSavedLaundry)
{
MelonCoroutines.Start(StartSavedLaundryCheck());
}
if (!isUpdatingFriendly)
{
MelonCoroutines.Start(UpdateFriendlyState());
}
}
[IteratorStateMachine(typeof(<StartLaundryCheck>d__28))]
private IEnumerator StartLaundryCheck()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StartLaundryCheck>d__28(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<StartDialougeCheck>d__29))]
private IEnumerator StartDialougeCheck()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StartDialougeCheck>d__29(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<StartSavedLaundryCheck>d__30))]
private IEnumerator StartSavedLaundryCheck()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <StartSavedLaundryCheck>d__30(0)
{
<>4__this = this
};
}
[IteratorStateMachine(typeof(<UpdateFriendlyState>d__31))]
private IEnumerator UpdateFriendlyState()
{
//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
return new <UpdateFriendlyState>d__31(0)
{
<>4__this = this
};
}
private void LoadLaundererData()
{
if (laundererData != null && !(laundererData.RequiredProductID == ""))
{
Contract val = ((IEnumerable<Contract>)Object.FindObjectsOfType<Contract>()).FirstOrDefault((Func<Contract, bool>)((Contract c) => (int)((Quest)c).State == 1 && ((Quest)c).GetQuestTitle().Contains(nPC.FirstName)));
if ((Object)(object)val != (Object)null && !withContract && val.ProductList.entries.Any((Entry e) => e.ProductID == laundererData.RequiredProductID))
{
MelonCoroutines.Start(AddContractListener(val));
}
if ((Object)(object)val == (Object)null && !withContract && laundererData.RequiredProductID != "")
{
RequireMix(laundererData.RequiredProductID);
}
}
}
}
public static class NPCUtilities
{
public static DialogueNodeData CreateDialogueInitNodeData(float amount_min, float amount_max, double cut, float upfront, Launderer launderer)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Expected O, but got Unknown
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
//IL_0058: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006f: Expected O, but got Unknown
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Expected O, but got Unknown
DialogueNodeData val = new DialogueNodeData();
val.DialogueNodeLabel = "LAUNDER_INIT_NODE";
val.DialogueText = $"Alright, I can wash around <color=#16F01C>${amount_min} - ${amount_max}</color> of your dirties. But there will be some cuts, of course. I'll let you know how much every week. But for now, Let us start with <color=#6b9cff>{cut}%</color> and an upfront of <color=#16F01C>${upfront}</color>";
DialogueChoiceData[] choices = (DialogueChoiceData[])(object)new DialogueChoiceData[2]
{
new DialogueChoiceData
{
ChoiceLabel = "ACCEPT_LAUNDER_TERMS",
ChoiceText = "Sure, Let's do it."
},
new DialogueChoiceData
{
ChoiceLabel = "DECLINE_LAUNDER_TERMS",
ChoiceText = "Nevermind"
}
};
val.choices = choices;
return val;
}
}
}
namespace System.Runtime.CompilerServices
{
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
internal sealed class IgnoresAccessChecksToAttribute : Attribute
{
internal IgnoresAccessChecksToAttribute(string assemblyName)
{
}
}
}