Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of CatchupLoot v3.0.0
CatchupLoot.dll
Decompiled 5 hours agousing System; using System.Collections.Generic; using System.Collections.ObjectModel; 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 HG.Reflection; using Microsoft.CodeAnalysis; using On.RoR2; using On.RoR2.Networking; using R2API.Networking; using R2API.Networking.Interfaces; using RoR2; using RoR2.Artifacts; using RoR2.Networking; using RoR2.UI; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: OptIn] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("CatchupLoot")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+54de05d8639907e57a333aaccea732a1ae8f557e")] [assembly: AssemblyProduct("CatchupLoot")] [assembly: AssemblyTitle("CatchupLoot")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace CatchupLoot { [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("zerocodehero.CatchupLoot", "CatchupLoot", "2.2.0")] public class CatchupLootPlugin : BaseUnityPlugin { [CompilerGenerated] private static class <>O { public static hook_GetExpAdjustedDropChancePercent <0>__Util_GetExpAdjustedDropChancePercent; public static NetworkMessageDelegate <1>__HandlePickupMessage; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_DropRewards <>9__40_0; public static Func<PlayerCharacterMasterController, bool> <>9__56_0; internal void <OnEnable>b__40_0(orig_DropRewards orig, BossGroup self) { if (EnablePlayerDropRateScaling.Value && IsModHooked) { self.scaleRewardsByPlayerCount = false; } orig.Invoke(self); } internal bool <GetPlayerCount>b__56_0(PlayerCharacterMasterController pc) { return pc.isConnected; } } public const string PluginGUID = "zerocodehero.CatchupLoot"; public const string PluginAuthor = "zerocodehero"; public const string PluginName = "CatchupLoot"; public const string PluginVersion = "2.2.0"; public static float dropChance = 5f; private static bool IsModHooked = false; private bool forceDisabled; private static bool useManualDropRate = false; private static DropRateManager dropRateManager; private static ConfigEntry<float> DropChanceMultiplier { get; set; } private static ConfigEntry<float> MinimumDropChance { get; set; } private static ConfigEntry<float> BaseDropChance { get; set; } private static ConfigEntry<bool> EnablePlayerDropRateScaling { get; set; } private static ConfigEntry<bool> EnableSwarmsScaling { get; set; } private static ConfigEntry<bool> EnableBadLuckProtection { get; set; } private static ConfigEntry<KeyCode> PullItemsHotKey { get; set; } public void Awake() { Log.Init(((BaseUnityPlugin)this).Logger); DropChanceMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("General", "DropChanceMultiplier", 1f, "Manipulate drop rate. Use `0.5` to halve or `2` to double."); MinimumDropChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "MinimumDropChance", 1f, "The lowest possible drop chance when player count scaling is active."); EnablePlayerDropRateScaling = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnablePlayerBasedDropRateScaling", true, "Enabling this will reduce drop rates to account for shared loot."); EnableSwarmsScaling = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableSwarmsScaling", true, "Enabling this will (correctly) reduce drop rates for Artifact of Swarms."); EnableBadLuckProtection = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableBadLuckProtection", true, "Enabling this will increase drop rate consistency with low drop rates."); PullItemsHotKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("General", "PullItemsHotkey", (KeyCode)284, "Hotkey to use to pull items to yourself."); BaseDropChance = ((BaseUnityPlugin)this).Config.Bind<float>("General", "BaseDropChance", 5f, "Base item drop chance. It is recommended to leave this at the default value."); dropChance = BaseDropChance.Value; dropRateManager = new DropRateManager(EnableBadLuckProtection, EnableSwarmsScaling, DropChanceMultiplier, BaseDropChance, MinimumDropChance); Log.Info("CatchupLoot loaded"); } private void Update() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (!Input.GetKeyDown(PullItemsHotKey.Value) || !IsModHooked) { return; } try { Object.FindObjectsOfType<RuleBookViewer>(); PickupDisplay[] array = Object.FindObjectsOfType<PickupDisplay>(); Vector3 position = ((MPEventSystem)EventSystem.current).localUser.cachedMaster.GetBodyObject().transform.position; float num = 10f; Vector3 position2 = default(Vector3); for (int i = 0; i < array.Length; i++) { PickupDisplay val = array[i]; if (((Object)val.highlight).name.StartsWith("CommandCube")) { float num2 = (float)i * MathF.PI * 2f / (float)array.Length; ((Vector3)(ref position2))..ctor(position.x + Mathf.Cos(num2) * num, position.y, position.z + Mathf.Sin(num2) * num); ((Component)val).gameObject.transform.position = position2; } } } catch (NullReferenceException) { ((BaseUnityPlugin)this).Logger.LogDebug((object)"Failed to pull CommandCubes with F3 - most likely because there were none."); } } private void OnApplicationFocus(bool hasFocus) { if (hasFocus) { ReevaluateLifecycle(); } } private void OnEnable() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown object obj = <>c.<>9__40_0; if (obj == null) { hook_DropRewards val = delegate(orig_DropRewards orig, BossGroup self) { if (EnablePlayerDropRateScaling.Value && IsModHooked) { self.scaleRewardsByPlayerCount = false; } orig.Invoke(self); }; <>c.<>9__40_0 = val; obj = (object)val; } BossGroup.DropRewards += (hook_DropRewards)obj; SceneManager.activeSceneChanged += delegate(Scene oldScene, Scene newScene) { bool flag = ((Scene)(ref newScene)).name == "loadingbasic" || ((Scene)(ref newScene)).name == "intro" || ((Scene)(ref newScene)).name == "splash" || ((Scene)(ref newScene)).name == "title" || ((Scene)(ref newScene)).name == "eclipseworld" || ((Scene)(ref newScene)).name == "infinitetowerworld" || ((Scene)(ref newScene)).name == "lobby"; forceDisabled = ((Scene)(ref newScene)).name == "artifactworld" || flag; if (flag) { useManualDropRate = false; DropRateTracker.ResetTracker(); } ReevaluateLifecycle(); }; NetworkingAPI.RegisterMessageType<SpawnCustomMessage2>(); } private void ReevaluateLifecycle() { if (EnablePlayerDropRateScaling.Value && IsSacrificeEnabled() && !useManualDropRate) { dropChance = dropRateManager.GetPlayerAwareBaseDropChance(GetPlayerCount(), dropChance); } if (forceDisabled) { if (IsModHooked) { Log.Warning("Force Disabled: Will remove hooks, even if Artifact of Command is enabled."); UnHook(); } else { Log.Debug("Force Disabled: Will not hook."); } return; } bool flag = IsCommandEnabled(); if (IsModHooked && !flag) { UnHook(); } else if (!IsModHooked && flag) { Hook(); } } private void Hook() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"Loading hooks"); object obj = <>O.<0>__Util_GetExpAdjustedDropChancePercent; if (obj == null) { hook_GetExpAdjustedDropChancePercent val = Util_GetExpAdjustedDropChancePercent; <>O.<0>__Util_GetExpAdjustedDropChancePercent = val; obj = (object)val; } Util.GetExpAdjustedDropChancePercent += (hook_GetExpAdjustedDropChancePercent)obj; NetworkMessageHandlerAttribute.RegisterClientMessages += new hook_RegisterClientMessages(NetworkMessageHandlerAttribute_RegisterClientMessages); PickupDropletController.CreateCommandCube += new hook_CreateCommandCube(PickupDropletController_CreateCommandCube); Interactor.AttemptInteraction += new hook_AttemptInteraction(Interactor_AttemptInteraction); PickupPickerController.SubmitChoice += new hook_SubmitChoice(PickupPickerController_SubmitChoice); GenericPickupController.CreatePickup += new hook_CreatePickup(GenericPickupController_CreatePickup); IsModHooked = true; } private void UnHook() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Expected O, but got Unknown //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"Unloading hooks"); object obj = <>O.<0>__Util_GetExpAdjustedDropChancePercent; if (obj == null) { hook_GetExpAdjustedDropChancePercent val = Util_GetExpAdjustedDropChancePercent; <>O.<0>__Util_GetExpAdjustedDropChancePercent = val; obj = (object)val; } Util.GetExpAdjustedDropChancePercent -= (hook_GetExpAdjustedDropChancePercent)obj; NetworkMessageHandlerAttribute.RegisterClientMessages -= new hook_RegisterClientMessages(NetworkMessageHandlerAttribute_RegisterClientMessages); PickupDropletController.CreateCommandCube -= new hook_CreateCommandCube(PickupDropletController_CreateCommandCube); Interactor.AttemptInteraction -= new hook_AttemptInteraction(Interactor_AttemptInteraction); PickupPickerController.SubmitChoice -= new hook_SubmitChoice(PickupPickerController_SubmitChoice); GenericPickupController.CreatePickup -= new hook_CreatePickup(GenericPickupController_CreatePickup); IsModHooked = false; } private GenericPickupController GenericPickupController_CreatePickup(orig_CreatePickup orig, ref CreatePickupInfo createPickupInfo) { return null; } private void PickupPickerController_SubmitChoice(orig_SubmitChoice orig, PickupPickerController self, int choiceIndex) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((ulong)choiceIndex >= (ulong)self.options.Length) { return; } ref Option reference = ref self.options[choiceIndex]; if (reference.available) { PickupIndexUnityEvent onPickupSelected = self.onPickupSelected; if (onPickupSelected != null) { ((UnityEvent<int>)(object)onPickupSelected).Invoke(((Option)(ref reference)).pickupIndex.value); Log.Info($"Sending CreatePickup {((Option)(ref self.options[choiceIndex])).pickupIndex}"); NetMessageExtensions.Send((INetMessage)(object)new SpawnCustomMessage2(((Option)(ref self.options[choiceIndex])).pickupIndex, ((MPEventSystem)EventSystem.current).localUser.cachedMaster.GetBodyObject().transform.position), (NetworkDestination)2); self.OnDisplayEnd((NetworkUIPromptController)null, (LocalUser)null, (CameraRigController)null); Object.Destroy((Object)(object)((Component)self).gameObject); } } } private void Interactor_AttemptInteraction(orig_AttemptInteraction orig, Interactor self, GameObject interactableObject) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (((Object)interactableObject).name.StartsWith("CommandCube")) { interactableObject.GetComponent<PickupPickerController>().OnDisplayBegin((NetworkUIPromptController)null, (LocalUser)null, ((MPEventSystem)EventSystem.current).localUser.cameraRigController); } else { orig.Invoke(self, interactableObject); } } private void PickupDropletController_CreateCommandCube(orig_CreateCommandCube orig, PickupDropletController self) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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_019f: Unknown result type (might be due to invalid IL or missing references) DropRateTracker.RegisterItemDrop(self.createPickupInfo); NetworkServer.SendToAll((short)969, (MessageBase)(object)new SpawnCustomMessage { position = self.createPickupInfo.position, pickupIndex = ((CreatePickupInfo)(ref self.createPickupInfo)).pickupIndex }); if (!NetworkServer.active) { return; } ReadOnlyCollection<NetworkUser> readOnlyInstancesList = NetworkUser.readOnlyInstancesList; if (readOnlyInstancesList == null) { return; } Vector3 val = default(Vector3); foreach (NetworkUser item in readOnlyInstancesList) { if ((Object)(object)item == (Object)null || ((NetworkBehaviour)item).connectionToClient == null || !((NetworkBehaviour)item).connectionToClient.isReady || (Object)(object)item.master == (Object)null || !item.master.hasBody) { continue; } ItemTier? catchupTier = PlayerCatchupManager.GetCatchupTier(item); if (!catchupTier.HasValue) { continue; } int deficit = PlayerCatchupManager.GetDeficit(item, catchupTier.Value); float catchupChance = PlayerCatchupManager.GetCatchupChance(deficit, catchupTier.Value); if (Random.value < catchupChance) { PickupIndex randomPickupForTier = PlayerCatchupManager.GetRandomPickupForTier(catchupTier.Value); if (((PickupIndex)(ref randomPickupForTier)).isValid) { ((Vector3)(ref val))..ctor(Random.Range(-1.5f, 1.5f), 0f, Random.Range(-1.5f, 1.5f)); SpawnCustomMessage spawnCustomMessage = new SpawnCustomMessage { position = self.createPickupInfo.position + val, pickupIndex = randomPickupForTier }; ((NetworkBehaviour)item).connectionToClient.Send((short)969, (MessageBase)(object)spawnCustomMessage); Log.Info($"Catchup drop for {item.userName}: tier={catchupTier.Value} deficit={deficit} chance={catchupChance:P} pickup={randomPickupForTier.value}"); } } } } private void NetworkMessageHandlerAttribute_RegisterClientMessages(orig_RegisterClientMessages orig, NetworkClient client) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown orig.Invoke(client); object obj = <>O.<1>__HandlePickupMessage; if (obj == null) { NetworkMessageDelegate val = SpawnCustomController.HandlePickupMessage; <>O.<1>__HandlePickupMessage = val; obj = (object)val; } client.RegisterHandler((short)969, (NetworkMessageDelegate)obj); } private static float Util_GetExpAdjustedDropChancePercent(orig_GetExpAdjustedDropChancePercent orig, float nativeBaseDropChance, GameObject characterBodyObject) { float num = orig.Invoke(nativeBaseDropChance, characterBodyObject); float num2 = dropRateManager.ComputeDropChance(IsSwarmEnabled(), num, nativeBaseDropChance, dropChance); Log.Debug($"DropChance: original_base={nativeBaseDropChance} original_final={num}; plugin_base={dropChance}; plugin_final={num2} (Character={((Object)characterBodyObject).name})"); DropRateTracker.RegisterDropOpportunity(num2); if (dropRateManager.NeedsBadLuckProtection(num2, Run.instance.GetRunStopwatch())) { return dropRateManager.GetBadLuckProtectedDropChance(num2); } return num2; } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCSetDropRate(ConCommandArgs args) { dropChance = ((ConCommandArgs)(ref args)).GetArgFloat(0); useManualDropRate = true; Log.Info("Drop rate set to: " + ((ConCommandArgs)(ref args)).GetArgString(0) + "%"); } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCGetDropRateReport(ConCommandArgs args) { if (IsModHooked) { DropRateTracker.LogReport(); } } private static bool IsSacrificeEnabled() { if (RunArtifactManager.instance != null && ((Behaviour)RunArtifactManager.instance).isActiveAndEnabled) { return RunArtifactManager.instance.IsArtifactEnabled(Artifacts.sacrificeArtifactDef); } return false; } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCSetHotkey(ConCommandArgs args) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) if (IsModHooked) { string argString = ((ConCommandArgs)(ref args)).GetArgString(0); if (Enum.TryParse<KeyCode>(argString, ignoreCase: true, out KeyCode result)) { PullItemsHotKey.Value = result; } else { Log.Warning("Failed to set hotkey to " + argString); } } } private static bool IsCommandEnabled() { if (RunArtifactManager.instance != null && ((Behaviour)RunArtifactManager.instance).isActiveAndEnabled) { return RunArtifactManager.instance.IsArtifactEnabled(Artifacts.commandArtifactDef); } return false; } private static bool IsSwarmEnabled() { if (RunArtifactManager.instance != null && ((Behaviour)RunArtifactManager.instance).isActiveAndEnabled) { return RunArtifactManager.instance.IsArtifactEnabled(Artifacts.swarmsArtifactDef); } return false; } private int GetPlayerCount() { return PlayerCharacterMasterController.instances.Count((PlayerCharacterMasterController pc) => pc.isConnected); } } public class DropRateManager { private ConfigEntry<bool> EnableBadLuckProtection; private ConfigEntry<bool> EnableSwarmsScaling; private ConfigEntry<float> DropChanceMultiplier; private ConfigEntry<float> BaseDropChance; private ConfigEntry<float> MinimumDropChance; public DropRateManager(ConfigEntry<bool> enableBadLuckProtection, ConfigEntry<bool> enableSwarmsScaling, ConfigEntry<float> dropChanceMultiplier, ConfigEntry<float> baseDropChance, ConfigEntry<float> minimumDropChance) { EnableBadLuckProtection = enableBadLuckProtection; EnableSwarmsScaling = enableSwarmsScaling; DropChanceMultiplier = dropChanceMultiplier; BaseDropChance = baseDropChance; MinimumDropChance = minimumDropChance; } public float GetPlayerAwareBaseDropChance(int playerCount, float dropChance) { float num = 1f / (float)playerCount * DropChanceMultiplier.Value; float num2 = Math.Max(BaseDropChance.Value * num, MinimumDropChance.Value); if (!dropChance.Equals(num2)) { dropChance = num2; Log.Debug($"Using dropRate of {dropChance}% (base={BaseDropChance.Value}, multiplier={DropChanceMultiplier.Value}, playerCount={playerCount}, minimumDropChance={MinimumDropChance.Value}"); } return dropChance; } public float ComputeDropChance(bool isSwarmEnabled, float nativeDropChance, float nativeBaseDropChance, float dropChance) { float num = ((!(EnableSwarmsScaling.Value && isSwarmEnabled) || nativeDropChance == 0f) ? nativeDropChance : ((nativeDropChance - nativeBaseDropChance) * 0.6f + nativeBaseDropChance)); float num2 = nativeBaseDropChance / 5f; float num3 = num / nativeBaseDropChance; return dropChance * num2 * num3; } public bool NeedsBadLuckProtection(float actualDropChance, float time) { if (EnableBadLuckProtection.Value && DropRateTracker.cumulativeDropChance >= 100f && actualDropChance > 0f) { bool num = DropRateTracker.expectedItems > (float)DropRateTracker.totalItemDrops; float num2 = (float)DropRateTracker.totalItemDrops / (time / 60f); if (!num) { return (double)num2 < 0.8; } return true; } return false; } public float GetBadLuckProtectedDropChance(float dropChance) { float num = DropRateTracker.cumulativeDropChance - 100f; float num2 = Math.Min(dropChance + num, 90f); Log.Debug($"Bad Luck Protection triggered! ({dropChance}% => {num2}%)"); return num2; } } public static class DropRateTracker { private static Dictionary<float, long> DropRateReport = new Dictionary<float, long>(); public static long totalItemDrops { get; private set; } = 0L; public static float cumulativeDropChance { get; private set; } = 0f; public static float expectedItems { get; private set; } = 0f; public static void ResetTracker() { DropRateReport = new Dictionary<float, long>(); totalItemDrops = 0L; cumulativeDropChance = 0f; expectedItems = 0f; } public static void RegisterDropOpportunity(float dropChance) { cumulativeDropChance += dropChance; expectedItems += (float)Math.Round(dropChance / 100f, 2); if (DropRateReport.TryGetValue(dropChance, out var _)) { DropRateReport[dropChance]++; } else { DropRateReport.Add(dropChance, 1L); } } public static void RegisterItemDrop(CreatePickupInfo createPickupInfo) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0018: Unknown result type (might be due to invalid IL or missing references) PickupIndex pickupIndex = ((CreatePickupInfo)(ref createPickupInfo)).pickupIndex; if (((PickupIndex)(ref pickupIndex)).pickupDef != null) { pickupIndex = ((CreatePickupInfo)(ref createPickupInfo)).pickupIndex; PickupDef pickupDef = ((PickupIndex)(ref pickupIndex)).pickupDef; if (pickupDef.coinValue == 0 && pickupDef.nameToken != "PICKUP_LUNAR_COIN") { cumulativeDropChance = 0f; totalItemDrops++; } } } public static void LogReport() { if (Run.instance == null || !((Behaviour)Run.instance).isActiveAndEnabled) { return; } long num = DropRateReport.Values.Aggregate(0L, (long i, long l) => i + l); if (num != 0L) { string text = DropRateReport.Keys.OrderByDescending((float f) => f).Aggregate("Kills by Drop Rate", (string s, float f) => $"{s}\n {f}%: {DropRateReport[f]} kills"); float runStopwatch = Run.instance.GetRunStopwatch(); float num2 = runStopwatch / 60f; float num3 = DropRateReport.Keys.Aggregate(0f, (float f, float f1) => f + (float)DropRateReport[f1] * f1) / (float)num; Log.Info(string.Concat(string.Concat(string.Concat(string.Concat(string.Concat(string.Concat(string.Concat(string.Concat("------ DROP RATE RUN REPORT -----\n" + $"Stage: {Run.instance.stageClearCount + 1}\n", $"Run Duration: {runStopwatch}s\n"), $"Total kills: {num}\n"), $"Total items: {totalItemDrops}\n"), $"Theoretical Average Drop Rate: {num3}%\n"), $"Actual Average Drop Rate: {(float)totalItemDrops / (float)num * 100f}%\n"), $"Drops per Minute: {Math.Round((float)totalItemDrops / num2, 2)}\n"), text, "\n"), "------ END OF REPORT -----")); } } } internal static class Log { private static ManualLogSource _logSource; internal static void Init(ManualLogSource logSource) { _logSource = logSource; } internal static void Debug(object data) { _logSource.LogDebug(data); } internal static void Error(object data) { _logSource.LogError(data); } internal static void Fatal(object data) { _logSource.LogFatal(data); } internal static void Info(object data) { _logSource.LogInfo(data); } internal static void Message(object data) { _logSource.LogMessage(data); } internal static void Warning(object data) { _logSource.LogWarning(data); } } public static class PlayerCatchupManager { private static readonly Dictionary<ItemTier, float> TierWeights = new Dictionary<ItemTier, float> { [(ItemTier)0] = 1f, [(ItemTier)1] = 3f, [(ItemTier)2] = 10f, [(ItemTier)4] = 15f }; private static readonly HashSet<ItemTier> IgnoredTiers = new HashSet<ItemTier> { (ItemTier)3, (ItemTier)6, (ItemTier)7, (ItemTier)8, (ItemTier)9, (ItemTier)5 }; public static ItemTier? GetCatchupTier(NetworkUser user) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) List<NetworkUser> players = GetPlayers(); if (players.Count <= 1) { return null; } Dictionary<uint, Dictionary<ItemTier, int>> dictionary = new Dictionary<uint, Dictionary<ItemTier, int>>(); NetworkInstanceId netId; foreach (NetworkUser item in players) { object obj; if (item == null) { obj = null; } else { CharacterMaster master = item.master; obj = ((master != null) ? master.inventory : null); } if ((Object)obj != (Object)null) { netId = ((NetworkBehaviour)item).netId; dictionary[((NetworkInstanceId)(ref netId)).Value] = CountItemsByTier(item); } } if (dictionary.Count <= 1) { return null; } netId = ((NetworkBehaviour)user).netId; if (!dictionary.TryGetValue(((NetworkInstanceId)(ref netId)).Value, out var value)) { return null; } Dictionary<ItemTier, int> dictionary2 = new Dictionary<ItemTier, int>(); foreach (ItemTier tier in TierWeights.Keys) { dictionary2[tier] = dictionary.Values.Select((Dictionary<ItemTier, int> c) => c.TryGetValue(tier, out var value3) ? value3 : 0).Max(); } ItemTier? result = null; float num = 0f; foreach (ItemTier key in TierWeights.Keys) { int value2; int num2 = dictionary2[key] - (value.TryGetValue(key, out value2) ? value2 : 0); if (num2 > 0) { float num3 = (float)num2 * TierWeights[key]; if (num3 > num) { num = num3; result = key; } } } return result; } public static int GetDeficit(NetworkUser user, ItemTier tier) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) List<NetworkUser> players = GetPlayers(); if (players.Count <= 1) { return 0; } Dictionary<uint, Dictionary<ItemTier, int>> dictionary = new Dictionary<uint, Dictionary<ItemTier, int>>(); NetworkInstanceId netId; foreach (NetworkUser item in players) { object obj; if (item == null) { obj = null; } else { CharacterMaster master = item.master; obj = ((master != null) ? master.inventory : null); } if ((Object)obj != (Object)null) { netId = ((NetworkBehaviour)item).netId; dictionary[((NetworkInstanceId)(ref netId)).Value] = CountItemsByTier(item); } } netId = ((NetworkBehaviour)user).netId; if (!dictionary.TryGetValue(((NetworkInstanceId)(ref netId)).Value, out var value)) { return 0; } int value2; int num = (value.TryGetValue(tier, out value2) ? value2 : 0); int value3; int num2 = dictionary.Values.Select((Dictionary<ItemTier, int> dict) => dict.TryGetValue(tier, out value3) ? value3 : 0).Max(); return Math.Max(0, num2 - num); } public static float GetCatchupChance(int deficit, ItemTier tier) { if (deficit <= 0) { return 0f; } return Math.Min((float)deficit * 0.05f, 0.5f); } public static PickupIndex GetRandomPickupForTier(ItemTier tier) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected I4, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Run.instance == (Object)null) { return PickupIndex.none; } try { List<PickupIndex> list = (int)tier switch { 0 => Run.instance.availableTier1DropList, 1 => Run.instance.availableTier2DropList, 2 => Run.instance.availableTier3DropList, 4 => Run.instance.availableBossDropList, _ => null, }; if (list != null && list.Count > 0) { return list[Random.Range(0, list.Count)]; } } catch { } return PickupIndex.none; } private static List<NetworkUser> GetPlayers() { if (NetworkUser.readOnlyInstancesList != null && NetworkUser.readOnlyInstancesList.Count > 0) { return NetworkUser.readOnlyInstancesList.ToList(); } return (from p in PlayerCharacterMasterController.instances where (Object)(object)((p != null) ? p.networkUser : null) != (Object)null select p.networkUser).ToList(); } private static Dictionary<ItemTier, int> CountItemsByTier(NetworkUser user) { //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Dictionary<ItemTier, int> dictionary = new Dictionary<ItemTier, int>(); object obj; if (user == null) { obj = null; } else { CharacterMaster master = user.master; obj = ((master != null) ? master.inventory : null); } Inventory val = (Inventory)obj; if ((Object)(object)val == (Object)null) { return dictionary; } foreach (ItemTier value in Enum.GetValues(typeof(ItemTier))) { if (!IgnoredTiers.Contains(value)) { try { dictionary[value] = val.GetTotalItemCountOfTier(value); } catch { dictionary[value] = 0; } } } return dictionary; } } public class SpawnCustomController : NetworkBehaviour { [NetworkMessageHandler(msgType = 969, client = true)] public static void HandlePickupMessage(NetworkMessage netMsg) { //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) SpawnCustomMessage spawnCustomMessage = new SpawnCustomMessage(); netMsg.ReadMessage<SpawnCustomMessage>(spawnCustomMessage); Log.Info($"HandlePickupMessage {spawnCustomMessage.pickupIndex.value}"); CreatePickupDroplet(spawnCustomMessage.pickupIndex, spawnCustomMessage.position); } public static void CreatePickupDroplet(PickupIndex pickupIndex, Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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) CreatePickupInfo val = default(CreatePickupInfo); val.rotation = Quaternion.identity; ((CreatePickupInfo)(ref val)).pickupIndex = pickupIndex; CreatePickupInfo val2 = val; UniquePickup val3 = default(UniquePickup); ((UniquePickup)(ref val3))..ctor(pickupIndex); GameObject obj = Object.Instantiate<GameObject>(CommandArtifactManager.commandCubePrefab, position, val2.rotation); PickupIndexNetworker component = obj.GetComponent<PickupIndexNetworker>(); PickupPickerController component2 = obj.GetComponent<PickupPickerController>(); component2.SetOptionsInternal(PickupPickerController.GetOptionsFromPickupState(val3)); if (!NetworkServer.active) { ((NetworkBehaviour)component2).SetDirtyBit(PickupPickerController.optionsDirtyBit); } component.NetworkpickupState = val3; if (Object.op_Implicit((Object)(object)component.pickupDisplay)) { component.pickupDisplay.SetPickup(ref val3, false); } } public static void CreatePickupItem(PickupIndex pickupIndex, Vector3 position) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active) { CreatePickupInfo val = default(CreatePickupInfo); val.rotation = Quaternion.identity; val.position = position; ((CreatePickupInfo)(ref val)).pickupIndex = pickupIndex; CreatePickupInfo val2 = val; UniquePickup val3 = default(UniquePickup); ((UniquePickup)(ref val3))..ctor(pickupIndex); GameObject obj = Object.Instantiate<GameObject>(val2.prefabOverride ?? GenericPickupController.pickupPrefab, position, val2.rotation); GenericPickupController component = obj.GetComponent<GenericPickupController>(); if (Object.op_Implicit((Object)(object)component)) { component.Network_pickupState = val3; } PickupIndexNetworker component2 = obj.GetComponent<PickupIndexNetworker>(); if (Object.op_Implicit((Object)(object)component2)) { component2.NetworkpickupState = val3; } PickupPickerController component3 = obj.GetComponent<PickupPickerController>(); if (Object.op_Implicit((Object)(object)component3) && val2.pickerOptions != null) { component3.SetOptionsServer(val2.pickerOptions); } NetworkServer.Spawn(obj); } } } public class SpawnCustomMessage : MessageBase, INetMessage, ISerializableObject { public Vector3 position; public PickupIndex pickupIndex; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(position); writer.Write(pickupIndex.value); } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0018: Unknown result type (might be due to invalid IL or missing references) position = reader.ReadVector3(); pickupIndex = new PickupIndex(reader.ReadInt32()); } public void OnReceived() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) SpawnCustomController.CreatePickupItem(pickupIndex, position); } } public struct SpawnCustomMessage2 : INetMessage, ISerializableObject { public Vector3 position; public PickupIndex pickupIndex; public void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(position); writer.Write(pickupIndex.value); } public void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: 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_0018: Unknown result type (might be due to invalid IL or missing references) position = reader.ReadVector3(); pickupIndex = new PickupIndex(reader.ReadInt32()); } public void OnReceived() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) SpawnCustomController.CreatePickupItem(pickupIndex, position); } public SpawnCustomMessage2(PickupIndex pickupIndex, Vector3 position) { //IL_0001: 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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) this.position = position; this.pickupIndex = pickupIndex; } } }