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 VanillaPlusPlus v0.1.0
BepInEx/plugins/VanillaPlusPlus/Olligame.VanillaVoidQuality.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BepInEx; using BepInEx.Bootstrap; using EntityStates; using EntityStates.DeepVoidPortalBattery; using ItemQualities; using ItemQualities.ContentManagement; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using On.RoR2; using On.RoR2.Projectile; using R2API; using RoR2; using RoR2.Projectile; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using vanillaVoid.Items; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace OlligameVoidQuality; [BepInPlugin("Olligame.VanillaVoidQuality", "Vanilla Void Quality", "0.1.0")] [BepInDependency("Olligame.SeparateVoidDonation", "1.7.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency("com.Gorakh.ItemQualities", "0.8.5")] [BepInDependency("com.Zenithrium.vanillaVoid", "1.7.2")] public sealed class Plugin : BaseUnityPlugin { private delegate bool OriginalDelivery(VoidShell self, bool original, Charged state); private delegate bool ReplaceDelivery(OriginalDelivery orig, VoidShell self, bool original, Charged state); internal static Plugin Instance; internal static readonly Dictionary<string, ItemQualityGroup> Groups = new Dictionary<string, ItemQualityGroup>(); internal static readonly Dictionary<string, ItemBase> Items = new Dictionary<string, ItemBase>(); internal static BuffDef DashRefund; internal static BuffDef WatchHits; private static GameObject largeRocket; private readonly List<IDisposable> hooks = new List<IDisposable>(); internal static readonly float[] Strength = new float[4] { 1f, 2f, 4f, 6f }; private static readonly string[] ids = new string[15] { "AbyssalAdze", "ClockworkMechanism", "EnhancementVials", "ExtraterrestrialExhaust", "CryoCanister", "VoidShell", "CorrosiveCore", "CrystalLotus", "ExeBlade", "DashQuill", "VoidFin", "LensOrrery", "ConsumedClockworkMechanism", "EmptyVials", "ShatteredVials" }; private void Awake() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Expected O, but got Unknown //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) Instance = this; List<string> list = new List<string>(NetworkModCompatibilityHelper.networkModList); list.Add("Olligame.VanillaVoidQuality;0.1.0"); NetworkModCompatibilityHelper.networkModList = list; QualityContentManager.LoadContentAsync += new LoadContentAsyncDelegate(LoadContent); ((ResourceAvailability)(ref QualityCatalog.Availability)).CallWhenAvailable((Action)ValidateCatalog); DashRefund = ScriptableObject.CreateInstance<BuffDef>(); ((Object)DashRefund).name = "OlligameVoidQualityDashRefund"; DashRefund.canStack = true; DashRefund.isHidden = true; ContentAddition.AddBuffDef(DashRefund); WatchHits = ScriptableObject.CreateInstance<BuffDef>(); ((Object)WatchHits).name = "OlligameVoidQualityWatchHits"; WatchHits.canStack = true; WatchHits.isHidden = true; ContentAddition.AddBuffDef(WatchHits); if (Object.op_Implicit((Object)(object)ExtraterrestrialExhaust.RocketProjectile)) { largeRocket = PrefabAPI.InstantiateClone(ExtraterrestrialExhaust.RocketProjectile, "OlligameQualityRocketProjectile", true); Transform transform = largeRocket.transform; transform.localScale *= 1.5f; ProjectileImpactExplosion component = largeRocket.GetComponent<ProjectileImpactExplosion>(); if (Object.op_Implicit((Object)(object)component)) { ((ProjectileExplosion)component).blastRadius = ((ProjectileExplosion)component).blastRadius * 1.5f; } ContentAddition.AddProjectile(largeRocket); } CharacterBody.onBodyStartGlobal += BodyStarted; GlobalEventManager.onCharacterDeathGlobal += Death; HealthComponent.TakeDamage += new hook_TakeDamage(TakeDamage); GlobalEventManager.OnHitEnemy += new hook_OnHitEnemy(Hit); ProjectileManager.FireProjectile_FireProjectileInfo += new hook_FireProjectile_FireProjectileInfo(Fire); HoldoutZoneController.Awake += new hook_Awake(Holdout); RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(Stats); InstallSpecificHooks(); ConsumableSupport.Install(hooks); ScrapCompatibility.Install(hooks); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Vanilla Void Quality 0.1.0: custom quality groups and item-specific bonuses enabled."); } private void ValidateCatalog() { //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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_004d: Invalid comparison between Unknown and I4 int num = 0; foreach (KeyValuePair<string, ItemQualityGroup> group in Groups) { for (int i = 0; i < 4; i++) { ItemIndex itemIndex = group.Value.GetItemIndex((QualityTier)i); if ((int)itemIndex == -1 || itemIndex == group.Value.BaseItemIndex || (int)QualityCatalog.GetQualityTier(itemIndex) != i) { ((BaseUnityPlugin)this).Logger.LogError((object)("Missing quality variant: " + group.Key + " / " + (object)(QualityTier)i)); } else { num++; } } } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Vanilla Void Quality ready: " + Groups.Count + " groups, " + num + " quality variants. Void Scrap names and Mark for Scrap compatibility enabled when installed.")); } private IEnumerator LoadContent(QualityContentLoadArgs args) { _ = typeof(ItemBase).Assembly; BaseUnityPlugin plugin = Chainloader.PluginInfos["com.Zenithrium.vanillaVoid"].Instance; IEnumerable all = (IEnumerable)((object)plugin).GetType().GetField("Items", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(plugin); foreach (ItemBase item in all) { ItemBase val = item; string name = ((object)val).GetType().Name; if (Array.IndexOf(ids, name) >= 0 && Object.op_Implicit((Object)(object)val.ItemDef)) { Items[name] = val; Groups[name] = args.CreateItemQualityGroup(val.ItemDef); for (int i = 0; i < 4; i++) { string text = "ITEM_" + ((Object)val.ItemDef).name.ToUpperInvariant() + "_" + ((object)(QualityTier)i).ToString().ToUpperInvariant(); string text2 = Description(name, i); LanguageAPI.Add(text + "_PICKUP", "{0}\n<sprite name=\"Quality\"> " + text2); LanguageAPI.Add(text + "_DESC", "{0}\n<sprite name=\"Quality\"> " + text2); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Registered quality variants: " + val.ItemName)); } } yield return ScrapCompatibility.LoadContent(args); } internal static float Power(Inventory inventory, string id) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Invalid comparison between Unknown and I4 //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)inventory) || !Groups.TryGetValue(id, out var value)) { return 0f; } float num = 0f; for (int i = 0; i < 4; i++) { ItemIndex itemIndex = value.GetItemIndex((QualityTier)i); if ((int)itemIndex != -1) { num += (float)inventory.GetItemCountEffective(itemIndex) * Strength[i]; } } return num; } internal static float Power(CharacterBody body, string id) { return Object.op_Implicit((Object)(object)body) ? Power(body.inventory, id) : 0f; } internal static int Highest(CharacterBody body, string id) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Invalid comparison between Unknown and I4 //IL_0045: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || !Groups.TryGetValue(id, out var value)) { return -1; } for (int num = 3; num >= 0; num--) { if ((int)value.GetItemIndex((QualityTier)num) != -1 && body.inventory.GetItemCountEffective(value.GetItemIndex((QualityTier)num)) > 0) { return num; } } return -1; } internal static bool Roll(float percent, CharacterBody body) { return percent > 0f && Util.CheckRoll(Mathf.Min(100f, percent), Object.op_Implicit((Object)(object)body) ? body.master : null); } internal static BodyState State(CharacterBody body) { BodyState component = ((Component)body).GetComponent<BodyState>(); return Object.op_Implicit((Object)(object)component) ? component : ((Component)body).gameObject.AddComponent<BodyState>(); } private void BodyStarted(CharacterBody body) { if (body.isPlayerControlled) { State(body); } } private void TakeDamage(orig_TakeDamage orig, HealthComponent self, DamageInfo info) { if (!NetworkServer.active) { orig.Invoke(self, info); return; } CharacterBody val = (Object.op_Implicit((Object)(object)info.attacker) ? info.attacker.GetComponent<CharacterBody>() : null); if (Object.op_Implicit((Object)(object)self.body) && self.body.isPlayerControlled && info.damage > 0f && info.procCoefficient > 0f) { BodyState bodyState = State(self.body); bodyState.ResetStage(); if (self.body.GetBuffCount(WatchHits) < 25) { self.body.AddBuff(WatchHits); } } if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)self.body) && self.alive && info.damage > 0f) { Vulnerable component = ((Component)self).GetComponent<Vulnerable>(); if (Object.op_Implicit((Object)(object)component) && component.Until > Time.fixedTime) { info.damage *= 1f + component.Bonus; } float num = Power(val, "AbyssalAdze"); if (num > 0f && info.procCoefficient > 0f && self.combinedHealthFraction < 0.5f) { BodyState bodyState2 = State(val); if (++bodyState2.WoundedHits >= 10) { bodyState2.WoundedHits = 0; info.damage *= 1f + 0.5f * num; } } } orig.Invoke(self, info); } private void Hit(orig_OnHitEnemy orig, GlobalEventManager self, DamageInfo info, GameObject victim) { //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Expected O, but got Unknown orig.Invoke(self, info, victim); if (!NetworkServer.active || info.rejected || info.procCoefficient <= 0f || !Object.op_Implicit((Object)(object)info.attacker) || !Object.op_Implicit((Object)(object)victim)) { return; } CharacterBody component = info.attacker.GetComponent<CharacterBody>(); CharacterBody component2 = victim.GetComponent<CharacterBody>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component2)) { return; } float num = Power(component, "CorrosiveCore"); if (num > 0f && info.crit) { component2.AddTimedBuff(Buffs.Slow50, Mathf.Min(12f, 2f + num)); } float num2 = Power(component, "EnhancementVials"); float num3 = Power(component, "LensOrrery"); if (num2 <= 0f && num3 <= 0f) { return; } BodyState bodyState = State(component); if (num2 > 0f && Time.fixedTime >= bodyState.NextVial && Roll((5f + (float)Mathf.Min(20, ConsumedCount(component.inventory)) * 0.5f) * info.procCoefficient, component)) { bodyState.NextVial = Time.fixedTime + 0.5f; Area(component, component2.corePosition, 10f, 2.5f * num2, 3f); } if (!(num3 > 0f) || info.crit || !(Time.fixedTime >= bodyState.NextOrrery) || !Roll(20f * num3 * info.procCoefficient, component)) { return; } if (Items.TryGetValue("LensOrrery", out var value)) { BuffDef val = (BuffDef)((object)value).GetType().GetProperty("OrreryDamageBonus", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic).GetValue(value, null); LensOrrery val2 = (LensOrrery)(object)((value is LensOrrery) ? value : null); if (Object.op_Implicit((Object)(object)val) && val2 != null && val2.itemVariant.Value == 0 && component.GetBuffCount(val) < LensOrrery.buffStacksPerCount.Value * component.inventory.GetItemCountEffective(value.ItemDef)) { component.AddBuff(val); } } bodyState.NextOrrery = Time.fixedTime + 0.1f; } private static int ConsumedCount(Inventory inventory) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) int num = 0; foreach (ItemIndex item in inventory.itemAcquisitionOrder) { ItemDef itemDef = ItemCatalog.GetItemDef(item); if (Object.op_Implicit((Object)(object)itemDef) && itemDef.isConsumed) { num += inventory.GetItemCountEffective(item); } if (num >= 20) { return 20; } } return num; } private void Fire(orig_FireProjectile_FireProjectileInfo orig, ProjectileManager self, FireProjectileInfo info) { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (NetworkServer.active && Object.op_Implicit((Object)(object)info.projectilePrefab) && ((Object)info.projectilePrefab).name == "RocketProjectile" && Object.op_Implicit((Object)(object)info.owner)) { CharacterBody component = info.owner.GetComponent<CharacterBody>(); float num = Power(component, "ExtraterrestrialExhaust"); if (num > 0f && Roll(15f * num, component)) { info.damage *= 2f + 0.25f * num; if (Object.op_Implicit((Object)(object)largeRocket)) { info.projectilePrefab = largeRocket; } } } orig.Invoke(self, info); } private void Death(DamageReport report) { if (!NetworkServer.active || !Object.op_Implicit((Object)(object)report.attackerBody) || !Object.op_Implicit((Object)(object)report.victimBody)) { return; } CharacterBody attackerBody = report.attackerBody; float num = Power(attackerBody, "CryoCanister"); float num2 = Power(attackerBody, "DashQuill"); if (!(num <= 0f) || !(num2 <= 0f)) { BodyState bodyState = State(attackerBody); if (num > 0f && (report.victimBody.HasBuff(Buffs.Slow50) || report.victimBody.HasBuff(Buffs.Slow80) || IsVanillaVoidSlowed(report.victimBody))) { bodyState.FrostUntil = Time.fixedTime + Mathf.Min(12f, 3f + num); bodyState.FrostRadius = Mathf.Min(20f, bodyState.FrostRadius + 2f); } if (num2 > 0f && Object.op_Implicit((Object)(object)attackerBody.characterMotor) && !attackerBody.characterMotor.isGrounded && (float)bodyState.AirRefunds < Mathf.Min(20f, 2f * num2)) { bodyState.AirRefunds++; attackerBody.AddBuff(DashRefund); } } } internal static bool IsVanillaVoidSlowed(CharacterBody body) { //IL_0007: 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) //IL_0017: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < BuffCatalog.buffCount; i++) { BuffIndex val = (BuffIndex)i; if (body.HasBuff(val)) { BuffDef buffDef = BuffCatalog.GetBuffDef(val); if (Object.op_Implicit((Object)(object)buffDef) && (((Object)buffDef).name.IndexOf("Slow", StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)buffDef).name.IndexOf("Freeze", StringComparison.OrdinalIgnoreCase) >= 0)) { return true; } } } return false; } internal static void Area(CharacterBody owner, Vector3 position, float radius, float coefficient, float slowDuration) { //IL_00b0: 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_00b6: 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) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_009d: Invalid comparison between Unknown and I4 if (!NetworkServer.active || !Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)owner.teamComponent)) { return; } List<CharacterBody> list = new List<CharacterBody>(CharacterBody.readOnlyInstancesList); foreach (CharacterBody item in list) { if (!Object.op_Implicit((Object)(object)item) || !Object.op_Implicit((Object)(object)item.healthComponent) || !item.healthComponent.alive || !Object.op_Implicit((Object)(object)item.teamComponent) || item.teamComponent.teamIndex == owner.teamComponent.teamIndex || (int)item.teamComponent.teamIndex == 0) { continue; } Vector3 val = item.corePosition - position; if (!(((Vector3)(ref val)).sqrMagnitude > radius * radius)) { item.AddTimedBuff(Buffs.Slow50, slowDuration); if (coefficient > 0f) { HealthComponent healthComponent = item.healthComponent; DamageInfo val2 = new DamageInfo(); val2.attacker = ((Component)owner).gameObject; val2.damage = owner.damage * coefficient; val2.position = item.corePosition; val2.procCoefficient = 0f; val2.damageColorIndex = (DamageColorIndex)9; healthComponent.TakeDamage(val2); } } } } private void Stats(CharacterBody body, StatHookEventArgs args) { int num = Highest(body, "ClockworkMechanism"); if (num >= 0) { BodyState bodyState = State(body); bodyState.ResetStage(); int[] array = new int[4] { 12, 15, 20, 25 }; if (body.GetBuffCount(WatchHits) < array[num]) { args.damageMultAdd += 0.1f * Power(body, "ClockworkMechanism"); } } } private void Holdout(orig_Awake orig, HoldoutZoneController self) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown orig.Invoke(self); self.calcChargeRate += (CalcChargeRateDelegate)delegate(ref float rate) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 float num = 0f; foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { if (Object.op_Implicit((Object)(object)readOnlyInstances) && readOnlyInstances.isPlayerControlled && Object.op_Implicit((Object)(object)readOnlyInstances.teamComponent) && (int)readOnlyInstances.teamComponent.teamIndex == 1 && self.IsBodyInChargingRadius(readOnlyInstances)) { num += Power(readOnlyInstances, "CrystalLotus"); } } rate *= 1f + Mathf.Min(2f, num * 0.2f); }; } private void InstallSpecificHooks() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Expected O, but got Unknown //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Expected O, but got Unknown //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Expected O, but got Unknown Assembly assembly = typeof(ItemBase).Assembly; MethodInfo method = assembly.GetType("vanillaVoid.Items.ExeBlade").GetMethod("ExeBladeExtraDeath", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); hooks.Add((IDisposable)new ILHook((MethodBase)method, (Manipulator)delegate(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0049: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { (Instruction i) => i.OpCode == OpCodes.Ldfld && ((MemberReference)(FieldReference)i.Operand).Name == "victimIsElite" })) { throw new Exception("Blade elite condition not found"); } val.Emit(OpCodes.Ldarg_1); val.EmitDelegate<Func<bool, DamageReport, bool>>((Func<bool, DamageReport, bool>)((bool elite, DamageReport r) => elite || (Object.op_Implicit((Object)(object)r.victimBody) && r.victimBody.isBoss && Power(r.attackerBody, "ExeBlade") > 0f))); })); MethodInfo method2 = assembly.GetType("vanillaVoid.Misc.ClutchNetBehavior").GetMethod("ServerClutchEffects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); hooks.Add((IDisposable)new ILHook((MethodBase)method2, (Manipulator)delegate(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); int num2 = 0; while (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => IsCall(i, "RoR2.HealthComponent", "TakeDamage") })) { val.EmitDelegate<Action<HealthComponent, DamageInfo>>((Action<HealthComponent, DamageInfo>)ClutchDamage); val.Remove(); num2++; } if (num2 != 2) { throw new Exception("Expected both Clutch damage paths in Vanilla Void 1.7.2"); } })); MethodInfo method3 = assembly.GetType("vanillaVoid.Items.VoidShell").GetMethod("<OverrideBatteryChargedEnter>b__51_2", BindingFlags.Instance | BindingFlags.NonPublic); hooks.Add((IDisposable)new Hook((MethodBase)method3, (Delegate)(ReplaceDelivery)delegate(OriginalDelivery orig, VoidShell self, bool original, Charged state) { bool result = orig(self, original, state); BonusDelivery(state); return result; })); Type type = assembly.GetType("vanillaVoid.Items.SwordToken"); Type[] nestedTypes = type.GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic); foreach (Type type2 in nestedTypes) { MethodInfo method4 = type2.GetMethod("MoveNext", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method4 == null || type2.Name.IndexOf("ExeBladeDelayedExecutions", StringComparison.Ordinal) < 0) { continue; } hooks.Add((IDisposable)new ILHook((MethodBase)method4, (Manipulator)delegate(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { (Instruction i) => IsCall(i, "RoR2.HealthComponent", "TakeDamage") })) { throw new Exception("Blade burst damage call not found"); } val.EmitDelegate<Action<HealthComponent, DamageInfo>>((Action<HealthComponent, DamageInfo>)delegate(HealthComponent target, DamageInfo info) { CharacterBody body = (Object.op_Implicit((Object)(object)info.attacker) ? info.attacker.GetComponent<CharacterBody>() : null); info.damage *= 1f + 0.25f * Power(body, "ExeBlade"); target.TakeDamage(info); }); val.Remove(); })); } } private static bool IsCall(Instruction i, string type, string name) { object operand = i.Operand; MethodReference val = (MethodReference)((operand is MethodReference) ? operand : null); return val != null && ((MemberReference)((MemberReference)val).DeclaringType).FullName == type && ((MemberReference)val).Name == name; } private static void ClutchDamage(HealthComponent target, DamageInfo info) { CharacterBody body = (Object.op_Implicit((Object)(object)info.attacker) ? info.attacker.GetComponent<CharacterBody>() : null); float num = Power(body, "VoidFin"); if (NetworkServer.active && Object.op_Implicit((Object)(object)target) && num > 0f) { Vulnerable vulnerable = ((Component)target).GetComponent<Vulnerable>(); if (!Object.op_Implicit((Object)(object)vulnerable)) { vulnerable = ((Component)target).gameObject.AddComponent<Vulnerable>(); } vulnerable.Bonus = Mathf.Max((vulnerable.Until > Time.fixedTime) ? vulnerable.Bonus : 0f, Mathf.Min(1f, 0.15f * num)); vulnerable.Until = Time.fixedTime + 5f; } target.TakeDamage(info); } private static void BonusDelivery(Charged state) { //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)((EntityState)state).outer) || !Object.op_Implicit((Object)(object)((Component)((EntityState)state).outer).gameObject.GetComponent(typeof(ItemBase).Assembly.GetType("vanillaVoid.Items.VoidShellIdentifierToken"))) || Object.op_Implicit((Object)(object)((Component)((EntityState)state).outer).gameObject.GetComponent<DeliveryDone>())) { return; } ((Component)((EntityState)state).outer).gameObject.AddComponent<DeliveryDone>(); if (!Object.op_Implicit((Object)(object)Run.instance) || !Items.TryGetValue("VoidShell", out var value)) { return; } FieldInfo field = ((object)value).GetType().GetField("dropTable", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); object? value2 = field.GetValue(value); PickupDropTable val = (PickupDropTable)((value2 is PickupDropTable) ? value2 : null); if (!Object.op_Implicit((Object)(object)val)) { return; } foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (!Object.op_Implicit((Object)(object)instance.master)) { continue; } float num = Mathf.Min(300f, 50f * Power(instance.master.inventory, "VoidShell")); int num2 = (int)(num / 100f) + (Util.CheckRoll(num % 100f, instance.master) ? 1 : 0); for (int i = 0; i < num2; i++) { PickupIndex[] array = (PickupIndex[])((object)val).GetType().GetMethod("GenerateUniqueDropsPreReplacement", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).Invoke(val, new object[2] { 1, Run.instance.treasureRng }); if (array != null && array.Length > 0 && array[0] != PickupIndex.none) { PickupDropletController.CreatePickupDroplet(new UniquePickup(array[0]), ((Component)((EntityState)state).outer).transform.position + Vector3.up * 3f, Vector3.up * 10f); } } } } private static string Description(string id, int tier) { float num = Strength[tier]; return id switch { "AbyssalAdze" => "Every 10th proc-capable hit against an enemy below 50% health deals +" + 50f * num + "% total damage per stack of this quality.", "ClockworkMechanism" => "+" + 10f * num + "% damage per stack until hit " + (new int[4] { 12, 15, 20, 25 })[tier] + " times this stage (highest quality determines hit limit).", "EnhancementVials" => "5% proc-scaled chance on hit to burst for " + 250f * num + "% damage per stack, slowing enemies within 10m for 3s. +0.5% chance per consumed item, capped at +10%. Maximum 2 bursts/s; bursts cannot proc.", "ExtraterrestrialExhaust" => 15f * num + "% chance per stack for a rocket to deal " + (2f + 0.25f * num) * 100f + "% of its normal damage. No extra rockets. Mixed qualities add their power.", "CryoCanister" => "Killing slowed enemies creates a frost aura for " + Math.Min(12f, 3f + num) + "s. Deals " + 100f * num + "% damage per second per stack and slows. Kills grow radius from 6m up to 20m. No proc chains.", "VoidShell" => 50f * num + "% chance per stack for an extra reward at each Cornucopia delivery. 100% guarantees one; capped at 3 extra rewards per player/delivery.", "CorrosiveCore" => "Critical hits slow enemies for " + Math.Min(12f, 2f + num) + "s, enabling corrosion. Stacks extend duration, capped at 12s.", "CrystalLotus" => "+" + 20f * num + "% holdout charging speed per stack while inside (team cap +200%). In special boss arenas, pulse every 15s within 20m: slow enemies for " + Math.Min(10f, 2f + num) + "s.", "ExeBlade" => "Boss kills also trigger the blade. Its existing burst deals +" + 25f * num + "% damage per stack. Does not add extra death triggers beyond the item's normal behavior.", "DashQuill" => "Airborne kills restore one used air dash, up to " + 2f * num + " per stack per airtime (cap 20). Landing resets the allowance.", "VoidFin" => "Kicked enemies take +" + Math.Min(100f, 15f * num) + "% damage for 5s. Stacks raise the bonus, capped at +100%; repeated kicks refresh duration.", "LensOrrery" => 20f * num + "% proc-scaled chance per stack for non-critical hits to add an extra Orrery damage stack. Maximum 10 triggers/s. Intended for original item variant 0.", _ => "Consumed form retains its quality for restoration; no active quality bonus.", }; } } public sealed class Vulnerable : MonoBehaviour { public float Bonus; public float Until; } public sealed class DeliveryDone : MonoBehaviour { } public sealed class BodyState : MonoBehaviour { private CharacterBody body; public int HitsTaken; public int WoundedHits; public int AirRefunds; public float NextVial; public float NextOrrery; public float FrostUntil; public float FrostRadius = 6f; private float nextPulse; private float nextLotus; private int stage = -1; private int seenRefunds; private void Awake() { body = ((Component)this).GetComponent<CharacterBody>(); seenRefunds = (Object.op_Implicit((Object)(object)body) ? body.GetBuffCount(Plugin.DashRefund) : 0); } public void ResetStage() { //IL_0064: Unknown result type (might be due to invalid IL or missing references) int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.stageClearCount : (-1)); if (stage != num) { stage = num; HitsTaken = 0; if (NetworkServer.active && Object.op_Implicit((Object)(object)body)) { body.SetBuffCount(Plugin.WatchHits.buffIndex, 0); } } } private void FixedUpdate() { //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)body)) { return; } int buffCount = body.GetBuffCount(Plugin.DashRefund); if (buffCount > seenRefunds && ((NetworkBehaviour)body).hasAuthority) { Component component = ((Component)body).GetComponent(typeof(ItemBase).Assembly.GetType("vanillaVoid.Items.DashQuill+AirdashToken")); if (Object.op_Implicit((Object)(object)component)) { Type type = ((object)component).GetType(); FieldInfo field = type.GetField("dashCurrent", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo field2 = type.GetField("dashMax", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); field.SetValue(component, Math.Min((int)field2.GetValue(component), (int)field.GetValue(component) + buffCount - seenRefunds)); } } seenRefunds = buffCount; if (!NetworkServer.active) { return; } if (Object.op_Implicit((Object)(object)body.characterMotor) && body.characterMotor.isGrounded) { AirRefunds = 0; } if (Time.fixedTime < nextPulse) { return; } nextPulse = Time.fixedTime + 0.5f; ResetStage(); float num = Plugin.Power(body, "CryoCanister"); if (num > 0f && FrostUntil > Time.fixedTime) { Plugin.Area(body, body.corePosition, FrostRadius, num * 0.5f, 1f); } else { FrostRadius = 6f; } num = Plugin.Power(body, "CrystalLotus"); Scene activeScene = SceneManager.GetActiveScene(); string name = ((Scene)(ref activeScene)).name; if (!(num > 0f) || !(Time.fixedTime >= nextLotus)) { return; } switch (name) { default: if (!(name == "artifactworld")) { break; } goto case "moon2"; case "moon2": case "limbo": case "voidraid": case "meridian": nextLotus = Time.fixedTime + 15f; Plugin.Area(body, body.corePosition, 20f, 0f, Mathf.Min(10f, 2f + num)); break; } } } internal static class ScrapCompatibility { private delegate bool OriginalScrappable(ItemIndex item); private delegate bool ReplacementScrappable(OriginalScrappable orig, ItemIndex item); public static void Install(List<IDisposable> hooks) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Expected O, but got Unknown if (!Chainloader.PluginInfos.TryGetValue("com.eviegc.MarkForScrap", out var value)) { return; } MethodInfo method = ((object)value.Instance).GetType().Assembly.GetType("MarkForScrap.Utils.ItemUtils").GetMethod("IsScrappable", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); hooks.Add((IDisposable)new Hook((MethodBase)method, (Delegate)new ReplacementScrappable(IsScrappable))); string[] array = new string[2] { "MarkForScrap.InventoryScrapCounter", "MarkForScrap.MarkForScrapPlugin" }; foreach (string name in array) { MethodInfo[] methods = ((object)value.Instance).GetType().Assembly.GetType(name).GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "SyncScrapCountWithInventory" && methodInfo.Name != "Interactor_PerformInteraction") { continue; } hooks.Add((IDisposable)new ILHook((MethodBase)methodInfo, (Manipulator)delegate(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); while (val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { delegate(Instruction instruction) { object operand = instruction.Operand; MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); return val2 != null && ((MemberReference)val2).FullName == "System.Int32 RoR2.Inventory::GetItemCountPermanent(RoR2.ItemIndex)"; } })) { val.Remove(); val.EmitDelegate<Func<Inventory, ItemIndex, int>>((Func<Inventory, ItemIndex, int>)PhysicalCount); } })); } } } private static int PhysicalCount(Inventory inventory, ItemIndex index) { //IL_0002: 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) //IL_0019: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Invalid comparison between Unknown and I4 //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Invalid comparison between Unknown and I4 //IL_005e: Unknown result type (might be due to invalid IL or missing references) int num = inventory.GetItemCountPermanent(index); ItemDef itemDef = ItemCatalog.GetItemDef(index); if (!Object.op_Implicit((Object)(object)itemDef) || !IsVoid(itemDef.tier) || (int)QualityCatalog.GetQualityTier(index) != -1) { return num; } for (int i = 0; i < 4; i++) { ItemIndex itemIndexOfQuality = QualityCatalog.GetItemIndexOfQuality(index, (QualityTier)i); if (itemIndexOfQuality != index && (int)itemIndexOfQuality != -1) { num -= inventory.GetItemCountPermanent(itemIndexOfQuality); } } return Math.Max(0, num); } private static bool IsScrappable(OriginalScrappable orig, ItemIndex index) { //IL_0001: 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_0026: Unknown result type (might be due to invalid IL or missing references) ItemDef itemDef = ItemCatalog.GetItemDef(index); if (!Object.op_Implicit((Object)(object)itemDef)) { return false; } if (!IsVoid(itemDef.tier)) { return orig(index); } return itemDef.canRemove && !itemDef.ContainsTag((ItemTag)10) && !itemDef.ContainsTag((ItemTag)33); } private static bool IsVoid(ItemTier tier) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 return (int)tier == 6 || (int)tier == 7 || (int)tier == 8 || (int)tier == 9; } public static IEnumerator LoadContent(QualityContentLoadArgs args) { string[] colors = new string[3] { "White", "Green", "Red" }; try { string[] array = colors; foreach (string color in array) { string name = "Scrap" + color + "Suppressed"; AsyncOperationHandle<ItemDef> handle = Addressables.LoadAssetAsync<ItemDef>((object)("RoR2/DLC1/ScrapVoid/" + name + ".asset")); yield return handle; if ((int)handle.Status != 1 || !Object.op_Implicit((Object)(object)handle.Result)) { throw new InvalidOperationException("Could not load Void Scrap item " + name); } ItemDef item = handle.Result; string display = "Void Scrap (" + color + ")"; LanguageAPI.Add(item.nameToken, display); LanguageAPI.Add(item.pickupToken, "Scrap from Void items. Accepted by the Void donation altar."); LanguageAPI.Add(item.descriptionToken, "Scrap from Void items. The Void donation altar consumes scrap before useful items. Each scrap counts as one item, regardless of quality."); Plugin.Groups[name] = args.CreateItemQualityGroup(item); for (int j = 0; j < 4; j++) { string text = "ITEM_" + name.ToUpperInvariant() + "_" + ((object)(QualityTier)j).ToString().ToUpperInvariant(); LanguageAPI.Add(text + "_PICKUP", "{0}\nRetains the quality of the scrapped item."); LanguageAPI.Add(text + "_DESC", "{0}\n<sprite name=\"Quality\"> Retains the quality of the scrapped item. Quality does not multiply its donation value or guarantee a quality reward."); } } } finally { } } } internal static class ConsumableSupport { private sealed class Transfer { public string Source; public readonly float[] Quantities = new float[5]; public bool Temporary; } private static readonly ConditionalWeakTable<Inventory, Transfer> pending = new ConditionalWeakTable<Inventory, Transfer>(); public static void Install(List<IDisposable> hooks) { //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown Type[] types = typeof(ItemBase).Assembly.GetTypes(); foreach (Type type in types) { if (type.Name != "ClockworkMechanism" && type.Name != "EnhancementVials" && type.Name != "EmptyVials" && type.Name != "ShatteredVials") { continue; } MethodInfo[] methods = type.GetMethods(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.GetMethodBody() != null && !methodInfo.Name.StartsWith("Create") && !methodInfo.Name.StartsWith("get_") && !(methodInfo.Name == "Init") && !(methodInfo.Name == "Hooks")) { hooks.Add((IDisposable)new ILHook((MethodBase)methodInfo, new Manipulator(Patch))); } } } } private static void Patch(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); while (val.Next != null) { object operand = val.Next.Operand; MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); if (val2 == null || ((MemberReference)((MemberReference)val2).DeclaringType).FullName != "RoR2.Inventory") { val.Index += 1; continue; } string name = ((MemberReference)val2).Name; bool flag = val2.Parameters.Count > 0 && ((MemberReference)((ParameterReference)val2.Parameters[0]).ParameterType).FullName == "RoR2.ItemDef"; bool flag2 = val2.Parameters.Count > 0 && ((MemberReference)((ParameterReference)val2.Parameters[0]).ParameterType).FullName == "RoR2.ItemIndex"; if ((flag || flag2) && val2.Parameters.Count == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "System.Int32" && (name == "RemoveItemPermanent" || name == "GiveItemPermanent" || name == "GiveItem")) { val.Remove(); if (name == "RemoveItemPermanent") { if (flag) { val.EmitDelegate<Action<Inventory, ItemDef, int>>((Action<Inventory, ItemDef, int>)delegate(Inventory inv, ItemDef item, int count) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Remove(inv, item.itemIndex, count); }); } else { val.EmitDelegate<Action<Inventory, ItemIndex, int>>((Action<Inventory, ItemIndex, int>)Remove); } } else if (flag) { val.EmitDelegate<Action<Inventory, ItemDef, int>>((Action<Inventory, ItemDef, int>)delegate(Inventory inv, ItemDef item, int count) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) Give(inv, item.itemIndex, count); }); } else { val.EmitDelegate<Action<Inventory, ItemIndex, int>>((Action<Inventory, ItemIndex, int>)Give); } } else if (flag2 && name == "GetTempItemDecayValue") { val.Remove(); val.EmitDelegate<Func<Inventory, ItemIndex, float>>((Func<Inventory, ItemIndex, float>)TempValue); } else if (flag2 && name == "RemoveItemTemp" && val2.Parameters.Count == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "System.Single") { val.Remove(); val.EmitDelegate<Action<Inventory, ItemIndex, float>>((Action<Inventory, ItemIndex, float>)RemoveTemp); } else if (flag2 && name == "GiveItemTemp" && val2.Parameters.Count == 2 && ((MemberReference)((ParameterReference)val2.Parameters[1]).ParameterType).FullName == "System.Single") { val.Remove(); val.EmitDelegate<Action<Inventory, ItemIndex, float>>((Action<Inventory, ItemIndex, float>)GiveTemp); } else { val.Index += 1; } } } private static string Group(ItemIndex index, out ItemQualityGroup group) { //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00c4: Unknown result type (might be due to invalid IL or missing references) foreach (KeyValuePair<string, ItemQualityGroup> group2 in Plugin.Groups) { if (group2.Key != "ClockworkMechanism" && group2.Key != "ConsumedClockworkMechanism" && group2.Key != "EnhancementVials" && group2.Key != "EmptyVials" && group2.Key != "ShatteredVials") { continue; } if (group2.Value.BaseItemIndex == index) { group = group2.Value; return group2.Key; } for (int i = 0; i < 4; i++) { if (group2.Value.GetItemIndex((QualityTier)i) == index) { group = group2.Value; return group2.Key; } } } group = null; return null; } private static bool IsPartner(string source, string target) { return (source == "ClockworkMechanism" && target == "ConsumedClockworkMechanism") || (source == "ConsumedClockworkMechanism" && target == "ClockworkMechanism") || (source == "EnhancementVials" && (target == "EmptyVials" || target == "ShatteredVials")) || (target == "EnhancementVials" && (source == "EmptyVials" || source == "ShatteredVials")); } private static void Remove(Inventory inv, ItemIndex item, int count) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_008a: 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_0066: 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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) pending.Remove(inv); ItemQualityGroup group; string text = Group(item, out group); if (text == null || count <= 0) { inv.RemoveItemPermanent(item, count); return; } int[] array = new int[5]; int num = 0; for (int i = 1; i < 5; i++) { ItemIndex itemIndex = group.GetItemIndex((QualityTier)(i - 1)); array[i] = ((item == group.BaseItemIndex || item == itemIndex) ? inv.GetItemCountPermanent(itemIndex) : 0); num += array[i]; } array[0] = ((item == group.BaseItemIndex) ? Math.Max(0, inv.GetItemCountPermanent(item) - num) : 0); Transfer transfer = new Transfer(); transfer.Source = text; Transfer transfer2 = transfer; for (int i = 0; i < 5; i++) { if (count <= 0) { break; } int num2 = Math.Min(count, array[i]); if (num2 > 0) { inv.RemoveItemPermanent(group.GetItemIndex((QualityTier)(i - 1)), num2); transfer2.Quantities[i] = num2; count -= num2; } } pending.Add(inv, transfer2); } private static void Give(Inventory inv, ItemIndex item, int count) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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) ItemQualityGroup group; string target = Group(item, out group); if (pending.TryGetValue(inv, out var value) && !value.Temporary && IsPartner(value.Source, target)) { pending.Remove(inv); for (int i = 0; i < 5; i++) { if (count <= 0) { break; } int num = Math.Min(count, (int)value.Quantities[i]); if (num > 0) { inv.GiveItemPermanent(group.GetItemIndex((QualityTier)(i - 1)), num); count -= num; } } } else { pending.Remove(inv); } if (count > 0) { inv.GiveItemPermanent(item, count); } } private static float TempValue(Inventory inv, ItemIndex item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000d: 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_0036: Unknown result type (might be due to invalid IL or missing references) if (Group(item, out var group) == null || item != group.BaseItemIndex) { return inv.GetTempItemDecayValue(item); } float num = 0f; for (int i = -1; i < 4; i++) { num += inv.GetTempItemDecayValue(group.GetItemIndex((QualityTier)i)); } return num; } private static void RemoveTemp(Inventory inv, ItemIndex item, float amount) { //IL_000d: 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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_009a: Unknown result type (might be due to invalid IL or missing references) pending.Remove(inv); ItemQualityGroup group; string text = Group(item, out group); if (text == null) { inv.RemoveItemTemp(item, amount); return; } Transfer transfer = new Transfer(); transfer.Source = text; transfer.Temporary = true; Transfer transfer2 = transfer; for (int i = 0; i < 5; i++) { if (!(amount > 0f)) { break; } ItemIndex itemIndex = group.GetItemIndex((QualityTier)(i - 1)); if (item == group.BaseItemIndex || item == itemIndex) { float num = Math.Min(amount, inv.GetTempItemDecayValue(itemIndex)); if (num > 0f) { inv.RemoveItemTemp(itemIndex, num); transfer2.Quantities[i] = num; amount -= num; } } } pending.Add(inv, transfer2); } private static void GiveTemp(Inventory inv, ItemIndex item, float amount) { //IL_0001: 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_0074: Unknown result type (might be due to invalid IL or missing references) ItemQualityGroup group; string target = Group(item, out group); if (pending.TryGetValue(inv, out var value) && value.Temporary && IsPartner(value.Source, target)) { pending.Remove(inv); for (int i = 0; i < 5; i++) { if (!(amount > 0f)) { break; } float num = Math.Min(amount, value.Quantities[i]); if (num > 0f) { inv.GiveItemTemp(group.GetItemIndex((QualityTier)(i - 1)), num); amount -= num; } } } else { pending.Remove(inv); } if (amount > 0f) { inv.GiveItemTemp(item, amount); } } }
BepInEx/plugins/VanillaPlusPlus/Olligame.VoidDonation.dll
Decompiled a day agousing System; using System.Collections; using System.Collections.Generic; using System.Reflection; using System.Runtime.CompilerServices; using BazaarIsMyHaven; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using Mono.Cecil; using Mono.Cecil.Cil; using MonoMod.Cil; using MonoMod.RuntimeDetour; using On.RoR2; using PerClientSync; using RoR2; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.Networking; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: AssemblyVersion("0.0.0.0")] namespace OlligameDonations; public sealed class DonationLedger { public readonly Dictionary<string, int> RunCounts = new Dictionary<string, int>(); private readonly HashSet<string> visited = new HashSet<string>(); public bool CanDonate(string key) { return !visited.Contains(key); } public int Price(string key, int initial) { RunCounts.TryGetValue(key, out var value); return (int)Math.Min(2147483647L, initial + 2L * (long)Math.Max(0, value)); } public void Record(string key) { RunCounts.TryGetValue(key, out var value); RunCounts[key] = value + 1; visited.Add(key); } public void NewVisit() { visited.Clear(); } public void NewRun() { visited.Clear(); RunCounts.Clear(); } public static List<int> PlanPayment(IDictionary<int, int> counts, Random random, int price = 2) { Dictionary<int, int> dictionary = new Dictionary<int, int>(counts); List<int> list = new List<int>(); long num = 0L; foreach (int value in counts.Values) { num += Math.Max(0, value); } if (price < 1 || num < price) { return null; } for (int i = 0; i < price; i++) { int num2 = 0; foreach (int value2 in dictionary.Values) { num2 = checked(num2 + Math.Max(0, value2)); } if (num2 == 0) { return null; } int num3 = random.Next(num2); int num4 = -1; foreach (KeyValuePair<int, int> item in dictionary) { if (num3 < item.Value) { num4 = item.Key; break; } num3 -= Math.Max(0, item.Value); } list.Add(num4); dictionary[num4]--; } return list; } public static List<int> PlanScrapFirst(IDictionary<int, int> counts, ISet<int> scrap, Random random, int price = 2) { Dictionary<int, int> dictionary = new Dictionary<int, int>(counts); List<int> list = new List<int>(); long num = 0L; foreach (int value in counts.Values) { num += Math.Max(0, value); } if (price < 1 || num < price) { return null; } foreach (KeyValuePair<int, int> count in counts) { if (scrap.Contains(count.Key)) { int num2 = Math.Min(price - list.Count, Math.Max(0, count.Value)); for (int i = 0; i < num2; i++) { list.Add(count.Key); } dictionary[count.Key] -= num2; if (list.Count == price) { return list; } } } List<int> list2 = PlanPayment(dictionary, random, price - list.Count); if (list2 == null) { return null; } list.AddRange(list2); return list; } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Olligame.SeparateVoidDonation", "Separate Void Donation", "1.8.0")] [BepInDependency("Def.BazaarIsMyHaven", "5.3.0")] public sealed class VoidDonation : BaseUnityPlugin { private readonly DonationLedger ledger = new DonationLedger(); private readonly DonationLedger yellowLedger = new DonationLedger(); private YellowDonationPrices yellowPricing; private DonationQuality qualityRewards; private BazaarPaymentFix paymentFix; private readonly Random random = new Random(); private GameObject altar; private GameObject prefab; private bool attempted; private float nextCheck; private ConfigEntry<bool> customPlacement; private ConfigEntry<Vector3> yellowPosition; private ConfigEntry<Vector3> voidPosition; private ILHook placementHook; private void Awake() { //IL_0072: 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_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Expected O, but got Unknown //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Expected O, but got Unknown paymentFix = new BazaarPaymentFix(); VoidScrapSupport.Hook(); VoidAltarText.Hook(); yellowPricing = new YellowDonationPrices(yellowLedger); qualityRewards = new DonationQuality(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Logger); customPlacement = ((BaseUnityPlugin)this).Config.Bind<bool>("Placement", "UseSavedPositions", false, "Use positions saved with Page Down in the Bazaar. Applies next visit."); yellowPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Placement", "YellowPosition", Vector3.zero, "World position for the yellow donation altar."); voidPosition = ((BaseUnityPlugin)this).Config.Bind<Vector3>("Placement", "VoidPosition", Vector3.zero, "World position for the Void donation altar."); placementHook = new ILHook((MethodBase)typeof(BazaarDonate).GetMethod("SpawnDonateAltar", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchYellowPosition)); PurchaseInteraction.OnInteractionBegin += new hook_OnInteractionBegin(Interact); PurchaseInteraction.GetInteractability += new hook_GetInteractability(Interactability); Run.onRunStartGlobal += RunStarted; Run.onRunDestroyGlobal += RunEnded; SceneManager.sceneLoaded += SceneLoaded; ModCompatibilityProperSave.Register("Olligame.VoidDonations", (Func<object>)Save, (Action<object>)Load); ModCompatibilityProperSave.Register("Olligame.YellowDonationPrices", (Func<object>)(() => new Dictionary<string, int>(yellowLedger.RunCounts)), (Action<object>)delegate(object data) { LoadCounts(yellowLedger, data); }); ((BaseUnityPlugin)this).Logger.LogInfo((object)"Donation prices: yellow starts at 3, Void at 2; +2 per personal use; one per visit, no run cap."); } private void PatchYellowPosition(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { delegate(Instruction instruction) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) object operand = instruction.Operand; MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); return instruction.OpCode == OpCodes.Newobj && val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "UnityEngine.Vector3" && val2.Parameters.Count == 3; } })) { throw new InvalidOperationException("Could not find yellow altar spawn position; this add-on requires BazaarIsMyHaven 5.3.0."); } val.EmitDelegate<Func<Vector3, Vector3>>((Func<Vector3, Vector3>)((Vector3 original) => customPlacement.Value ? yellowPosition.Value : original)); } private void SavePlacementAtHost() { //IL_0032: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015c: 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_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: 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_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_0179: 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) if (!Input.GetKeyDown((KeyCode)281)) { return; } if (!NetworkServer.active) { Chat.AddMessage("Only the host can place the donation altars."); return; } Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "bazaar") { Chat.AddMessage("Enter the Bazaar before placing the donation altars."); return; } CharacterBody val = null; foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList) { if (Object.op_Implicit((Object)(object)readOnlyLocalUsers.cachedBody)) { val = readOnlyLocalUsers.cachedBody; break; } } if (!Object.op_Implicit((Object)(object)val)) { Chat.AddMessage("Could not find your character. Spawn in, then press Page Down again."); ((BaseUnityPlugin)this).Logger.LogWarning((object)"Page Down received, but no local character was available."); return; } Vector3 val2 = val.footPosition + Vector3.up * 2f; Vector3 down = Vector3.down; LayerIndex world = LayerIndex.world; RaycastHit val3 = default(RaycastHit); if (!Physics.Raycast(val2, down, ref val3, 8f, LayerMask.op_Implicit(((LayerIndex)(ref world)).mask), (QueryTriggerInteraction)1)) { Chat.AddMessage("Stand near the floor, then press Page Down again."); return; } Vector3 val4 = Vector3.ProjectOnPlane(((Component)val).transform.right, Vector3.up); Vector3 val5 = ((Vector3)(ref val4)).normalized; if (((Vector3)(ref val5)).sqrMagnitude < 0.5f) { val5 = Vector3.right; } yellowPosition.Value = ((RaycastHit)(ref val3)).point - val5 * 3.5f; voidPosition.Value = ((RaycastHit)(ref val3)).point + val5 * 3.5f; customPlacement.Value = true; ((BaseUnityPlugin)this).Config.Save(); Chat.AddMessage("Both altar positions saved, 7 metres apart. Re-enter the Bazaar to apply (console: next_stage bazaar)."); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Concat("Saved altar positions: yellow=", yellowPosition.Value, ", void=", voidPosition.Value)); } private void RunStarted(Run run) { ledger.NewRun(); yellowLedger.NewRun(); attempted = false; } private void RunEnded(Run run) { ledger.NewRun(); yellowLedger.NewRun(); altar = null; attempted = false; } private void SceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 if ((int)mode == 0) { ledger.NewVisit(); yellowLedger.NewVisit(); altar = null; attempted = false; nextCheck = Time.unscaledTime + 1f; } } private object Save() { return new Dictionary<string, int>(ledger.RunCounts); } private void Load(object data) { LoadCounts(ledger, data); } private static void LoadCounts(DonationLedger target, object data) { if (!(data is Dictionary<string, int> dictionary)) { return; } target.RunCounts.Clear(); foreach (KeyValuePair<string, int> item in dictionary) { target.RunCounts[item.Key] = Math.Max(0, item.Value); } } public static string Key(PlayerCharacterMasterController player) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) NetworkUserId id = player.networkUser.id; return $"{id.value}/{id.strValue}/{id.subId}"; } private bool Allowed(PlayerCharacterMasterController player) { return Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.networkUser) && ledger.CanDonate(Key(player)); } private static bool IsVoid(ItemTier tier) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 return (int)tier == 6 || (int)tier == 7 || (int)tier == 8 || (int)tier == 9; } private unsafe static Dictionary<int, int> Eligible(Inventory inventory) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected I4, but got Unknown Dictionary<int, int> dictionary = new Dictionary<int, int>(); GenericStaticEnumerable<ItemIndex, AllItemsEnumerator> allItems = ItemCatalog.allItems; AllItemsEnumerator enumerator = allItems.GetEnumerator(); try { while (((AllItemsEnumerator)(ref enumerator)).MoveNext()) { ItemIndex current = ((AllItemsEnumerator)(ref enumerator)).Current; ItemDef itemDef = ItemCatalog.GetItemDef(current); if (!((Object)(object)itemDef == (Object)null) && (VoidScrapSupport.IsScrap(current) || (IsVoid(itemDef.tier) && itemDef.canRemove)) && !inventory.IsItemDisabled(current)) { int num = DonationQuality.PermanentCount(inventory, current); if (num > 0) { dictionary[(int)current] = num; } } } } finally { ((IDisposable)(*(AllItemsEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose(); } return dictionary; } private void Update() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: 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_017e: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0249: 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_025e: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) SavePlacementAtHost(); if (!NetworkServer.active || !Object.op_Implicit((Object)(object)Run.instance) || attempted || Object.op_Implicit((Object)(object)altar) || Time.unscaledTime < nextCheck) { return; } nextCheck = Time.unscaledTime + 1f; Scene activeScene = SceneManager.GetActiveScene(); if (((Scene)(ref activeScene)).name != "bazaar") { return; } PurchaseInteraction val = null; PurchaseInteraction[] array = Object.FindObjectsOfType<PurchaseInteraction>(); foreach (PurchaseInteraction val2 in array) { if (val2.displayNameToken == "NEWT_STATUE_NAME") { val = val2; break; } } if (!Object.op_Implicit((Object)(object)val)) { return; } DonationPriceView.Attach(((Component)val).gameObject, yellowLedger, isVoid: false); DonationPriceView.AttachSigns(((Component)val).gameObject, yellowLedger, isVoid: false); attempted = true; try { if (!Object.op_Implicit((Object)(object)prefab)) { prefab = Addressables.LoadAssetAsync<GameObject>((object)"RoR2/DLC1/DeepVoidPortalBattery/DeepVoidPortalBattery.prefab").WaitForCompletion(); } Vector3 val3 = (customPlacement.Value ? voidPosition.Value : (((Component)val).transform.position + ((Component)val).transform.right * 7f)); altar = Object.Instantiate<GameObject>(prefab, val3, ((Component)val).transform.rotation); PurchaseInteraction val2 = altar.GetComponent<PurchaseInteraction>(); val2.Networkcost = 0; val2.NetworkcostType = (CostTypeIndex)0; val2.NetworkdisplayNameToken = "<color=#FF7ACD>Void Donation Altar (scrap first)</color>"; val2.NetworkcontextToken = "<color=#FF7ACD>Donate Void scrap/items (scrap first)</color>"; val2.Networkavailable = true; altar.AddComponent<InstancedPurchase>().original.available = true; DonationPriceView.Attach(altar, ledger, isVoid: true); DonationRewardDisplay.Apply(altar, (Func<PlayerCharacterMasterController, Dictionary<PickupIndex, int>>)Preview); NetworkServer.Spawn(altar); VoidSignalBeam.Remove(altar); PriceSigns.Apply(altar, altar.transform.TransformPoint(new Vector3(1.5534f, 1.1769f, -0.1835f)), altar.transform.rotation * Quaternion.Euler(0f, 270f, 0f), 2, (CostTypeIndex)4); VoidAltarText.MarkPriceSign(altar); DonationPriceView.AttachSigns(altar, ledger, isVoid: true); foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (Object.op_Implicit((Object)(object)instance) && Object.op_Implicit((Object)(object)instance.networkUser) && !Allowed(instance)) { DisableFor(instance); } } ((BaseUnityPlugin)this).Logger.LogInfo((object)"Spawned separate Void altar beside the yellow altar."); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)ex); if (Object.op_Implicit((Object)(object)altar)) { NetworkServer.Destroy(altar); } altar = null; } } private Dictionary<PickupIndex, int> Reward() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)Run.instance)) { return null; } List<PickupIndex> list = new List<PickupIndex>(); list.AddRange(Run.instance.availableVoidTier1DropList); list.AddRange(Run.instance.availableVoidTier2DropList); list.AddRange(Run.instance.availableVoidTier3DropList); list.AddRange(Run.instance.availableVoidBossDropList); list.RemoveAll(delegate(PickupIndex pickup) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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) PickupDef pickupDef = PickupCatalog.GetPickupDef(pickup); ItemDef val = ((pickupDef == null) ? null : ItemCatalog.GetItemDef(pickupDef.itemIndex)); return (Object)(object)val == (Object)null || !IsVoid(val.tier); }); if (list.Count == 0) { return null; } Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>(); dictionary.Add(list[random.Next(list.Count)], 1); return dictionary; } private Dictionary<PickupIndex, int> Preview(PlayerCharacterMasterController player) { return Allowed(player) ? Reward() : null; } private void DisableFor(PlayerCharacterMasterController player) { InstancedPurchase component = altar.GetComponent<InstancedPurchase>(); component.GetOrCreate(player).available = false; InstancedPurchases.UpdatePlayer(altar, player); PriceSigns.HideFor(altar, player); } private Interactability Interactability(orig_GetInteractability orig, PurchaseInteraction self, Interactor activator) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !Object.op_Implicit((Object)(object)altar) || (Object)(object)((Component)self).gameObject != (Object)(object)altar) { return orig.Invoke(self, activator); } CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null); PlayerCharacterMasterController player = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null); if (!Allowed(player)) { return (Interactability)0; } if (!Object.op_Implicit((Object)(object)val.inventory)) { return (Interactability)1; } int num = ledger.Price(Key(player), 2); long num2 = 0L; foreach (int value in Eligible(val.inventory).Values) { num2 += value; if (num2 >= num) { return (Interactability)2; } } return (Interactability)1; } private void Interact(orig_OnInteractionBegin orig, PurchaseInteraction self, Interactor activator) { //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)altar) || (Object)(object)((Component)self).gameObject != (Object)(object)altar) { orig.Invoke(self, activator); } else { if (!NetworkServer.active) { return; } CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null); PlayerCharacterMasterController val2 = ((Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.inventory) || !Allowed(val2)) { return; } Dictionary<int, int> dictionary = Eligible(val.inventory); HashSet<int> hashSet = new HashSet<int>(); foreach (int key in dictionary.Keys) { if (VoidScrapSupport.IsScrap((ItemIndex)key)) { hashSet.Add(key); } } List<int> list = DonationLedger.PlanScrapFirst(dictionary, hashSet, random, ledger.Price(Key(val2), 2)); if (list == null) { return; } Dictionary<PickupIndex, int> dictionary2 = Reward(); if (dictionary2 == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)"No enabled Void rewards; no items were taken."); return; } qualityRewards.Apply(dictionary2); foreach (int item in list) { val.inventory.RemoveItemPermanent((ItemIndex)item, 1); } ledger.Record(Key(val2)); Helper.GivePickups(val, dictionary2, (Vector3?)(altar.transform.position + Vector3.up * 6f), false); DisableFor(val2); DonationRewardDisplay component = altar.GetComponent<DonationRewardDisplay>(); if (Object.op_Implicit((Object)(object)component)) { component.ShowNextReward(val2); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("Void donation completed; player's run count = " + ledger.RunCounts[Key(val2)])); } } private void OnDestroy() { //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown if (yellowPricing != null) { yellowPricing.Dispose(); } if (qualityRewards != null) { qualityRewards.Dispose(); } if (paymentFix != null) { paymentFix.Dispose(); } VoidAltarText.Unhook(); VoidScrapSupport.Unhook(); if (placementHook != null) { placementHook.Dispose(); } PurchaseInteraction.OnInteractionBegin -= new hook_OnInteractionBegin(Interact); PurchaseInteraction.GetInteractability -= new hook_GetInteractability(Interactability); Run.onRunStartGlobal -= RunStarted; Run.onRunDestroyGlobal -= RunEnded; SceneManager.sceneLoaded -= SceneLoaded; } } public static class VoidScrapSupport { public static bool IsScrap(ItemIndex item) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ItemDef itemDef = ItemCatalog.GetItemDef(item); if ((Object)(object)itemDef == (Object)null) { return false; } string[] array = new string[3] { "ScrapWhiteSuppressed", "ScrapGreenSuppressed", "ScrapRedSuppressed" }; foreach (string text in array) { if (((Object)itemDef).name == text || ((Object)itemDef).name == text + "Uncommon" || ((Object)itemDef).name == text + "Rare" || ((Object)itemDef).name == text + "Epic" || ((Object)itemDef).name == text + "Legendary") { return true; } } return false; } private static bool IsVoid(ItemTier tier) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Invalid comparison between Unknown and I4 //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 return (int)tier == 6 || (int)tier == 7 || (int)tier == 8 || (int)tier == 9; } public static void Hook() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown PickupPickerController.GetGeneratedOptionsFromInteractor += new hook_GetGeneratedOptionsFromInteractor(Options); PickupCatalog.FindScrapIndexForItemTier += new hook_FindScrapIndexForItemTier(ScrapForTier); } public static void Unhook() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown PickupPickerController.GetGeneratedOptionsFromInteractor -= new hook_GetGeneratedOptionsFromInteractor(Options); PickupCatalog.FindScrapIndexForItemTier -= new hook_FindScrapIndexForItemTier(ScrapForTier); } private static PickupIndex ScrapForTier(orig_FindScrapIndexForItemTier orig, ItemTier tier) { //IL_0001: 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_004d: 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_0011: Invalid comparison between Unknown and I4 //IL_0050: 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_0015: Invalid comparison between Unknown and I4 //IL_002e: 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) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Invalid comparison between Unknown and I4 //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if (IsVoid(tier)) { string text = (((int)tier == 6) ? "ScrapWhiteSuppressed" : (((int)tier == 7) ? "ScrapGreenSuppressed" : "ScrapRedSuppressed")); ItemIndex val = ItemCatalog.FindItemIndex(text); if ((int)val != -1) { return PickupCatalog.FindPickupIndex(val); } } return orig.Invoke(tier); } private unsafe static List<Option> Options(orig_GetGeneratedOptionsFromInteractor orig, PickupPickerController self, Interactor activator) { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Invalid comparison between Unknown and I4 //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Invalid comparison between Unknown and I4 //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Invalid comparison between Unknown and I4 //IL_00e2: 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_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_0154: 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) List<Option> list = orig.Invoke(self, activator); if (!NetworkServer.active || !Object.op_Implicit((Object)(object)((Component)self).GetComponent<ScrapperController>()) || !Object.op_Implicit((Object)(object)activator)) { return list; } CharacterBody body = ((Component)activator).GetComponent<CharacterBody>(); if (!Object.op_Implicit((Object)(object)body) || !Object.op_Implicit((Object)(object)body.inventory) || body.inventory.inventoryDisabled) { return list; } if ((int)ItemCatalog.FindItemIndex("ScrapWhiteSuppressed") == -1 || (int)ItemCatalog.FindItemIndex("ScrapGreenSuppressed") == -1 || (int)ItemCatalog.FindItemIndex("ScrapRedSuppressed") == -1) { return list; } list.RemoveAll(delegate(Option option) { //IL_0008: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) PickupDef pickupDef = PickupCatalog.GetPickupDef(option.pickup.pickupIndex); ItemDef val = ((pickupDef == null) ? null : ItemCatalog.GetItemDef(pickupDef.itemIndex)); return Object.op_Implicit((Object)(object)val) && IsVoid(val.tier) && !((UniquePickup)(ref option.pickup)).isTempItem && !option.pickup.isRental && DonationQuality.PermanentCount(body.inventory, val.itemIndex) < 1; }); GenericStaticEnumerable<ItemIndex, AllItemsEnumerator> allItems = ItemCatalog.allItems; AllItemsEnumerator enumerator = allItems.GetEnumerator(); try { while (((AllItemsEnumerator)(ref enumerator)).MoveNext()) { ItemIndex current = ((AllItemsEnumerator)(ref enumerator)).Current; ItemDef itemDef = ItemCatalog.GetItemDef(current); if (Object.op_Implicit((Object)(object)itemDef) && IsVoid(itemDef.tier) && itemDef.canRemove && !itemDef.ContainsTag((ItemTag)10) && !itemDef.ContainsTag((ItemTag)33) && !body.inventory.IsItemDisabled(current) && DonationQuality.PermanentCount(body.inventory, current) >= 1) { PickupIndex pickup = PickupCatalog.FindPickupIndex(current); if (!(pickup == PickupIndex.none) && !list.Exists((Option option) => option.pickup.pickupIndex == pickup && !((UniquePickup)(ref option.pickup)).isTempItem && !option.pickup.isRental)) { list.Add(new Option { available = true, pickup = new UniquePickup(pickup) }); } } } } finally { ((IDisposable)(*(AllItemsEnumerator*)(&enumerator))/*cast due to .constrained prefix*/).Dispose(); } return list; } } public sealed class VoidPriceMarker : MonoBehaviour { } public static class VoidAltarText { private const string Marker = "OLLIGAME_VOID_PRICE_SIGN"; public static void Hook() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown PurchaseInteraction.UpdateHologramContent += new hook_UpdateHologramContent(UpdateContent); CostHologramContent.FixedUpdate += new hook_FixedUpdate(UpdateText); } public static void Unhook() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown PurchaseInteraction.UpdateHologramContent -= new hook_UpdateHologramContent(UpdateContent); CostHologramContent.FixedUpdate -= new hook_FixedUpdate(UpdateText); } public static void MarkPriceSign(GameObject altar) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Expected O, but got Unknown //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown FieldInfo field = typeof(PriceSigns).GetField("signs", BindingFlags.Instance | BindingFlags.NonPublic); PriceSigns[] array = Object.FindObjectsOfType<PriceSigns>(); foreach (PriceSigns obj in array) { IEnumerable enumerable = (IEnumerable)field.GetValue(obj); foreach (object item in enumerable) { Type type = item.GetType(); if (!((Object)(GameObject)type.GetField("terminal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item) != (Object)(object)altar)) { NetworkIdentity val = (NetworkIdentity)type.GetField("seer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item); ((Component)val).GetComponent<PurchaseInteraction>().NetworkdisplayNameToken = "OLLIGAME_VOID_PRICE_SIGN"; } } } } private static void UpdateContent(orig_UpdateHologramContent orig, PurchaseInteraction self, GameObject content, Transform viewer) { orig.Invoke(self, content, viewer); if (self.displayNameToken == "OLLIGAME_VOID_PRICE_SIGN" && Object.op_Implicit((Object)(object)content) && !Object.op_Implicit((Object)(object)content.GetComponent<VoidPriceMarker>())) { content.AddComponent<VoidPriceMarker>(); } } private static void UpdateText(orig_FixedUpdate orig, CostHologramContent self) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self); if (Object.op_Implicit((Object)(object)((Component)self).GetComponent<VoidPriceMarker>()) && Object.op_Implicit((Object)(object)self.targetTextMesh)) { ((TMP_Text)self.targetTextMesh).text = "<color=#FF7ACD>" + self.displayValue + " Void scrap/items</color>"; ((Graphic)self.targetTextMesh).color = Color.white; } } } public sealed class YellowDonationPrices : IDisposable { private delegate void OriginalInteraction(BazaarDonate donor, orig_OnInteractionBegin original, PurchaseInteraction purchase, Interactor activator); private delegate void ReplacementInteraction(OriginalInteraction original, BazaarDonate donor, orig_OnInteractionBegin chained, PurchaseInteraction purchase, Interactor activator); private delegate bool OriginalLimit(BazaarDonate donor, PlayerCharacterMasterController player); private delegate bool ReplacementLimit(OriginalLimit original, BazaarDonate donor, PlayerCharacterMasterController player); private readonly DonationLedger ledger; private readonly Hook interactionHook; private readonly Hook limitHook; public YellowDonationPrices(DonationLedger counts) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown ledger = counts; interactionHook = new Hook((MethodBase)typeof(BazaarDonate).GetMethod("PurchaseInteraction_OnInteractionBegin", BindingFlags.Instance | BindingFlags.NonPublic), (Delegate)new ReplacementInteraction(Interact)); limitHook = new Hook((MethodBase)typeof(BazaarDonate).GetMethod("CanGetReward", BindingFlags.Instance | BindingFlags.NonPublic), (Delegate)new ReplacementLimit(CanGetReward)); PurchaseInteraction.CanBeAffordedByInteractor += new hook_CanBeAffordedByInteractor(Affordable); } private static bool IsYellow(PurchaseInteraction self) { return NetworkServer.active && Object.op_Implicit((Object)(object)self) && self.displayNameToken == "NEWT_STATUE_NAME"; } private static PlayerCharacterMasterController Player(Interactor activator) { CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null); return (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.master)) ? val.master.playerCharacterMasterController : null; } private bool CanGetReward(OriginalLimit original, BazaarDonate donor, PlayerCharacterMasterController player) { return Object.op_Implicit((Object)(object)player) && Main.instance.GetPlayerStruct(player).RewardCount < 1; } private bool Affordable(orig_CanBeAffordedByInteractor original, PurchaseInteraction self, Interactor activator) { PlayerCharacterMasterController val = (IsYellow(self) ? Player(activator) : null); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.networkUser)) { return original.Invoke(self, activator); } int cost = self.cost; try { self.cost = ledger.Price(VoidDonation.Key(val), 3); return original.Invoke(self, activator); } finally { self.cost = cost; } } private void Interact(OriginalInteraction original, BazaarDonate donor, orig_OnInteractionBegin chained, PurchaseInteraction self, Interactor activator) { PlayerCharacterMasterController val = (IsYellow(self) ? Player(activator) : null); if (!Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val.networkUser)) { original(donor, chained, self, activator); return; } PlayerStruct playerStruct = Main.instance.GetPlayerStruct(val); int rewardCount = playerStruct.RewardCount; int cost = self.cost; try { self.cost = ledger.Price(VoidDonation.Key(val), 3); original(donor, chained, self, activator); if (playerStruct.RewardCount > rewardCount) { ledger.Record(VoidDonation.Key(val)); } } finally { self.cost = cost; } } public void Dispose() { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown PurchaseInteraction.CanBeAffordedByInteractor -= new hook_CanBeAffordedByInteractor(Affordable); interactionHook.Dispose(); limitHook.Dispose(); } } public sealed class DonationPriceView : InstancedPurchaseView { public DonationLedger Ledger; public bool VoidAltar; private int realCost; private string realContext; private bool usedBase; private float nextRefresh; public override uint PrivateBits => 26u; protected override void Apply(NetworkConnection connection) { realCost = ((ClientView<PurchaseInteraction>)this).Component.cost; realContext = ((ClientView<PurchaseInteraction>)this).Component.contextToken; usedBase = (Object)(object)((Component)this).GetComponent<InstancedPurchase>() != (Object)null; if (usedBase) { ((InstancedPurchaseView)this).Apply(connection); } ApplyPersonal(PerClient.GetPlayer(connection)); } protected override void Restore() { if (usedBase) { ((InstancedPurchaseView)this).Restore(); } ((ClientView<PurchaseInteraction>)this).Component.cost = realCost; ((ClientView<PurchaseInteraction>)this).Component.contextToken = realContext; } private void ApplyPersonal(PlayerCharacterMasterController player) { if (Ledger != null && Object.op_Implicit((Object)(object)player) && Object.op_Implicit((Object)(object)player.networkUser)) { int num = Ledger.Price(VoidDonation.Key(player), VoidAltar ? 2 : 3); ((ClientView<PurchaseInteraction>)this).Component.cost = num; ((ClientView<PurchaseInteraction>)this).Component.contextToken = (VoidAltar ? ("<color=#FF7ACD>Donate " + num + " Void scrap/items (scrap first)</color>") : ("Donate " + num + " yellow items for 1 yellow item")); } } private void LateUpdate() { if (!NetworkServer.active || Ledger == null) { return; } foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList) { if (Object.op_Implicit((Object)(object)readOnlyLocalUsers.cachedMasterController)) { ApplyPersonal(readOnlyLocalUsers.cachedMasterController); break; } } if (Time.unscaledTime >= nextRefresh) { nextRefresh = Time.unscaledTime + 0.5f; ((ClientView)this).SetDirtyForAll(((ClientView)this).PrivateBits); } } public static void Attach(GameObject target, DonationLedger ledger, bool isVoid) { if (!Object.op_Implicit((Object)(object)target.GetComponent<DonationPriceView>())) { InstancedPurchaseView component = target.GetComponent<InstancedPurchaseView>(); if (Object.op_Implicit((Object)(object)component)) { ((Behaviour)component).enabled = false; } DonationPriceView donationPriceView = target.AddComponent<DonationPriceView>(); donationPriceView.Ledger = ledger; donationPriceView.VoidAltar = isVoid; InstancedPurchase component2 = target.GetComponent<InstancedPurchase>(); if (Object.op_Implicit((Object)(object)component2)) { typeof(InstancedPurchase).GetField("purchaseView", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(component2, donationPriceView); } ((ClientView)donationPriceView).SetDirtyForAll(((ClientView)donationPriceView).PrivateBits); } } public static void AttachSigns(GameObject altar, DonationLedger ledger, bool isVoid) { //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown FieldInfo field = typeof(PriceSigns).GetField("signs", BindingFlags.Instance | BindingFlags.NonPublic); PriceSigns[] array = Object.FindObjectsOfType<PriceSigns>(); foreach (PriceSigns obj in array) { foreach (object item in (IEnumerable)field.GetValue(obj)) { Type type = item.GetType(); if (!((Object)(GameObject)type.GetField("terminal", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item) != (Object)(object)altar)) { NetworkIdentity val = (NetworkIdentity)type.GetField("seer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).GetValue(item); Attach(((Component)val).gameObject, ledger, isVoid); } } } } } public static class DonationQualityRoll { public static int Select(double chancePercent, double chanceRoll, double tierRoll) { if (double.IsNaN(chancePercent) || chanceRoll >= Math.Max(0.0, Math.Min(100.0, chancePercent)) / 100.0) { return -1; } return (!(tierRoll < 0.7)) ? ((tierRoll < 0.9) ? 1 : ((tierRoll < 0.98) ? 2 : 3)) : 0; } } public sealed class DonationQuality : IDisposable { private readonly ConfigEntry<float> chance; private readonly ManualLogSource log; private readonly Random random = new Random(); private MethodInfo getQuality; private MethodInfo withQuality; private Type tierType; private ILHook yellowHook; private bool warned; private static MethodInfo itemQuality; private static MethodInfo itemVariant; private static Type qualityEnum; public static int PermanentCount(Inventory inventory, ItemIndex index) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: 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_0093: Invalid comparison between Unknown and I4 //IL_0095: 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_00a5: Unknown result type (might be due to invalid IL or missing references) int num = inventory.GetItemCountPermanent(index); if (itemQuality == null || itemVariant == null || Convert.ToInt32(itemQuality.Invoke(null, new object[1] { index })) != -1) { return num; } for (int i = 0; i < 4; i++) { ItemIndex val = (ItemIndex)itemVariant.Invoke(null, new object[2] { index, Enum.ToObject(qualityEnum, i) }); if ((int)val != -1 && val != index) { num -= inventory.GetItemCountPermanent(val); } } return Math.Max(0, num); } public DonationQuality(ConfigFile config, ManualLogSource logger) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Expected O, but got Unknown //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Expected O, but got Unknown log = logger; chance = config.Bind<float>("Rewards", "QualityChancePercent", 5f, new ConfigDescription("Chance per donated reward item to gain quality. Both altars. Quality levels: 70% Uncommon, 20% Rare, 8% Epic, 2% Legendary. Requires the Quality mod.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), new object[0])); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { Type type = assembly.GetType("ItemQualities.QualityCatalog"); if (!(type == null)) { tierType = assembly.GetType("ItemQualities.QualityTier"); getQuality = type.GetMethod("GetQualityTier", new Type[1] { typeof(PickupIndex) }); withQuality = type.GetMethod("GetPickupIndexOfQuality", new Type[2] { typeof(PickupIndex), tierType }); itemQuality = type.GetMethod("GetQualityTier", new Type[1] { typeof(ItemIndex) }); itemVariant = type.GetMethod("GetItemIndexOfQuality", new Type[2] { typeof(ItemIndex), tierType }); qualityEnum = tierType; break; } } if (getQuality == null || withQuality == null) { log.LogWarning((object)"Quality mod API unavailable; donation rewards remain ordinary."); return; } yellowHook = new ILHook((MethodBase)typeof(BazaarDonate).GetMethod("PurchaseInteraction_OnInteractionBegin", BindingFlags.Instance | BindingFlags.NonPublic), new Manipulator(PatchYellow)); log.LogInfo((object)("Both donation altars have a " + chance.Value + "% quality chance per reward item.")); } private void PatchYellow(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown //IL_0082: Unknown result type (might be due to invalid IL or missing references) ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1] { delegate(Instruction instruction) { object operand = instruction.Operand; MethodReference val3 = (MethodReference)((operand is MethodReference) ? operand : null); return val3 != null && ((MemberReference)((MemberReference)val3).DeclaringType).FullName == "BazaarIsMyHaven.Helper" && ((MemberReference)val3).Name == "PayCost"; } })) { throw new InvalidOperationException("Yellow donation payment call not found."); } VariableDefinition val2 = il.Body.Variables[3]; if (((MemberReference)((VariableReference)val2).VariableType).FullName != "System.Collections.Generic.Dictionary`2<RoR2.PickupIndex,System.Int32>") { throw new InvalidOperationException("Yellow reward local changed; expected BazaarIsMyHaven 5.3.0."); } val.Emit(OpCodes.Ldloc, val2); val.EmitDelegate<Action<Dictionary<PickupIndex, int>>>((Action<Dictionary<PickupIndex, int>>)Apply); } public void Apply(Dictionary<PickupIndex, int> rewards) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Invalid comparison between Unknown and I4 //IL_0085: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || rewards == null || withQuality == null || chance.Value <= 0f) { return; } try { Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>(); foreach (KeyValuePair<PickupIndex, int> reward in rewards) { PickupDef pickupDef = PickupCatalog.GetPickupDef(reward.Key); bool flag = pickupDef != null && (int)pickupDef.itemIndex != -1 && Convert.ToInt32(getQuality.Invoke(null, new object[1] { reward.Key })) == -1; for (int i = 0; i < reward.Value; i++) { PickupIndex val = reward.Key; int num = (flag ? DonationQualityRoll.Select(chance.Value, random.NextDouble(), random.NextDouble()) : (-1)); if (num >= 0) { PickupIndex val2 = (PickupIndex)withQuality.Invoke(null, new object[2] { val, Enum.ToObject(tierType, num) }); if (val2 != PickupIndex.none && PickupCatalog.GetPickupDef(val2) != null) { val = val2; } } dictionary.TryGetValue(val, out var value); dictionary[val] = value + 1; } } rewards.Clear(); foreach (KeyValuePair<PickupIndex, int> item in dictionary) { rewards.Add(item.Key, item.Value); } } catch (Exception ex) { if (!warned) { warned = true; log.LogWarning((object)("Quality roll failed; keeping original donation reward. " + ex)); } } } public void Dispose() { if (yellowHook != null) { yellowHook.Dispose(); } } } public sealed class BazaarPaymentFix : IDisposable { private readonly ILHook hook; public BazaarPaymentFix() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (typeof(Helper).GetMethod("PayCostWithCompleteContext", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic) != null) { return; } hook = new ILHook((MethodBase)typeof(Helper).GetMethod("PayCost", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic), (Manipulator)delegate(ILContext il) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ILCursor val = new ILCursor(il); if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1] { delegate(Instruction instruction) { object operand = instruction.Operand; MethodReference val2 = (MethodReference)((operand is MethodReference) ? operand : null); return val2 != null && ((MemberReference)((MemberReference)val2).DeclaringType).FullName == "RoR2.CostTypeDef" && ((MemberReference)val2).Name == "PayCost" && val2.Parameters.Count == 5; } })) { throw new InvalidOperationException("Bazaar payment call changed; expected BazaarIsMyHaven 5.3.0."); } val.Remove(); val.EmitDelegate<Func<CostTypeDef, int, Interactor, GameObject, Xoroshiro128Plus, ItemIndex, PayCostResults>>((Func<CostTypeDef, int, Interactor, GameObject, Xoroshiro128Plus, ItemIndex, PayCostResults>)Pay); }); } private static PayCostResults Pay(CostTypeDef definition, int cost, Interactor activator, GameObject purchased, Xoroshiro128Plus rng, ItemIndex avoided) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected O, but got Unknown //IL_0045: 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) CharacterBody val = (Object.op_Implicit((Object)(object)activator) ? ((Component)activator).GetComponent<CharacterBody>() : null); PayCostResults val2 = new PayCostResults(); PayCostContext val3 = new PayCostContext(); val3.costTypeDef = definition; val3.cost = cost; val3.activator = activator; val3.purchasedObject = purchased; val3.rng = rng; val3.avoidedItemIndex = avoided; val3.activatorBody = val; val3.activatorMaster = (Object.op_Implicit((Object)(object)val) ? val.master : null); val3.activatorInventory = (Object.op_Implicit((Object)(object)val) ? val.inventory : null); val3.purchaseInteraction = (Object.op_Implicit((Object)(object)purchased) ? purchased.GetComponent<PurchaseInteraction>() : null); val3.results = val2; PayCostContext val4 = val3; definition.PayCost(val4, val2); return val2; } public void Dispose() { if (hook != null) { hook.Dispose(); } } }