using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using BudgetingPlugin.Config; using BudgetingPlugin.Core; using BudgetingPlugin.Network; using BudgetingPlugin.UI; using ExitGames.Client.Photon; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using REPOLib.Modules; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("znore")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+42a0c10c3661ea9a72e5743cbf29f87044a80c78")] [assembly: AssemblyProduct("BudgetingPlugin")] [assembly: AssemblyTitle("BudgetingPlugin")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BudgetingPlugin { [BepInPlugin("znore.Budgeting", "Budgeting", "1.0.0")] public class BudgetingPlugin : BaseUnityPlugin { internal static BudgetingPlugin Instance { get; private set; } internal static ManualLogSource Logger => Instance._logger; private ManualLogSource _logger => ((BaseUnityPlugin)this).Logger; internal Harmony? Harmony { get; set; } private void Awake() { Instance = this; ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; PluginConfig.Initialize(((BaseUnityPlugin)this).Config); Patch(); Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); } private void Update() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.RunIsShop()) { BudgetWidget.Destroy(); } else if (Input.GetKeyDown(PluginConfig.OpenMenuKey.Value)) { BudgetSharePopup.TogglePopup(); } } internal void Patch() { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown if (Harmony == null) { Harmony val = new Harmony(((BaseUnityPlugin)this).Info.Metadata.GUID); Harmony val2 = val; Harmony = val; } Harmony.PatchAll(); } internal void Unpatch() { Harmony? harmony = Harmony; if (harmony != null) { harmony.UnpatchSelf(); } } } } namespace BudgetingPlugin.UI { internal static class BudgetSharePopup { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static Action <>9__2_2; public static ScrollViewBuilderDelegate <>9__2_1; internal void b__2_2(int i) { SetMoneyToDrop(i); } internal RectTransform b__2_1(Transform scrollView) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) REPOButton val = MenuAPI.CreateREPOButton("DROP THE BAG", (Action)ActionSubmit, scrollView, default(Vector2)); return ((REPOElement)val).rectTransform; } } private static REPOPopupPage? _page; private static int _moneyToDrop; internal static void InitPopupPage() { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown _moneyToDrop = 0; int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; int playerMax = BudgetingStats.Instance.getShare(actorNumber) / 1000; if (playerMax <= 0) { PlayerBudgetLines.SaySomethingStupid(PlayerBudgetLines.GetRandomLine(PlayerBudgetLines.LineTypes.NotEnoughMoneyToGive)); return; } _page = MenuAPI.CreateREPOPopupPage("How much money to share?", (PresetSide)0, false, true, 1.5f); _page.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform scrollView) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) REPOSlider val2 = MenuAPI.CreateREPOSlider(string.Empty, string.Empty, (Action)delegate(int i) { SetMoneyToDrop(i); }, scrollView, default(Vector2), 0, playerMax, 0, "$", "K", (BarBehavior)0); return ((REPOElement)val2).rectTransform; }, 0f, 0f); REPOPopupPage? page = _page; object obj = <>c.<>9__2_1; if (obj == null) { ScrollViewBuilderDelegate val = delegate(Transform scrollView) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) REPOButton val2 = MenuAPI.CreateREPOButton("DROP THE BAG", (Action)ActionSubmit, scrollView, default(Vector2)); return ((REPOElement)val2).rectTransform; }; <>c.<>9__2_1 = val; obj = (object)val; } page.AddElementToScrollView((ScrollViewBuilderDelegate)obj, 0f, 0f); } private static void SetMoneyToDrop(int inMoney) { _moneyToDrop = inMoney; } private static void ActionSubmit() { if (_moneyToDrop <= 0) { Close(); return; } BudgetingNetwork.Instance?.SpawnMoneyBag(_moneyToDrop * 1000); Close(); } internal static void TogglePopup() { if (IsOpen()) { Close(); } else { Open(); } } private static void Open() { InitPopupPage(); _page.OpenPage(true); } private static void Close() { _page.ClosePage(true); _page = null; } private static bool IsOpen() { return _page != null; } } internal static class BudgetWidget { private const string TextTemplate = "Your wallet: ${0}K"; private static readonly Vector2 PositionOffset = new Vector2(PluginConfig.WalletOffsetX.Value, PluginConfig.WalletOffsetY.Value); private static TextMeshProUGUI? _widgetText; internal static void Initialize() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_widgetText != (Object)null) { return; } CurrencyUI instance = CurrencyUI.instance; if ((Object)(object)instance == (Object)null) { BudgetingPlugin.Logger.LogWarning((object)"BudgetWidget.Initialize: CurrencyUI.instance is null; widget not created."); return; } TextMeshProUGUI text = instance.Text; BudgetingPlugin.Logger.LogDebug((object)$"CurrencyUI font size: {((TMP_Text)text).fontSize}"); if ((Object)(object)text == (Object)null) { BudgetingPlugin.Logger.LogWarning((object)"BudgetWidget.Initialize: CurrencyUI.Text is null; widget not created."); return; } GameObject val = Object.Instantiate(((Component)text).gameObject, ((TMP_Text)text).transform.parent); ((Object)val).name = "BudgetWidget"; RectTransform component = ((Component)text).GetComponent(); RectTransform component2 = val.GetComponent(); component2.anchoredPosition = component.anchoredPosition + PositionOffset; MonoBehaviour[] components = val.GetComponents(); foreach (MonoBehaviour val2 in components) { if (!(val2 is TextMeshProUGUI)) { ((Behaviour)val2).enabled = false; } } _widgetText = val.GetComponent(); ((TMP_Text)_widgetText).fontSize = ((TMP_Text)text).fontSize * 0.6f; ((Graphic)_widgetText).color = Color.yellow; SetValue(0); } internal static void Destroy() { if (!((Object)(object)_widgetText == (Object)null)) { Object.Destroy((Object)(object)((Component)_widgetText).gameObject); _widgetText = null; } } internal static void SetValue(int amount) { amount /= 1000; if ((Object)(object)_widgetText == (Object)null) { BudgetingPlugin.Logger.LogWarning((object)"BudgetWidget.SetValue called before the widget was initialized."); } else { ((TMP_Text)_widgetText).text = $"Your wallet: ${amount}K"; } } } } namespace BudgetingPlugin.Patches { [HarmonyPatch(typeof(ShopManager))] public static class BudgetingPatch { [HarmonyPostfix] [HarmonyPatch("ShopInitialize")] private static void ShopInitialize_Postfix(ShopManager __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown if ((Object)(object)BudgetingNetwork.Instance == (Object)null) { GameObject val = new GameObject("BudgetingNetwork"); Object.DontDestroyOnLoad((Object)(object)val); val.AddComponent(); } if (!SemiFunc.IsMasterClientOrSingleplayer()) { return; } int num = __instance.totalCurrency * 1000; if (num == 0) { return; } List list = SemiFunc.PlayerGetList(); BudgetingStats.Instance.setPlayers(list); double[] weights = GetWeights(); Dictionary shares = BudgetingStats.Instance.getShares(); int num2 = 0; foreach (int value2 in shares.Values) { num2 += value2; } int total = num - num2; int[] array = BudgetDistribution.Distribute(total, weights); Dictionary dictionary = new Dictionary(list.Count); for (int i = 0; i < list.Count; i++) { PhotonView photonView = list[i].photonView; int? obj; if (photonView == null) { obj = null; } else { Player owner = photonView.Owner; obj = ((owner != null) ? new int?(owner.ActorNumber) : ((int?)null)); } int num3 = obj ?? i; int share = BudgetingStats.Instance.getShare(num3); int value = share + array[i]; dictionary[num3] = value; BudgetingPlugin.Logger.LogDebug((object)$"===== Player [{num3}] | Existing: {share} | Added On: {array[i]} | TotalShare : ({dictionary[num3]}) ====="); } BudgetingStats.Instance.setShares(dictionary); BudgetingNetwork.Instance?.SendShares(dictionary); } private static double[] GetWeights() { return BudgetWeights.GetWeights(BudgetingStats.Instance.getPlayers()); } } [HarmonyPatch(typeof(ItemAttributes))] public static class DiscountPatch { [HarmonyPostfix] [HarmonyPatch("GetValue")] private static void GetValue_Postfix(ItemAttributes __instance) { if (!__instance.shopItem || SemiFunc.IsNotMasterClient() || __instance.value < 10) { return; } int value = PluginConfig.ShopDiscountPercent.Value; if (value > 0) { int num = __instance.value * 1000; int num2 = num * (100 - value) / 100 / 1000; BudgetingPlugin.Logger.LogDebug((object)$"[BudgetingPlugin] Discounted {((Object)__instance).name} by {value}% for a resulting value of ${num2 * 1000} (from {num})"); __instance.value = num2; if (GameManager.Multiplayer() && __instance.photonView.ViewID != 0) { __instance.photonView.RPC("GetValueRPC", (RpcTarget)1, new object[1] { __instance.value }); } } } } [HarmonyPatch(typeof(ExtractionPoint))] public static class ExtractionPointPatch { private static bool _purchaseMade; private static int _approvedCartTotal; [HarmonyPrefix] [HarmonyPatch("OnShopClick")] private static bool OnShopClick_Prefix(ExtractionPoint __instance) { _purchaseMade = false; int lastShopButtonPresserActorNumber = BudgetingNetwork.LastShopButtonPresserActorNumber; BudgetingPlugin.Logger.LogDebug((object)$"================== Pressed: {lastShopButtonPresserActorNumber} =================="); int share = BudgetingStats.Instance.getShare(lastShopButtonPresserActorNumber); int haulCurrent = __instance.haulCurrent; if (share >= haulCurrent && haulCurrent > 0) { _purchaseMade = true; return true; } if (haulCurrent == 0) { return true; } BudgetingNetwork.TriggerPlayerTalk(lastShopButtonPresserActorNumber); return false; } [HarmonyPrefix] [HarmonyPatch("DestroyAllPhysObjectsInShoppingList")] private static bool DestroyAllPhysObjectsInShoppingList_Prefix(ExtractionPoint __instance) { if (!_purchaseMade || !__instance.isShop) { return true; } int lastShopButtonPresserActorNumber = BudgetingNetwork.LastShopButtonPresserActorNumber; int num = SemiFunc.ShopGetTotalCost() * 1000; if (BudgetingStats.Instance.getShare(lastShopButtonPresserActorNumber) < num) { _purchaseMade = false; ShopManager.instance.isThief = true; __instance.isThief = true; return false; } _approvedCartTotal = num; return true; } [HarmonyPostfix] [HarmonyPatch("DestroyAllPhysObjectsInShoppingList")] private static void DestroyAllPhysObjectsInShoppingList_Postfix(ExtractionPoint __instance) { if (_purchaseMade && __instance.isShop) { int lastShopButtonPresserActorNumber = BudgetingNetwork.LastShopButtonPresserActorNumber; int amount = BudgetingStats.Instance.deductAmountFromPlayerShare(lastShopButtonPresserActorNumber, _approvedCartTotal); _purchaseMade = false; BudgetingNetwork.LastShopButtonPresserActorNumber = -1; BudgetingNetwork.TriggerMoneyDeductedEvent(lastShopButtonPresserActorNumber, amount); } } } [HarmonyPatch(typeof(PhysGrabber))] public class PhysGrabberPatch { [HarmonyPrefix] [HarmonyPatch(typeof(PhysGrabber), "StartGrabbingPhysObject")] private static void StartGrabbingPhysObject_Prefix(PhysGrabber __instance) { if (SemiFunc.RunIsShop()) { BudgetingNetwork.NotifyShopButtonPressed(); } } [HarmonyPostfix] [HarmonyPatch(typeof(PhysGrabber), "StartGrabbingPhysObject")] private static void StartGrabbingPhysObject_Postfix(PhysGrabber __instance) { PhysGrabObject grabbedPhysGrabObject = __instance.grabbedPhysGrabObject; if (!((Object)(object)grabbedPhysGrabObject == (Object)null)) { int viewID = ((Component)grabbedPhysGrabObject).GetComponent().ViewID; BudgetingNetwork.NotifyBagPickedUp(viewID); } } } } namespace BudgetingPlugin.Network { public class BudgetingNetwork : MonoBehaviour, IInRoomCallbacks { private const string SharesKey = "BudgetShares"; internal static readonly Dictionary BudgetBags = new Dictionary(); internal static int LastShopButtonPresserActorNumber = -1; private static readonly Durability InvincibleDurability = CreateInvincibleDurability(); private NetworkedEvent _spawnBagEvent = null; private NetworkedEvent _pickupBagEvent = null; private NetworkedEvent _makePlayerTalk = null; private NetworkedEvent _shopButtonPressedEvent = null; private NetworkedEvent _moneyDeductedEvent = null; public static BudgetingNetwork? Instance { get; private set; } private void Awake() { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown Instance = this; PhotonNetwork.AddCallbackTarget((object)this); _spawnBagEvent = new NetworkedEvent("BudgetBag_Spawn", (Action)OnSpawnBagEvent); _pickupBagEvent = new NetworkedEvent("BudgetBag_Pickup", (Action)OnPickupBagEvent); _makePlayerTalk = new NetworkedEvent("MakePlayerTalk", (Action)OnMakePlayerTalk); _shopButtonPressedEvent = new NetworkedEvent("ShopButtonPressed", (Action)OnShopButtonPressed); _moneyDeductedEvent = new NetworkedEvent("MoneyDeductedFromPlayers", (Action)OnMoneyDeducted); } private void OnDestroy() { PhotonNetwork.RemoveCallbackTarget((object)this); BudgetWidget.Destroy(); Instance = null; } public unsafe void OnRoomPropertiesUpdate(Hashtable changedProps) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) if (!((Dictionary)(object)changedProps).ContainsKey((object)"BudgetShares")) { return; } Hashtable val = (Hashtable)changedProps[(object)"BudgetShares"]; Dictionary dictionary = new Dictionary(); DictionaryEntryEnumerator enumerator = val.GetEnumerator(); try { while (((DictionaryEntryEnumerator)(ref enumerator)).MoveNext()) { var (obj3, obj4) = (DictionaryEntry)(ref ((DictionaryEntryEnumerator)(ref enumerator)).Current); dictionary[(int)obj3] = (int)obj4; } } finally { ((IDisposable)(*(DictionaryEntryEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose(); } BudgetingStats.Instance.setShares(dictionary); int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; if (!((Dictionary)(object)val).ContainsKey((object)actorNumber)) { BudgetingPlugin.Logger.LogWarning((object)$"No share found for player with ActorNumber {actorNumber}"); return; } BudgetWidget.Initialize(); BudgetWidget.SetValue((int)val[(object)actorNumber]); } public void OnPlayerEnteredRoom(Player newPlayer) { } public void OnPlayerLeftRoom(Player otherPlayer) { } public void OnPlayerPropertiesUpdate(Player targetPlayer, Hashtable changedProps) { } public void OnMasterClientSwitched(Player newMasterClient) { } private void OnMakePlayerTalk(EventData photonEvent) { object[] array = (object[])photonEvent.CustomData; if (PhotonNetwork.LocalPlayer.ActorNumber == (int)array[0]) { string randomLine = PlayerBudgetLines.GetRandomLine((PlayerBudgetLines.LineTypes)array[1]); PlayerBudgetLines.SaySomethingStupid(randomLine); } } private void OnMoneyDeducted(EventData photonEvent) { object[] array = (object[])photonEvent.CustomData; if (PhotonNetwork.LocalPlayer.ActorNumber == (int)array[0]) { BudgetWidget.SetValue((int)array[1]); } } private void OnShopButtonPressed(EventData photonEvent) { if (PhotonNetwork.IsMasterClient) { LastShopButtonPresserActorNumber = photonEvent.Sender; } } internal static void NotifyShopButtonPressed() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient) { LastShopButtonPresserActorNumber = PhotonNetwork.LocalPlayer.ActorNumber; return; } BudgetingNetwork? instance = Instance; if (instance != null) { instance._shopButtonPressedEvent.RaiseEvent((object)PhotonNetwork.LocalPlayer.ActorNumber, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); } } internal static void TriggerPlayerTalk(int actorNumber, PlayerBudgetLines.LineTypes lineType = PlayerBudgetLines.LineTypes.NotEnoughMoney) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) BudgetingNetwork? instance = Instance; if (instance != null) { instance._makePlayerTalk.RaiseEvent((object)new object[2] { actorNumber, lineType }, NetworkingEvents.RaiseAll, SendOptions.SendReliable); } } internal static void TriggerMoneyDeductedEvent(int actorNumber, int amount) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) BudgetingNetwork? instance = Instance; if (instance != null) { instance._moneyDeductedEvent.RaiseEvent((object)new object[2] { actorNumber, amount }, NetworkingEvents.RaiseAll, SendOptions.SendReliable); } } private void OnSpawnBagEvent(EventData photonEvent) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (PhotonNetwork.IsMasterClient) { object[] array = (object[])photonEvent.CustomData; ProcessSpawnRequest(photonEvent.Sender, (int)array[0], (Vector3)array[1]); } } private void OnPickupBagEvent(EventData photonEvent) { if (PhotonNetwork.IsMasterClient) { ProcessBagPickup((int)photonEvent.CustomData, photonEvent.Sender); } } public void SpawnMoneyBag(int amount) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (!SemiFunc.RunIsShop()) { return; } int actorNumber = PhotonNetwork.LocalPlayer.ActorNumber; int share = BudgetingStats.Instance.getShare(actorNumber); if (amount > 0) { if (amount > share) { TriggerPlayerTalk(actorNumber, PlayerBudgetLines.LineTypes.NotEnoughMoneyToGive); return; } Transform transform = ((Component)PlayerAvatar.instance).transform; Vector3 val = transform.position + transform.forward * PluginConfig.BagSpawnForwardOffset.Value + transform.up * PluginConfig.BagSpawnHeightOffset.Value; _spawnBagEvent.RaiseEvent((object)new object[2] { amount, val }, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); } } private void ProcessSpawnRequest(int requesterActor, int amount, Vector3 spawnPos) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) int share = BudgetingStats.Instance.getShare(requesterActor); if (share >= amount) { SpawnBag(requesterActor, amount, spawnPos); } } private void SpawnBag(int ownerActor, int amount, Vector3 spawnPos) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) GameObject surplusValuableSmall = AssetManager.instance.surplusValuableSmall; GameObject val = PhotonNetwork.InstantiateRoomObject("Valuables/" + ((Object)surplusValuableSmall).name, spawnPos, Quaternion.identity, (byte)0, (object[])null); val.GetComponent().dollarValueOverride = amount; val.GetComponent().durabilityPreset = InvincibleDurability; int viewID = val.GetComponent().ViewID; BudgetBags[viewID] = amount; BudgetingStats.Instance.deductAmountFromPlayerShare(ownerActor, amount); SendShares(BudgetingStats.Instance.getShares()); } private void ProcessBagPickup(int bagViewId, int pickerActor) { if (BudgetBags.TryGetValue(bagViewId, out var value)) { BudgetBags.Remove(bagViewId); BudgetingStats.Instance.addAmountToPlayerShare(pickerActor, value); SendShares(BudgetingStats.Instance.getShares()); PhotonView val = PhotonView.Find(bagViewId); if ((Object)(object)val != (Object)null) { PhotonNetwork.Destroy(((Component)val).gameObject); } } } internal static void NotifyBagPickedUp(int bagViewId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.RunIsShop()) { BudgetingNetwork? instance = Instance; if (instance != null) { instance._pickupBagEvent.RaiseEvent((object)bagViewId, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); } } } public void SendShares(Dictionary shares) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0087: Expected O, but got Unknown if (!PhotonNetwork.IsMasterClient) { return; } Hashtable val = new Hashtable(); foreach (var (num3, num4) in shares) { ((Dictionary)(object)val).Add((object)num3, (object)num4); } Room currentRoom = PhotonNetwork.CurrentRoom; Hashtable val2 = new Hashtable(); ((Dictionary)val2).Add((object)"BudgetShares", (object)val); currentRoom.SetCustomProperties(val2, (Hashtable)null, (WebFlags)null); } private static Durability CreateInvincibleDurability() { Durability val = ScriptableObject.CreateInstance(); val.durability = 100f; val.fragility = 0f; return val; } } } namespace BudgetingPlugin.Core { public enum DistributionMethod { Even, Manual, Upgrades } public static class BudgetDistribution { public static int[] Distribute(int total, double[] weights) { if (weights == null || weights.Length == 0) { return Array.Empty(); } if (total < 0) { total = 0; } int num = weights.Length; double num2 = 0.0; for (int i = 0; i < num; i++) { num2 += Math.Max(0.0, weights[i]); } if (num2 <= 0.0) { return DistributeEven(total, num); } int[] array = new int[num]; int num3 = 0; for (int j = 0; j < num; j++) { double num4 = (double)total * (Math.Max(0.0, weights[j]) / num2); num4 = Math.Floor(num4 / 1000.0); num4 *= 1000.0; array[j] = (int)num4; num3 += (int)num4; } int num5 = total - num3; double value = weights.Max(); int num6 = Array.IndexOf(weights, value); int num7 = Array.LastIndexOf(weights, value); if (num6 != num7) { int num8 = array.Length; int num9 = 0; while (num5 > 0) { if (num9 >= num8) { num9 = 0; } array[num9] += 1000; num5 -= 1000; num9++; } } else { array[num6] += num5; } return array; } private static int[] DistributeEven(int total, int playerCount) { double[] array = new double[playerCount]; for (int i = 0; i < playerCount; i++) { array[i] = 1.0; } return Distribute(total, array); } } public class BudgetingStats { private List _players = new List(); private Dictionary _shares = new Dictionary(); public static BudgetingStats Instance { get; } = new BudgetingStats(); public int playerCount => _players.Count; public Dictionary getShares() { return _shares; } public int deductAmountFromPlayerShare(int actorNumber, int amountLost) { BudgetingPlugin.Logger.LogDebug((object)$"==== deductAmountFromPlayerShare; Actor = {actorNumber}; amountLost = {amountLost};"); if (!_shares.ContainsKey(actorNumber)) { BudgetingPlugin.Logger.LogWarning((object)$"deductAmountFromPlayerShare: actor {actorNumber} not in shares, skipping deduction."); return 0; } int share = getShare(actorNumber); int num = Math.Max(0, share - amountLost); _shares[actorNumber] = num; return num; } public int addAmountToPlayerShare(int actorNumber, int amount) { if (!_shares.ContainsKey(actorNumber)) { BudgetingPlugin.Logger.LogWarning((object)$"addAmountToPlayerShare: actor {actorNumber} not in shares, skipping."); return 0; } int num = _shares[actorNumber] + amount; _shares[actorNumber] = num; return num; } public int getShare(int actorNumber) { if (!_shares.TryGetValue(actorNumber, out var value)) { BudgetingPlugin.Logger.LogWarning((object)$"getShare: no share found for actor {actorNumber}, defaulting to 0."); return 0; } return value; } public void setShares(Dictionary shares) { _shares = shares; } public List getPlayers() { return _players; } public PlayerAvatar getPlayer(int index) { return _players[index]; } public void setPlayers(List players) { _players = players; } } public static class BudgetWeights { private static int _playerCount; public static double[] GetWeights(List players) { _playerCount = players.Count; double[] array = new double[_playerCount]; string value = PluginConfig.DesiredDist.Value; string text = value; if (text == "Manual") { GetWeights_Manual(array); } else { GetWeights_Even(array); } return array; } private static void GetWeights_Even(double[] weights) { Array.Fill(weights, 1.0); } private static void GetWeights_Manual(double[] weights) { weights[0] = 1.0; for (int i = 1; i < _playerCount; i++) { weights[i] = 0.0; } } private static int GetWeightPointsForGroup() { return (int)((double)(float)_playerCount * 1.5); } } public static class PlayerBudgetLines { public enum LineTypes { NotEnoughMoney, NotEnoughMoneyToGive } private static readonly Random RandomNumGenerator = new Random(); private static readonly string[] NotEnoughMoneyLines = new string[12] { "Nope. I'm outta cash", "No moners!", "Nope, gotta pay for rent this month", "I DON'T HAVE ANY MONEEEEEEEEEEEEEEEEEEEEEY", "NOOOOOOOOOO MONNNNEEEEEEEEY", "Holla holla get $", "Job application incoming", "WHAT DO I DO, MY CREDIT CARD DECLINED", "DID I LOSE MY WALLET", "Mom would be so disappointed", "Yeah in retrospect all those crypto investments weren't the right move", "'Put it all on black', they said" }; private static readonly string[] NotEnoughMoneyToGiveLines = new string[2] { "I don't have this much money to give out", "I should probably keep this for myself" }; public static string GetRandomLine(LineTypes type = LineTypes.NotEnoughMoney) { string[] array = Array.Empty(); array = ((type == LineTypes.NotEnoughMoney || type != LineTypes.NotEnoughMoneyToGive) ? NotEnoughMoneyLines : NotEnoughMoneyToGiveLines); if (array.Length != 0) { int num = RandomNumGenerator.Next(0, array.Length); return array[num]; } return string.Empty; } public static void SaySomethingStupid(string message) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) ChatManager.instance.PossessChatScheduleStart(10); ChatManager.instance.PossessChat((PossessChatID)0, message, 3f, new Color(0f, 1f, 0f), 0f, false, 0, (UnityEvent)null); ChatManager.instance.PossessChatScheduleEnd(); } } } namespace BudgetingPlugin.Config { public static class DistributionMethods { public const string Even = "Even"; public const string Manual = "Manual"; public const string Death = "Death"; public const string DeathReverse = "Death Reverse"; public const string KillPercent = "Kill %"; public const string UpgradeCount = "Upgrade Count"; } internal static class PluginConfig { private static readonly string[] DistributionMethodsList = new string[2] { "Even", "Manual" }; internal static ConfigEntry OpenMenuKey { get; private set; } = null; internal static ConfigEntry BagSpawnForwardOffset { get; private set; } = null; internal static ConfigEntry BagSpawnHeightOffset { get; private set; } = null; internal static ConfigEntry ShopDiscountPercent { get; private set; } = null; internal static ConfigEntry DesiredDist { get; private set; } = null; internal static ConfigEntry WalletOffsetX { get; private set; } = null; internal static ConfigEntry WalletOffsetY { get; private set; } = null; internal static void Initialize(ConfigFile config) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown OpenMenuKey = config.Bind("Controls", "ShareMoneyKey", (KeyCode)52, "What key should be pressed to open the 'Share Money' pop up"); BagSpawnForwardOffset = config.Bind("BagSpawn", "ForwardOffset", 1.5f, "How far in front of the player the money bag spawns (in units)."); BagSpawnHeightOffset = config.Bind("BagSpawn", "HeightOffset", 1.5f, "How high above the player the money bag spawns (in units)."); ShopDiscountPercent = config.Bind("Game", "ShopDiscountPercent", 10, new ConfigDescription("Discount applied to all items above $10 in the shop. Caps at 30%", (AcceptableValueBase)(object)new AcceptableValueRange(0, 30), Array.Empty())); DesiredDist = config.Bind("Game", "DistributionMethod", "Even", new ConfigDescription("Even: Money is distributed evenly to all playersManual: Host gets all money, then distributes it with money sharing", (AcceptableValueBase)(object)new AcceptableValueList(DistributionMethodsList), Array.Empty())); WalletOffsetX = config.Bind("UI", "WalletOffset_X", 0f, "Where the 'Wallet' text should be displayed during the shop phase (horizontal location). This is relative to the existing money count text."); WalletOffsetY = config.Bind("UI", "WalletOffset_Y", -50f, "Where the 'Wallet' text should be displayed during the shop phase (vertical location). This is relative to the existing money count text."); } } }