using System; using System.Collections.Generic; using System.Diagnostics; 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 Microsoft.CodeAnalysis; using On.RoR2; using On.RoR2.Artifacts; using On.RoR2.UI; using RoR2; using RoR2.Artifacts; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.Networking; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("EarlyBirdSacrifice")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("EarlyBirdSacrifice")] [assembly: AssemblyTitle("EarlyBirdSacrifice")] [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 EarlyBirdSacrifice { [BepInPlugin("com.FortressForce.earlybirdsacrifice", "EarlyBirdSacrifice", "1.0.0")] public class Plugin : BaseUnityPlugin { public class SyncSacrificeMessage : MessageBase { public float currentKillProgress; public int itemsDroppedInStage; public float killsNeededPerDrop; public int bufferRemainingInStage; public override void Serialize(NetworkWriter writer) { writer.Write(currentKillProgress); writer.Write(itemsDroppedInStage); writer.Write(killsNeededPerDrop); writer.Write(bufferRemainingInStage); } public override void Deserialize(NetworkReader reader) { currentKillProgress = reader.ReadSingle(); itemsDroppedInStage = reader.ReadInt32(); killsNeededPerDrop = reader.ReadSingle(); bufferRemainingInStage = reader.ReadInt32(); } } [CompilerGenerated] private static class <>O { public static NetworkMessageDelegate <0>__OnSyncMessage; } public const string PluginGUID = "com.FortressForce.earlybirdsacrifice"; public const string PluginName = "EarlyBirdSacrifice"; public const string PluginVersion = "1.0.0"; internal static ManualLogSource Log; public static ConfigEntry BufferCount; public static ConfigEntry BaseKillRequirement; public static ConfigEntry KillTaxPerDrop; public static ConfigEntry EliteBossDropMode; public static ConfigEntry EliteKillWeight; public static ConfigEntry BossKillWeight; public static ConfigEntry EliteExtraDropChance; public static ConfigEntry BossExtraDropChance; public static ConfigEntry ForceConsoleLogging; public static ConfigEntry StageBufferBonus; public static ConfigEntry StageBonusTax; public static ConfigEntry DoppelgangerDropMode; public static ConfigEntry DoppelgangerDropChance; public static ConfigEntry DoppelgangerBossWeight; public static ConfigEntry DoppelgangerLegendaryWeight; public static ConfigEntry DoppelgangerUncommonWeight; public static ConfigEntry DoppelgangerVoidUncommonWeight; public static ConfigEntry EnableGUI; public static ConfigEntry GUIPositionX; public static ConfigEntry GUIPositionY; public static ConfigEntry GUIFontSize; public static ConfigEntry AutoScaleForSwarms; public static ConfigEntry AutoScaleForSoul; private static float currentKillProgress = 0f; private static int itemsDroppedInStage = 0; private static float killsNeededPerDrop = 1f; private static int bufferRemainingInStage = 5; private static HGTextMeshProUGUI hudTextComponent = null; private void Awake() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Expected O, but got Unknown //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0396: Expected O, but got Unknown //IL_039d: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Expected O, but got Unknown //IL_03ae: Unknown result type (might be due to invalid IL or missing references) //IL_03b8: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; BufferCount = ((BaseUnityPlugin)this).Config.Bind("General", "BufferCount", 5, "Number of initial 'free' drops before the kill tax increases."); BaseKillRequirement = ((BaseUnityPlugin)this).Config.Bind("General", "BaseKillRequirement", 1, "The initial number of kills required per drop during the first buffer."); KillTaxPerDrop = ((BaseUnityPlugin)this).Config.Bind("General", "KillTaxPerDrop", 1, "The additional kills added to the requirement each time the buffer is depleted."); EliteBossDropMode = ((BaseUnityPlugin)this).Config.Bind("General", "EliteBossDropMode", "percent", new ConfigDescription("Determines how Elite and Boss/Champion deaths are handled regarding item drops and kill progression.", (AcceptableValueBase)(object)new AcceptableValueList(new string[3] { "percent", "extra credit", "both" }), Array.Empty())); EliteKillWeight = ((BaseUnityPlugin)this).Config.Bind("General", "EliteKillWeight", 2, "How many normal kills an Elite enemy counts as toward the progress bar (only active if EliteBossDropMode is 'extra credit' or 'both')."); BossKillWeight = ((BaseUnityPlugin)this).Config.Bind("General", "BossKillWeight", 5, "How many normal kills a Boss/Champion enemy counts as toward the progress bar (only active if EliteBossDropMode is 'extra credit' or 'both')."); EliteExtraDropChance = ((BaseUnityPlugin)this).Config.Bind("General", "EliteExtraDropChance", 3f, "Percent chance (0-100) that an Elite enemy triggers an extra lucky drop on death (enabled by default)."); BossExtraDropChance = ((BaseUnityPlugin)this).Config.Bind("General", "BossExtraDropChance", 30f, "Percent chance (0-100) that a Boss/Champion triggers an extra lucky drop on death (enabled by default)."); ForceConsoleLogging = ((BaseUnityPlugin)this).Config.Bind("General", "ForceConsoleLogging", false, "Set to true to force progress updates as Info logs (visible by default) in the BepInEx console."); StageBufferBonus = ((BaseUnityPlugin)this).Config.Bind("General", "StageBufferBonus", 2, "Additional free drops added to the stage buffer for each stage cleared in the run."); StageBonusTax = ((BaseUnityPlugin)this).Config.Bind("General", "StageBonusTax", 1, "Additional base kills required per drop for each stage cleared in the run."); DoppelgangerDropMode = ((BaseUnityPlugin)this).Config.Bind("Vengeance", "DoppelgangerDropMode", "Boss", new ConfigDescription("The tier of item dropped by Vengeance doppelgangers on death.", (AcceptableValueBase)(object)new AcceptableValueList(new string[5] { "Boss", "Legendary", "Void Uncommon", "Uncommon", "Random" }), Array.Empty())); DoppelgangerDropChance = ((BaseUnityPlugin)this).Config.Bind("Vengeance", "DoppelgangerDropChance", 100f, "Percent chance (0-100) that a Vengeance doppelganger will drop its configured special item on death."); DoppelgangerBossWeight = ((BaseUnityPlugin)this).Config.Bind("Vengeance Weights", "DoppelgangerBossWeight", 40f, "Percentage weight for dropping a Boss item when DoppelgangerDropMode is 'Random'."); DoppelgangerLegendaryWeight = ((BaseUnityPlugin)this).Config.Bind("Vengeance Weights", "DoppelgangerLegendaryWeight", 30f, "Percentage weight for dropping a Legendary item when DoppelgangerDropMode is 'Random'."); DoppelgangerUncommonWeight = ((BaseUnityPlugin)this).Config.Bind("Vengeance Weights", "DoppelgangerUncommonWeight", 20f, "Percentage weight for dropping an Uncommon item when DoppelgangerDropMode is 'Random'."); DoppelgangerVoidUncommonWeight = ((BaseUnityPlugin)this).Config.Bind("Vengeance Weights", "DoppelgangerVoidUncommonWeight", 10f, "Percentage weight for dropping a Void Uncommon item when DoppelgangerDropMode is 'Random'."); EnableGUI = ((BaseUnityPlugin)this).Config.Bind("HUD", "EnableGUI", true, "Should the on-screen HUD progress text be visible?"); GUIPositionX = ((BaseUnityPlugin)this).Config.Bind("HUD", "GUIPositionX", -40f, "Horizontal anchored position from the right side of the screen."); GUIPositionY = ((BaseUnityPlugin)this).Config.Bind("HUD", "GUIPositionY", -360f, "Vertical anchored position from the top of the screen (sits perfectly below the teleporter tracker)."); GUIFontSize = ((BaseUnityPlugin)this).Config.Bind("HUD", "GUIFontSize", 14f, "The font size of the HUD tracker text."); AutoScaleForSwarms = ((BaseUnityPlugin)this).Config.Bind("Balance Scaling", "AutoScaleForSwarms", true, "If true, automatically halves the required kills and taxes if the Artifact of Swarms is NOT active (since Swarms doubles spawns)."); AutoScaleForSoul = ((BaseUnityPlugin)this).Config.Bind("Balance Scaling", "AutoScaleForSoul", true, "If true, automatically halves the required kills and taxes if the Artifact of Soul is NOT active (since Soul wisps yield extra kills)."); SacrificeArtifactManager.OnServerCharacterDeath += new hook_OnServerCharacterDeath(SacrificeArtifactManager_OnServerCharacterDeath); Run.Start += new hook_Start(Run_Start); HUD.Awake += new hook_Awake(HUD_Awake); Stage.onStageStartGlobal += OnStageStart; Log.LogInfo((object)"EarlyBirdSacrifice has successfully initialized!"); } private void OnDestroy() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown Stage.onStageStartGlobal -= OnStageStart; SacrificeArtifactManager.OnServerCharacterDeath -= new hook_OnServerCharacterDeath(SacrificeArtifactManager_OnServerCharacterDeath); Run.Start -= new hook_Start(Run_Start); HUD.Awake -= new hook_Awake(HUD_Awake); } private static void LogProgress(string message) { if (ForceConsoleLogging.Value) { Log.LogInfo((object)message); } else { Log.LogDebug((object)message); } } private void Run_Start(orig_Start orig, Run self) { orig.Invoke(self); if (NetworkServer.active) { currentKillProgress = 0f; itemsDroppedInStage = 0; int num = (((Object)(object)self != (Object)null) ? self.stageClearCount : 0); float artifactScaleFactor = GetArtifactScaleFactor(); killsNeededPerDrop = (float)(BaseKillRequirement.Value + num * StageBonusTax.Value) * artifactScaleFactor; if (killsNeededPerDrop < 1f) { killsNeededPerDrop = 1f; } bufferRemainingInStage = BufferCount.Value + num * StageBufferBonus.Value; LogProgress($"New run started! Resetting Early Bird Sacrifice counters. Clear count: {num}. Artifact Scale: {artifactScaleFactor:F2}. Required kills: {killsNeededPerDrop:F1}, Stage buffer size: {bufferRemainingInStage}"); UpdateHUDText(); SyncState(); } } private void OnStageStart(Stage stage) { if (NetworkServer.active) { currentKillProgress = 0f; itemsDroppedInStage = 0; int num = (((Object)(object)Run.instance != (Object)null) ? Run.instance.stageClearCount : 0); float artifactScaleFactor = GetArtifactScaleFactor(); killsNeededPerDrop = (float)(BaseKillRequirement.Value + num * StageBonusTax.Value) * artifactScaleFactor; if (killsNeededPerDrop < 1f) { killsNeededPerDrop = 1f; } bufferRemainingInStage = BufferCount.Value + num * StageBufferBonus.Value; string text = (((Object)(object)stage != (Object)null && (Object)(object)stage.sceneDef != (Object)null) ? stage.sceneDef.cachedName : "Unknown"); LogProgress($"New stage entered ({text})! Resetting Early Bird Sacrifice counters. Clear count: {num}. Artifact Scale: {artifactScaleFactor:F2}. Required kills: {killsNeededPerDrop:F1}, Stage buffer size: {bufferRemainingInStage}"); UpdateHUDText(); SyncState(); } } private static Transform FindChildRecursive(Transform parent, string name) { if (((Object)parent).name == name) { return parent; } for (int i = 0; i < parent.childCount; i++) { Transform val = FindChildRecursive(parent.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } private void HUD_Awake(orig_Awake orig, HUD self) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0265: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02d6: Expected O, but got Unknown orig.Invoke(self); if (!EnableGUI.Value) { return; } try { GameObject val = new GameObject("EarlyBirdSacrificeHUDText"); val.layer = 5; RectTransform val2 = val.AddComponent(); Transform val3 = null; ObjectivePanelController componentInChildren = ((Component)self).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { val3 = ((Component)componentInChildren).transform; LogProgress("ObjectivePanelController component found successfully."); } else { val3 = FindChildRecursive(((Component)self).transform, "ObjectiveCluster"); if ((Object)(object)val3 == (Object)null) { val3 = FindChildRecursive(((Component)self).transform, "ObjectivePanel"); } if ((Object)(object)val3 != (Object)null) { LogProgress("ObjectiveCluster found via recursive name search: " + ((Object)val3).name); } } if ((Object)(object)val3 != (Object)null) { val.transform.SetParent(val3, false); val.transform.SetAsLastSibling(); LayoutElement obj = val.AddComponent(); obj.minHeight = 45f; obj.preferredHeight = 45f; val2.anchorMin = new Vector2(0f, 0f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(0.5f, 0.5f); LogProgress("HUD Text attached as child of Objective panel."); } else { val.transform.SetParent(self.mainContainer.transform, false); val2.anchorMin = new Vector2(1f, 1f); val2.anchorMax = new Vector2(1f, 1f); val2.pivot = new Vector2(1f, 1f); val2.anchoredPosition = new Vector2(GUIPositionX.Value, GUIPositionY.Value); val2.sizeDelta = new Vector2(250f, 65f); LogProgress("Objective Cluster container not found. Falling back to mainContainer manual offsets."); } hudTextComponent = val.AddComponent(); TMP_FontAsset val4 = null; HGTextMeshProUGUI[] componentsInChildren = ((Component)self).GetComponentsInChildren(true); foreach (HGTextMeshProUGUI val5 in componentsInChildren) { if ((Object)(object)val5 != (Object)null && (Object)(object)((TMP_Text)val5).font != (Object)null) { val4 = ((TMP_Text)val5).font; break; } } if ((Object)(object)val4 != (Object)null) { ((TMP_Text)hudTextComponent).font = val4; } ((TMP_Text)hudTextComponent).fontSize = GUIFontSize.Value; ((TMP_Text)hudTextComponent).alignment = (TextAlignmentOptions)258; ((Graphic)hudTextComponent).color = new Color(0.9f, 0.9f, 0.9f, 1f); val.SetActive(true); UpdateHUDText(); try { if ((Object)(object)NetworkManager.singleton != (Object)null && NetworkManager.singleton.client != null) { short num = 1337; NetworkClient client = NetworkManager.singleton.client; if (!client.handlers.ContainsKey(num)) { object obj2 = <>O.<0>__OnSyncMessage; if (obj2 == null) { NetworkMessageDelegate val6 = OnSyncMessage; <>O.<0>__OnSyncMessage = val6; obj2 = (object)val6; } client.RegisterHandler(num, (NetworkMessageDelegate)obj2); LogProgress("Registered client network sync message handler successfully."); } } } catch (Exception ex) { Log.LogError((object)("Failed to register client message handler: " + ex.Message)); } LogProgress("HUD Text initialized successfully using HGTextMeshProUGUI."); } catch (Exception ex2) { Log.LogError((object)("Failed to initialize HUD text: " + ex2.Message)); } } private static void UpdateHUDText() { if ((Object)(object)hudTextComponent == (Object)null) { return; } if ((Object)(object)Run.instance == (Object)null || (Object)(object)RunArtifactManager.instance == (Object)null || !RunArtifactManager.instance.IsArtifactEnabled(Artifacts.Sacrifice)) { ((TMP_Text)hudTextComponent).text = ""; return; } int stageClearCount = Run.instance.stageClearCount; float artifactScaleFactor = GetArtifactScaleFactor(); float num = (float)(BaseKillRequirement.Value + stageClearCount * StageBonusTax.Value) * artifactScaleFactor; if (num < 1f) { num = 1f; } int num2 = BufferCount.Value + stageClearCount * StageBufferBonus.Value; string text = ""; text = ((bufferRemainingInStage <= 0 || !(killsNeededPerDrop <= num + 0.01f)) ? $"Sacrifice:\n{currentKillProgress:F0}/{killsNeededPerDrop:F0} kills needed" : $"Sacrifice:\n{itemsDroppedInStage}/{num2} drops"); ((TMP_Text)hudTextComponent).text = text; } private void SacrificeArtifactManager_OnServerCharacterDeath(orig_OnServerCharacterDeath orig, DamageReport damageReport) { bool flag = false; try { if ((Object)(object)damageReport.victimBody.inventory != (Object)null && damageReport.victimBody.inventory.GetItemCountEffective(Items.InvadingDoppelganger) > 0) { flag = true; } } catch (Exception) { } if (flag) { float num = Random.Range(0f, 100f); if (num <= DoppelgangerDropChance.Value) { SpawnSpecialDoppelgangerDrop(damageReport); } else { LogProgress($"Vengeance doppelganger killed, but rolled no-drop ({num:F1}% vs {DoppelgangerDropChance.Value}% chance)."); } return; } string text = (EliteBossDropMode.Value ?? "percent").Trim().ToLowerInvariant(); bool flag2 = text == "extra credit" || text == "both"; bool flag3 = text == "percent" || text == "both"; float num2 = 1f; if (damageReport.victimBody.isElite) { if (flag2) { num2 = EliteKillWeight.Value; LogProgress($"Elite killed! Added {num2} to progress (Drop Mode: {text})."); } else { LogProgress("Elite killed! Added 1.0 to progress (Drop Mode: " + text + ")."); } if (flag3) { float num3 = Random.Range(0f, 100f); if (num3 <= EliteExtraDropChance.Value) { SpawnSacrificeDrop(damageReport); Log.LogInfo((object)$"Elite lucky drop triggered ({num3:F1}% roll vs {EliteExtraDropChance.Value}% limit)! Spawned bonus item."); } } } else if (damageReport.victimBody.isChampion) { if (flag2) { num2 = BossKillWeight.Value; LogProgress($"Boss/Champion killed! Added {num2} to progress (Drop Mode: {text})."); } else { LogProgress("Boss/Champion killed! Added 1.0 to progress (Drop Mode: " + text + ")."); } if (flag3) { float num4 = Random.Range(0f, 100f); if (num4 <= BossExtraDropChance.Value) { SpawnSacrificeDrop(damageReport); Log.LogInfo((object)$"Boss lucky drop triggered ({num4:F1}% roll vs {BossExtraDropChance.Value}% limit)! Spawned bonus item."); } } } currentKillProgress += num2; LogProgress($"Progress: {currentKillProgress:F1} / {killsNeededPerDrop:F1} (Buffer Remaining: {bufferRemainingInStage}, Stage Drops: {itemsDroppedInStage})"); while (currentKillProgress >= killsNeededPerDrop) { currentKillProgress -= killsNeededPerDrop; itemsDroppedInStage++; SpawnSacrificeDrop(damageReport); bufferRemainingInStage--; if (bufferRemainingInStage <= 0) { bufferRemainingInStage = BufferCount.Value; float artifactScaleFactor = GetArtifactScaleFactor(); float num5 = (float)KillTaxPerDrop.Value * artifactScaleFactor; killsNeededPerDrop += num5; LogProgress($"Buffer depleted! Refilling buffer to {bufferRemainingInStage} and increasing required kills to {killsNeededPerDrop:F1} (added tax: {num5:F2})."); } } UpdateHUDText(); SyncState(); } private void SpawnSacrificeDrop(DamageReport damageReport) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0059: 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) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) try { PickupDropTable val = (PickupDropTable)typeof(SacrificeArtifactManager).GetField("dropTable", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null); Xoroshiro128Plus val2 = (Xoroshiro128Plus)typeof(SacrificeArtifactManager).GetField("treasureRng", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null); if ((Object)(object)val != (Object)null && val2 != null) { UniquePickup val3 = val.GeneratePickup(val2); if (val3.pickupIndex != PickupIndex.none) { Vector3 corePosition = damageReport.victimBody.corePosition; Vector3 val4 = Vector3.up * 15f + Random.insideUnitSphere * 2f; CreatePickupInfo val5 = default(CreatePickupInfo); ((CreatePickupInfo)(ref val5)).pickup = val3; val5.position = corePosition; val5.rotation = Quaternion.identity; PickupDropletController.CreatePickupDroplet(val5, corePosition, val4); } } else { Log.LogError((object)"Could not retrieve Sacrifice drop table or RNG via reflection."); } } catch (Exception ex) { Log.LogError((object)("Failed to spawn deterministic Sacrifice drop: " + ex.Message)); } } private void SpawnSpecialDoppelgangerDrop(DamageReport damageReport) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Unknown result type (might be due to invalid IL or missing references) try { Xoroshiro128Plus val = (Xoroshiro128Plus)typeof(SacrificeArtifactManager).GetField("treasureRng", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(null); if (val == null) { val = Run.instance.treasureRng; } string text = (DoppelgangerDropMode.Value ?? "Boss").Trim().ToLowerInvariant(); List list = null; string text2 = ""; switch (text) { case "boss": list = Run.instance.availableBossDropList; text2 = "Boss"; break; case "legendary": list = Run.instance.availableTier3DropList; text2 = "Legendary"; break; case "uncommon": list = Run.instance.availableTier2DropList; text2 = "Uncommon"; break; case "void uncommon": { List availableVoidTier2DropList2 = Run.instance.availableVoidTier2DropList; if (availableVoidTier2DropList2 != null && availableVoidTier2DropList2.Count > 0) { list = availableVoidTier2DropList2; text2 = "Void Uncommon"; } else { list = Run.instance.availableTier2DropList; text2 = "Uncommon (Void Uncommon DLC not active fallback)"; } break; } case "random": { float num = Mathf.Max(0f, DoppelgangerBossWeight.Value); float num2 = Mathf.Max(0f, DoppelgangerLegendaryWeight.Value); float num3 = Mathf.Max(0f, DoppelgangerUncommonWeight.Value); float num4 = Mathf.Max(0f, DoppelgangerVoidUncommonWeight.Value); List availableVoidTier2DropList = Run.instance.availableVoidTier2DropList; if (availableVoidTier2DropList == null || availableVoidTier2DropList.Count == 0) { num4 = 0f; } float num5 = num + num2 + num3 + num4; if (num5 <= 0f) { num = 1f; num5 = 1f; } float num6 = Random.Range(0f, num5); if (num6 < num) { list = Run.instance.availableBossDropList; text2 = "Boss (Random Weight)"; } else if (num6 < num + num2) { list = Run.instance.availableTier3DropList; text2 = "Legendary (Random Weight)"; } else if (num6 < num + num2 + num3) { list = Run.instance.availableTier2DropList; text2 = "Uncommon (Random Weight)"; } else { list = availableVoidTier2DropList; text2 = "Void Uncommon (Random Weight)"; } break; } } if (list != null && list.Count > 0) { int index = val.RangeInt(0, list.Count); PickupIndex val2 = list[index]; if (val2 != PickupIndex.none) { Vector3 corePosition = damageReport.victimBody.corePosition; Vector3 val3 = Vector3.up * 15f + Random.insideUnitSphere * 2f; UniquePickup pickup = default(UniquePickup); pickup.pickupIndex = val2; CreatePickupInfo val4 = default(CreatePickupInfo); ((CreatePickupInfo)(ref val4)).pickup = pickup; val4.position = corePosition; val4.rotation = Quaternion.identity; PickupDropletController.CreatePickupDroplet(val4, corePosition, val3); Log.LogInfo((object)$"Vengeance doppelganger killed! Spawned special item drop. Tier: {text2}, Item: {val2}."); } } else { Log.LogError((object)("Vengeance doppelganger drop failed: Selected target pool '" + text2 + "' was null or empty.")); } } catch (Exception ex) { Log.LogError((object)("Failed to spawn doppelganger drop: " + ex.Message)); } } private static void OnSyncMessage(NetworkMessage netMsg) { try { SyncSacrificeMessage syncSacrificeMessage = netMsg.ReadMessage(); if (syncSacrificeMessage != null) { currentKillProgress = syncSacrificeMessage.currentKillProgress; itemsDroppedInStage = syncSacrificeMessage.itemsDroppedInStage; killsNeededPerDrop = syncSacrificeMessage.killsNeededPerDrop; bufferRemainingInStage = syncSacrificeMessage.bufferRemainingInStage; UpdateHUDText(); } } catch (Exception ex) { Log.LogError((object)("Failed to handle SyncSacrificeMessage: " + ex.Message)); } } private static void SyncState() { if (!NetworkServer.active) { return; } try { SyncSacrificeMessage syncSacrificeMessage = new SyncSacrificeMessage { currentKillProgress = currentKillProgress, itemsDroppedInStage = itemsDroppedInStage, killsNeededPerDrop = killsNeededPerDrop, bufferRemainingInStage = bufferRemainingInStage }; NetworkServer.SendToAll((short)1337, (MessageBase)(object)syncSacrificeMessage); } catch (Exception ex) { Log.LogError((object)("Failed to send SyncSacrificeMessage: " + ex.Message)); } } private static float GetArtifactScaleFactor() { float num = 1f; if ((Object)(object)RunArtifactManager.instance != (Object)null) { if (AutoScaleForSwarms != null && AutoScaleForSwarms.Value && !RunArtifactManager.instance.IsArtifactEnabled(Artifacts.Swarms)) { num *= 0.5f; } if (AutoScaleForSoul != null && AutoScaleForSoul.Value && !RunArtifactManager.instance.IsArtifactEnabled(Artifacts.WispOnDeath)) { num *= 0.5f; } } return num; } } }