using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BadItemAcademy.Components;
using BadItemAcademy.Modules;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HG.Reflection;
using IL.RoR2;
using Mono.Cecil.Cil;
using MonoMod.Cil;
using MonoMod.Utils;
using On.RoR2;
using On.RoR2.UI;
using R2API;
using R2API.Utils;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Items;
using RoR2.Orbs;
using RoR2.Projectile;
using RoR2.UI;
using RoR2BepInExPack.GameAssetPaths.Version_1_35_0;
using RoR2BepInExPack.GameAssetPathsBetter;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.Networking;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.UI;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: OptIn]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = "")]
[assembly: AssemblyCompany("BadItemAcademy")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("BadItemAcademy")]
[assembly: AssemblyTitle("BadItemAcademy")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: UnverifiableCode]
[module: UnverifiableCode]
namespace BadItemAcademy
{
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
[BepInPlugin("com.BadItemCouncil.BadItemRehabilitation", "BadItemRehabilitation", "1.3.4")]
[R2APISubmoduleDependency(new string[] { "ContentAddition" })]
[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
[BepInDependency(/*Could not decode attribute arguments.*/)]
public class BadItemAcademyPlugin : BaseUnityPlugin
{
private enum ScreamingInternally
{
Brfalse,
Brtrue,
Blt,
Bne,
Ble
}
public static PluginInfo PInfo;
public const string guid = "com.BadItemCouncil.BadItemRehabilitation";
public const string teamName = "BadItemCouncil";
public const string modName = "BadItemRehabilitation";
public const string version = "1.3.4";
private static AssetBundle _mainAssetBundle;
internal static bool AegisFortificationEnabled = false;
internal static float _AegisConversionInterval = 1f;
internal static float _AegisConversionRate = 1f;
internal static float _AegisRemovalRate = 1f;
internal static float _AegisForceConversionThreshold = 0.05f;
internal static int _AegisMaxFortificationStacks = 100;
internal static float _AegisMaxStatBonusBase = 0.2f;
internal static float _AegisMaxStatBonusStack = 0.1f;
internal static bool _AegisRevertHealingReduction = true;
internal static bool _AegisUseFortification = true;
private static float incomingHealingCache = 0f;
private static float modifiedHealingCache = 0f;
private static float barrierDecayedCache = 0f;
internal static bool _ChangeNkuhanaHealthCalculation = true;
internal static bool _ShouldBenthicWeighSelection = true;
internal static bool _InvertBenthicWeightedSelection = true;
internal static bool _BiasBenthicWeightedSelection = true;
private static GameObject _bottleChaosNetworkedBodyAttachment;
internal static readonly Xoroshiro128Plus globalBottledChaosEquipmentRng = new Xoroshiro128Plus(0uL);
public static List<EquipmentIndex> bottledChaosWidgetValidEquipment = new List<EquipmentIndex>();
internal static int _ChaosBonusBase = 1;
internal static int _ChaosBonusStack = 1;
internal static int _ChaosWidgetCount = 1;
internal static bool _ChaosBlacklistEgg = true;
internal static bool _ChaosQueueAllowCapacitor = true;
internal static bool _ChaosQueueAllowRecycler = true;
internal static bool _ChaosQueueAllowTricorn = true;
internal static bool _ChaosQueueAllowLunar = false;
internal static bool _ChaosQueueAllowEgg = true;
public const float chaosCycleIntervalExperimental = 7f;
public const float chaosCooldownMultiplierExperimental = 0.67f;
public static string chaosEquipCdrExperimental = $"{33f}%";
internal static bool _PoolHealingBeforeModifiers = true;
internal static bool _PoolHealingAfterIncrease = false;
internal static float _NkuhanaDamageMultiplier = 3.5f;
internal static float _NkuhanaProcCoefficient = 1f;
internal static float _NkuhanaMaxRange = 80f;
internal static float _VoidBandDamageMult = 2f;
internal static float _VoidBandProcCoeff = 2f;
public static AssetBundle mainAssetBundle
{
get
{
if ((Object)(object)_mainAssetBundle == (Object)null)
{
_mainAssetBundle = Assets.LoadAssetBundle("baditemrehab");
}
return _mainAssetBundle;
}
set
{
_mainAssetBundle = value;
}
}
public static bool isExperimentalMode => Tools.isLoaded("com.RiskOfBrainrot.RiskierRain");
public static BuffDef AegisFortificationBuff => CommonAssets.AegisFortificationBuff;
public static GameObject bottleChaosNetworkedBodyAttachment => _bottleChaosNetworkedBodyAttachment;
internal static int ChaosWidgetCountFinal => isExperimentalMode ? 1 : Bindings.ChaosWidgetCount.Value;
private void Awake()
{
PInfo = ((BaseUnityPlugin)this).Info;
Bindings.Init();
CommonAssets.Init();
if (Bindings.BindSection("NKuhanas Opinion"))
{
RehabNkuhanas();
}
if (Bindings.BindSection("Singularity Band"))
{
RehabSingularityBand();
}
if (Bindings.BindSection("Benthic Bloom"))
{
RehabBenthic();
}
if (Bindings.BindSection("Aegis") && !isExperimentalMode)
{
RehabAegis();
}
if (Bindings.BindSection("Bottled Chaos"))
{
RehabBottledChaos();
}
if (Bindings.AprilFools ? Bindings.DontUseAprilFools.Value : Bindings.UseAprilFools.Value)
{
CloverChanges();
}
Bindings.Save();
}
public static AssetReferenceT<T> LoadAsync<T>(string guid, Action<T> callback) where T : Object
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
AssetReferenceT<T> val = new AssetReferenceT<T>(guid);
AsyncOperationHandle<T> handle2 = AssetAsyncReferenceManager<T>.LoadAsset(val, (AsyncReferenceHandleUnloadType)2);
if (callback == null)
{
return val;
}
if (handle2.IsDone)
{
onCompleted(handle2);
return val;
}
handle2.Completed += onCompleted;
return val;
void onCompleted(AsyncOperationHandle<T> handle)
{
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0017: Invalid comparison between Unknown and I4
if (handle.Result == null || (int)handle.Status != 1)
{
Debug.LogError((object)$"Failed to load asset [{handle.DebugName}] : {handle.OperationException}");
}
else
{
callback(handle.Result);
}
}
}
public static void DebugBreakpoint(string methodName, int breakpointNumber = -1)
{
string text = "(BadItemRehabilitation) " + methodName + " IL hook failed!";
if (breakpointNumber >= 0)
{
text += $" (breakpoint {breakpointNumber})";
}
Debug.LogError((object)text);
}
public static void CloverChanges()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Expected O, but got Unknown
//IL_004c: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Expected O, but got Unknown
LanguageAPI.Add("ITEM_CLOVER_NAME", "67 Leaf Clover");
LanguageAPI.Add("ITEM_CLOVER_DESC", "Doubles the listed probabilities of ALL random effects <style=cStack>(+100% per stack)</style>.");
Util.CheckRoll_float_float_CharacterMaster += new hook_CheckRoll_float_float_CharacterMaster(FixCloverMath);
HealthComponent.TakeDamageProcess += new Manipulator(LuckForTeddies);
RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(CloverCrit);
}
private static void CloverCrit(CharacterBody sender, StatHookEventArgs args)
{
if (Object.op_Implicit((Object)(object)sender.inventory))
{
int itemCountEffective = sender.inventory.GetItemCountEffective(Items.Clover);
if (itemCountEffective > 0)
{
args.critAdd += 10f;
args.bleedChanceAdd += 1f;
}
}
}
private static void LuckForTeddies(ILContext il)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_00b5: 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 x) => ILPatternMatchingExt.MatchLdfld<ItemCounts>(x, "bear")
}) || !val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, "RoR2.Util", "CheckRoll")
}) || !val.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, 0f)
}))
{
DebugBreakpoint("LuckForTeddies");
return;
}
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)((float luckIn, HealthComponent healthComponent) => (Object.op_Implicit((Object)(object)healthComponent.body) && Object.op_Implicit((Object)(object)healthComponent.body.master)) ? healthComponent.body.master.luck : luckIn));
}
private static bool FixCloverMath(orig_CheckRoll_float_float_CharacterMaster orig, float percentChance, float luck, CharacterMaster effectOriginMaster)
{
if (luck == 0f)
{
return orig.Invoke(percentChance, 0f, effectOriginMaster);
}
float num = ((luck > 0f) ? (luck + 1f) : (1f / (luck + 1f)));
return orig.Invoke(percentChance * (luck + 1f), 0f, effectOriginMaster);
}
public static void RehabAegis()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Expected O, but got Unknown
//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
//IL_00f4: Expected O, but got Unknown
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Expected O, but got Unknown
if (Bindings.AegisUseFortification.Value)
{
AegisFortificationEnabled = true;
}
RecalculateStatsAPI.GetStatCoefficients += new StatHookEventHandler(AegisStatCoefficients);
LanguageAPI.Add("ITEM_BARRIERONOVERHEAL_PICKUP", "Healing past full grants you a temporary barrier. Decayed barrier boosts all damage stats.");
LanguageAPI.Add("ITEM_BARRIERONOVERHEAL_DESC", "Healing past full grants you a <style=cIsHealing>temporary barrier</style> for <style=cIsHealing>50% <style=cStack>(+50% per stack)</style></style> of the amount you <style=cIsHealing>healed</style>. " + ((!Bindings.AegisUseFortification.Value) ? "" : ($"Every <style=cIsHealing>{Bindings.AegisForceConversionThreshold.Value * 100f}%</style> barrier that decays is converted into " + "<style=cIsDamage>Fortification</style>, increasing damage, attack speed, and critical strike chance " + $"by up to <style=cIsDamage>{Bindings.AegisMaxStatBonusBase.Value * 100f}%</style> " + $"<style=cStack>(+{Bindings.AegisMaxStatBonusStack.Value * 100f}% per stack)</style>. " + "<style=cIsDamage>Fortification</style> is lost when taking damage.")));
HealthComponent.ServerFixedUpdate += new Manipulator(HealthComponent_ServerFixedUpdate_CumulateBarrierDecay);
HealthComponent.Heal += new Manipulator(HealthComponent_Heal_OverhealToBarrier);
}
private static void AegisStatCoefficients(CharacterBody sender, StatHookEventArgs args)
{
if (Bindings.AegisUseFortification.Value)
{
Inventory inventory = sender.inventory;
int num = ((inventory != null) ? inventory.GetItemCountEffective(Items.BarrierOnOverHeal) : 0);
int buffCount = sender.GetBuffCount(AegisFortificationBuff);
if (buffCount > 0 && num > 0)
{
float num2 = Bindings.AegisMaxStatBonusBase.Value + Bindings.AegisMaxStatBonusStack.Value * (float)(num - 1);
float num3 = num2 * ((float)buffCount / (float)Bindings.AegisMaxFortificationStacks.Value);
args.damageMultAdd += num3;
args.attackSpeedMultAdd += num3;
args.critAdd += num3 * 100f;
}
}
}
private static void HealthComponent_Heal_OverhealToBarrier(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
int modifiedHealingLoc = 2;
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<ItemCounts>(x, "increaseHealing")
}) || !val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStarg(x, 1)
}))
{
DebugBreakpoint("HealthComponent_Heal_OverhealToBarrier", 1);
val.Index = 0;
}
else
{
int index = val.Index;
val.Index = index + 1;
}
val.Emit(OpCodes.Ldarg_1);
val.EmitDelegate<Action<float>>((Action<float>)delegate(float incomingHealing)
{
incomingHealingCache = incomingHealing;
});
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 1),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref modifiedHealingLoc)
}))
{
DebugBreakpoint("HealthComponent_Heal_OverhealToBarrier", 2);
return;
}
val.Emit(OpCodes.Ldloc, modifiedHealingLoc);
val.EmitDelegate<Action<float>>((Action<float>)delegate(float modifiedHealing)
{
modifiedHealingCache = modifiedHealing;
});
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "AddBarrier")
}) || !val.TryGotoPrev((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdloc(x, modifiedHealingLoc)
}))
{
DebugBreakpoint("HealthComponent_Heal_OverhealToBarrier", 3);
return;
}
val.EmitDelegate<Func<float, float>>((Func<float, float>)delegate(float healingRemainder)
{
if (healingRemainder == 0f || modifiedHealingCache == 0f || !Bindings.AegisRevertHealingReduction.Value)
{
return healingRemainder;
}
if (healingRemainder == modifiedHealingCache)
{
return incomingHealingCache;
}
float num = incomingHealingCache / modifiedHealingCache;
return (num <= 1f) ? healingRemainder : (healingRemainder * num);
});
}
private static void HealthComponent_ServerFixedUpdate_CumulateBarrierDecay(ILContext il)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0050: 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)
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "set_Networkbarrier")
}))
{
DebugBreakpoint("HealthComponent_ServerFixedUpdate_CumulateBarrierDecay", 1);
return;
}
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Func<float, HealthComponent, float>>((Func<float, HealthComponent, float>)delegate(float newBarrier, HealthComponent self)
{
barrierDecayedCache = self.barrier - newBarrier;
return newBarrier;
});
int index = val.Index;
val.Index = index + 1;
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Action<HealthComponent>>((Action<HealthComponent>)delegate(HealthComponent self)
{
if (self.itemCounts.barrierOnOverHeal > 0 && NetworkServer.active && Bindings.AegisUseFortification.Value)
{
AegisItemBehavior component = ((Component)self.body).GetComponent<AegisItemBehavior>();
if ((Object)(object)component != (Object)null && ((BaseItemBodyBehavior)component).stack > 0)
{
component.OnBarrierDecayed(barrierDecayedCache);
}
}
});
}
public static void RehabBenthic()
{
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
if (Bindings.ShouldBenthicWeighSelection.Value)
{
CharacterMaster.TryCloverVoidUpgrades += new Manipulator(CloverWeightedSelection);
}
}
public static void CloverWeightedSelection(ILContext il)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt(x, "RoR2.Util", "ShuffleList")
}))
{
DebugBreakpoint("CloverWeightedSelection");
return;
}
val.Remove();
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Action<List<ItemIndex>, Xoroshiro128Plus, CharacterMaster>>((Action<List<ItemIndex>, Xoroshiro128Plus, CharacterMaster>)delegate(List<ItemIndex> itemList, Xoroshiro128Plus rng, CharacterMaster master)
{
CreateShuffledListFromWeightedSelection(ref itemList, rng, master);
});
}
public static void CreateShuffledListFromWeightedSelection(ref List<ItemIndex> list, Xoroshiro128Plus rng, CharacterMaster master)
{
//IL_001a: 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_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00e3: Invalid comparison between Unknown and I4
//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
//IL_013f: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)master.inventory == (Object)null || master.inventory.GetItemCountEffective(Items.CloverVoid.itemIndex) <= 0 || list == null || list.Count < 0)
{
return;
}
int totalItemCountOfTier = master.inventory.GetTotalItemCountOfTier((ItemTier)0);
int totalItemCountOfTier2 = master.inventory.GetTotalItemCountOfTier((ItemTier)1);
if (totalItemCountOfTier + totalItemCountOfTier2 == 0)
{
Debug.Log((object)"Could not create a Benthic weighted selection: No Tier 1/2 Items");
return;
}
WeightedSelection<ItemIndex> val = new WeightedSelection<ItemIndex>(list.Count);
foreach (ItemIndex item in list)
{
ItemDef itemDef = ItemCatalog.GetItemDef(item);
if ((Object)(object)itemDef == (Object)null || !itemDef.canRemove)
{
continue;
}
int num = 1;
ItemTier tier = itemDef.tier;
ItemTier val2 = tier;
if ((int)val2 != 0)
{
if ((int)val2 != 1)
{
continue;
}
num = totalItemCountOfTier / (totalItemCountOfTier + totalItemCountOfTier2);
}
else
{
num = totalItemCountOfTier2 / (totalItemCountOfTier + totalItemCountOfTier2);
}
int itemCountEffective = master.inventory.GetItemCountEffective(item);
float num2 = 1 / itemCountEffective;
float num3 = (Bindings.InvertBenthicWeightedSelection.Value ? num2 : ((float)itemCountEffective));
if (Bindings.BiasBenthicWeightedSelection.Value)
{
num3 *= (float)num;
}
val.AddChoice(item, num3);
}
list = new List<ItemIndex>(val.Count);
for (int i = 0; i < list.Count; i++)
{
if (val.Count <= 0)
{
break;
}
if (val.totalWeight == 0f)
{
break;
}
int num4 = val.EvaluateToChoiceIndex(rng.nextNormalizedFloat);
if (num4 < val.Count)
{
list[i] = val.choices[num4].value;
val.ModifyChoiceWeight(num4, 0f);
}
}
}
public static void RehabBottledChaos()
{
//IL_002d: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Expected O, but got Unknown
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Expected O, but got Unknown
//IL_0051: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: Expected O, but got Unknown
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Expected O, but got Unknown
//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
//IL_00ea: Expected O, but got Unknown
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Expected O, but got Unknown
CreateBottleChaosBodyAttachment();
if (ChaosWidgetCountFinal > 0)
{
Run.onRunStartGlobal += GenerateChaosWidgetEquipmentList;
HUD.Awake += new hook_Awake(AddBhaosWidget);
EquipmentSlot.RpcOnClientEquipmentActivationRecieved += new hook_RpcOnClientEquipmentActivationRecieved(UpdateBhaosWidgetClient);
EquipmentSlot.OnEquipmentExecuted_byte_byte_EquipmentIndex += new Manipulator(AlterBhaosFireCount);
CharacterMaster.OnBodyStart += new hook_OnBodyStart(OnPlayerBodyStart);
}
if (isExperimentalMode)
{
Inventory.CalculateEquipmentCooldownScale += new hook_CalculateEquipmentCooldownScale(BottledChaosCdrExperimental);
LanguageAPI.Add("ITEM_RANDOMEQUIPMENTTRIGGER_DESC", "Activating your equipment triggers an additonal <style=cIsDamage>random effect</style>, " + $"changing every <style=cIsDamage>{7f}</style> seconds. " + "<style=cIsUtility>Reduce equipment cooldown</style> by <style=cIsUtility>0%</style> <style=cStack>(+" + chaosEquipCdrExperimental + " per stack)</style>.");
}
EquipmentSlot.FireBossHunter += new Manipulator(FixBossHunterChaos);
BadItemAcademyPlugin.LoadAsync<EquipmentDef>(RoR2_Base_FireBallDash.FireBallDash_asset, (Action<EquipmentDef>)delegate(EquipmentDef equip)
{
if (Bindings.ChaosBlacklistEgg.Value)
{
equip.canBeRandomlyTriggered = false;
}
});
}
private static float BottledChaosCdrExperimental(orig_CalculateEquipmentCooldownScale orig, Inventory self)
{
float num = orig.Invoke(self);
int num2 = self.GetItemCountEffective(Items.RandomEquipmentTrigger) - 1;
if (num2 > 0)
{
num *= Mathf.Pow(0.67f, (float)num2);
}
return num;
}
private static void CreateBottleChaosBodyAttachment()
{
//IL_0006: 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)
_bottleChaosNetworkedBodyAttachment = PrefabAPI.InstantiateClone(Addressables.LoadAssetAsync<GameObject>((object)RoR2_Base_QuestVolatileBattery.QuestVolatileBatteryAttachment_prefab).WaitForCompletion(), "BIA_BottleChaosBodyAttachment", true);
NetworkStateMachine val = default(NetworkStateMachine);
if (_bottleChaosNetworkedBodyAttachment.TryGetComponent<NetworkStateMachine>(ref val))
{
Object.Destroy((Object)(object)val);
}
EntityStateMachine val2 = default(EntityStateMachine);
if (_bottleChaosNetworkedBodyAttachment.TryGetComponent<EntityStateMachine>(ref val2))
{
Object.Destroy((Object)(object)val2);
}
BottleChaosBodyAttachment bottleChaosBodyAttachment = _bottleChaosNetworkedBodyAttachment.AddComponent<BottleChaosBodyAttachment>();
ContentAddition.AddNetworkedObject(_bottleChaosNetworkedBodyAttachment);
}
private static void FixBossHunterChaos(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
ILCursor val = new ILCursor(il);
ILLabel label = val.DefineLabel();
if (!val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<CharacterMasterNotificationQueue>(x, "SendTransformNotification")
}) || !val.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref label)
}) || !val.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, 0),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<EquipmentSlot>(x, "get_characterBody")
}))
{
DebugBreakpoint("FixBossHunterChaos");
return;
}
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Func<EquipmentSlot, bool>>((Func<EquipmentSlot, bool>)delegate(EquipmentSlot slot)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
Debug.Log((object)EquipmentCatalog.GetEquipmentDef(slot.equipmentIndex).nameToken);
return slot.equipmentIndex == Equipment.BossHunter.equipmentIndex;
});
val.Emit(OpCodes.Brfalse_S, (object)label);
}
public static void GenerateChaosWidgetEquipmentList(Run run)
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: 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)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
bottledChaosWidgetValidEquipment = new List<EquipmentIndex>();
globalBottledChaosEquipmentRng.ResetSeed(run.seed);
foreach (EquipmentIndex randomTriggerEquipment in EquipmentCatalog.randomTriggerEquipmentList)
{
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef(randomTriggerEquipment);
ValidateEquipment(equipmentDef);
}
if (Bindings.ChaosQueueAllowLunar.Value)
{
foreach (EquipmentIndex enigmaEquipment in EquipmentCatalog.enigmaEquipmentList)
{
EquipmentDef equipmentDef2 = EquipmentCatalog.GetEquipmentDef(enigmaEquipment);
if (equipmentDef2.isLunar)
{
ValidateEquipment(equipmentDef2);
}
}
}
if (Bindings.ChaosBlacklistEgg.Value && Bindings.ChaosQueueAllowEgg.Value)
{
ValidateEquipment(Equipment.FireBallDash);
}
bool flag = false;
if (Bindings.ChaosQueueAllowRecycler.Value)
{
ValidateEquipment(Equipment.Recycle);
}
if (Bindings.ChaosQueueAllowTricorn.Value)
{
ValidateEquipment(Equipment.BossHunter);
}
void ValidateEquipment(EquipmentDef def)
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if (Object.op_Implicit((Object)(object)def) && (!Object.op_Implicit((Object)(object)def.requiredExpansion) || run.IsExpansionEnabled(def.requiredExpansion)))
{
bottledChaosWidgetValidEquipment.Add(def.equipmentIndex);
}
}
}
private static void RefreshChaosWidgetsOnStageStart(Stage obj)
{
BottleChaosWidget.RefreshAll();
}
private static void OnPlayerBodyStart(orig_OnBodyStart orig, CharacterMaster self, CharacterBody body)
{
orig.Invoke(self, body);
if (body.isPlayerControlled)
{
BottleChaosWidget.RefreshAll();
}
}
private static void OnPlayerBodyInventoryChange(orig_OnInventoryChanged orig, CharacterBody self)
{
orig.Invoke(self);
if (self.isPlayerControlled)
{
BottleChaosWidget.RefreshAll();
}
}
private static void UpdateBhaosWidgetClient(orig_RpcOnClientEquipmentActivationRecieved orig, EquipmentSlot self)
{
orig.Invoke(self);
BottleChaosWidget.RefreshAll();
}
public static int GetBhaosActivationCountFromBhaosStacks(int stack)
{
if (stack == 0)
{
return 0;
}
if (isExperimentalMode)
{
return ChaosWidgetCountFinal;
}
return Bindings.ChaosBonusBase.Value + Bindings.ChaosBonusStack.Value * (stack - 1);
}
private static void AddBhaosWidget(orig_Awake orig, HUD self)
{
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Expected O, but got Unknown
orig.Invoke(self);
GameObject val = new GameObject("BIA_BottledChaosHUD");
val.layer = LayerMask.NameToLayer("UI");
Transform transform = self.mainContainer.transform;
val.transform.SetParent(transform);
BottleChaosWidget bottleChaosWidget = val.AddComponent<BottleChaosWidget>();
bottleChaosWidget.Initialize(self);
((Component)bottleChaosWidget).gameObject.SetActive(false);
}
private static void AlterBhaosFireCount(ILContext il)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Expected O, but got Unknown
//IL_0072: 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>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdsfld(x, "RoR2.DLC1Content/Items", "RandomEquipmentTrigger"),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<Inventory>(x, "GetItemCountEffective")
}))
{
DebugBreakpoint("AlterBhaosFireCount", 1);
return;
}
val.Emit(OpCodes.Ldarg_0);
val.EmitDelegate<Func<int, EquipmentSlot, int>>((Func<int, EquipmentSlot, int>)delegate(int stack, EquipmentSlot equipmentSlot)
{
//IL_016f: 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_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: 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)
int bhaosActivationCountFromBhaosStacks = GetBhaosActivationCountFromBhaosStacks(stack);
if (bhaosActivationCountFromBhaosStacks <= 0)
{
return 0;
}
int num = bhaosActivationCountFromBhaosStacks;
BottleChaosItemBehavior bottleChaosItemBehavior = default(BottleChaosItemBehavior);
if (((Component)equipmentSlot.characterBody).TryGetComponent<BottleChaosItemBehavior>(ref bottleChaosItemBehavior))
{
BottleChaosBodyAttachment bodyAttachmentComponent = bottleChaosItemBehavior.bodyAttachmentComponent;
if (Object.op_Implicit((Object)(object)bodyAttachmentComponent))
{
for (int i = 0; i < bhaosActivationCountFromBhaosStacks && i < ((SyncList<int>)(object)bodyAttachmentComponent.nextEquipments).Count; i++)
{
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)((SyncList<int>)(object)bodyAttachmentComponent.nextEquipments)[i]);
if (equipmentSlot.PerformEquipmentAction(equipmentDef))
{
num--;
if (equipmentDef.equipmentIndex == Equipment.BFG.equipmentIndex)
{
ModelLocator component = ((Component)equipmentSlot).GetComponent<ModelLocator>();
if (Object.op_Implicit((Object)(object)component))
{
Transform modelTransform = component.modelTransform;
if (Object.op_Implicit((Object)(object)modelTransform))
{
CharacterModel component2 = ((Component)modelTransform).GetComponent<CharacterModel>();
if (Object.op_Implicit((Object)(object)component2))
{
List<GameObject> itemDisplayObjects = component2.GetItemDisplayObjects(Items.RandomEquipmentTrigger.itemIndex);
if (itemDisplayObjects.Count > 0)
{
Object.Instantiate<GameObject>(Addressables.LoadAssetAsync<GameObject>((object)"RoR2/Base/BFG/ChargeBFG.prefab").WaitForCompletion(), itemDisplayObjects[0].transform);
}
}
}
}
}
}
}
bottleChaosItemBehavior.UpdateNextEquipmentDef();
}
}
if (num == 0)
{
EffectData val2 = new EffectData();
val2.origin = equipmentSlot.characterBody.corePosition;
val2.SetNetworkedObjectReference(((Component)equipmentSlot).gameObject);
EffectManager.SpawnEffect(LegacyResourcesAPI.Load<GameObject>("Prefabs/Effects/RandomEquipmentTriggerProcEffect"), val2, true);
}
return num;
});
}
public static void RehabNkuhanas()
{
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Expected O, but got Unknown
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Expected O, but got Unknown
if (Bindings.PoolHealingBeforeModifiers.Value)
{
HealthComponent.Heal += new Manipulator(HealthComponent_Heal_Pooling);
}
HealthComponent.ServerFixedUpdate += new Manipulator(NkuhanasBuff);
LanguageAPI.Add("ITEM_NOVAONHEAL_DESC", "Store <style=cIsHealing>100%</style> <style=cStack>(+100% per stack)</style> of healing as <style=cIsHealing>Soul Energy</style>. After your <style=cIsHealing>Soul Energy</style> reaches <style=cIsHealing>10%</style> of your " + (Bindings.ChangeNkuhanaHealthCalculation.Value ? "<style=cIsHealing>base health</style>, " : "<style=cIsHealing>maximum health</style>, ") + $"<style=cIsDamage>fire a skull</style> that deals <style=cIsDamage>{Bindings.NkuhanaDamageMultiplier.Value * 100f}%</style> " + "of your <style=cIsHealing>Soul Energy</style> as <style=cIsDamage>damage</style>.");
}
public static void NkuhanasBuff(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);
bool flag = val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<HealthComponent>(x, "devilOrbHealPool")
});
int index = val.Index;
BuffNkuhanaDamage(val);
if (Bindings.ChangeNkuhanaHealthCalculation.Value)
{
val.Index = index;
FixNkuahanHealth(val);
}
val.Index = index;
BuffNkuhanaRange(val);
val.Index = index;
BuffNkuhanaProcCoefficient(val);
}
public static void BuffNkuhanaProcCoefficient(ILCursor c)
{
//IL_0066: Unknown result type (might be due to invalid IL or missing references)
int index = 9;
if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchNewobj<DevilOrb>(x),
(Instruction x) => ILPatternMatchingExt.MatchStloc(x, ref index)
}))
{
DebugBreakpoint("BuffNkuhanaProcCoefficient");
return;
}
c.Emit(OpCodes.Ldloc, index);
c.EmitDelegate<Action<DevilOrb>>((Action<DevilOrb>)delegate(DevilOrb devilOrb)
{
devilOrb.procCoefficient = Bindings.NkuhanaProcCoefficient.Value;
});
}
public static void BuffNkuhanaRange(ILCursor c)
{
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
float num = default(float);
if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdcR4(x, ref num),
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<DevilOrb>(x, "PickNextTarget")
}))
{
DebugBreakpoint("BuffNkuhanaRange");
return;
}
c.Remove();
c.Emit(OpCodes.Ldc_R4, Bindings.NkuhanaMaxRange.Value);
}
public static void FixNkuahanHealth(ILCursor c)
{
if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchCallOrCallvirt<HealthComponent>(x, "get_fullCombinedHealth")
}))
{
DebugBreakpoint("FixNkuahanHealth");
return;
}
c.Remove();
c.EmitDelegate<Func<HealthComponent, float>>((Func<HealthComponent, float>)delegate(HealthComponent hc)
{
CharacterBody body = hc.body;
if (!Object.op_Implicit((Object)(object)body))
{
return hc.fullCombinedHealth;
}
float num = body.level - 1f;
return body.baseMaxHealth + body.baseMaxShield + (body.levelMaxHealth + body.levelMaxShield) * num;
});
}
public static void BuffNkuhanaDamage(ILCursor c)
{
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStfld<DevilOrb>(x, "damageValue")
}))
{
DebugBreakpoint("BuffNkuhanaDamage");
return;
}
c.Index -= 2;
c.Remove();
c.Emit(OpCodes.Ldc_R4, Bindings.NkuhanaDamageMultiplier.Value);
}
public static void HealthComponent_Heal_Pooling(ILContext il)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Expected O, but got Unknown
ILCursor val = new ILCursor(il);
ILLabel val2 = val.DefineLabel();
ILLabel target = val.DefineLabel();
int num3 = default(int);
if (!val.TryGotoNext((MoveType)0, new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, ref num3),
(Instruction X) => ILPatternMatchingExt.MatchLdflda<HealthComponent>(X, "itemCounts"),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<ItemCounts>(x, "increaseHealing")
}))
{
DebugBreakpoint("HealthComponent_Heal_Pooling");
return;
}
if (!Bindings.PoolHealingAfterIncrease.Value || !val.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBle(x, ref target)
}))
{
if (Bindings.PoolHealingAfterIncrease.Value)
{
Debug.Log((object)"(BadItemRehabilitation) Error: PoolHealingAfterIncrease is true, but failed to find label. Falling back to [PoolHealingAfterIncrease=false] label.");
}
val.MarkLabel(target);
}
val2 = target;
int count = 1;
int count2 = 1;
GetOpinionLabels(val, target, out var poolStart, out var poolEnd);
HyperSwap(val, target, poolStart, poolEnd, out var newEnd, out var newStart, out var newTarget);
target = newTarget;
RedirectAllBranchesToLabel(val, poolEnd, newEnd, count, ScreamingInternally.Brtrue);
RedirectAllBranchesToLabel(val, poolEnd, newEnd, count2, ScreamingInternally.Ble);
int count3 = 1;
int count4 = 2;
int num = 1;
int num2 = 1;
GetCorpsebloomLabels(val, target, out poolStart, out poolEnd);
HyperSwap(val, target, poolStart, poolEnd, out newEnd, out newStart, out newTarget);
RedirectAllBranchesToLabel(val, poolEnd, newEnd, count3, ScreamingInternally.Brtrue);
RedirectAllBranchesToLabel(val, poolEnd, newEnd, count4);
RedirectAllBranchesToLabel(val, poolStart, newStart, 1, ScreamingInternally.Blt);
RedirectAllBranchesToLabel(val, poolStart, newStart, 1, ScreamingInternally.Bne);
Debug.Log((object)"bia redirecting branches before target to acknowledge inserted code. true search");
RedirectAllBranchesToLabel(val, val2, newTarget, 1);
Extensions.RecalculateILOffsets(val.Method);
}
public static void HyperSwap(ILCursor c, ILLabel target, ILLabel poolStart, ILLabel poolEnd, out ILLabel newEnd, out ILLabel newStart, out ILLabel newTarget)
{
SwapLabel(c, poolEnd, target, out newEnd);
SwapLabel(c, poolStart, poolEnd, out newStart);
SwapLabel(c, target, poolStart, out newTarget);
}
public static void GetOpinionLabels(ILCursor c, ILLabel target, out ILLabel poolStart, out ILLabel poolEnd)
{
poolStart = c.DefineLabel();
poolEnd = c.DefineLabel();
Debug.Log((object)"bia opinion");
c.Index = 0;
int num = default(int);
if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[3]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, ref num),
(Instruction X) => ILPatternMatchingExt.MatchLdflda<HealthComponent>(X, "itemCounts"),
(Instruction x) => ILPatternMatchingExt.MatchLdfld<ItemCounts>(x, "novaOnHeal")
}))
{
DebugBreakpoint("GetOpinionLabels", 1);
return;
}
c.MarkLabel(poolStart);
if (!c.TryGotoNext((MoveType)2, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchStfld<HealthComponent>(x, "devilOrbHealPool")
}))
{
DebugBreakpoint("GetOpinionLabels", 2);
}
else
{
c.MarkLabel(poolEnd);
}
}
public static void GetCorpsebloomLabels(ILCursor c, ILLabel target, out ILLabel poolStart, out ILLabel poolEnd)
{
poolStart = c.DefineLabel();
poolEnd = c.DefineLabel();
Debug.Log((object)"bia corpsebloom");
c.Index = 0;
if (!c.TryGotoNext((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchLdfld<HealthComponent>(x, "repeatHealComponent")
}))
{
DebugBreakpoint("GetCorpsebloomLabels", 1);
return;
}
ILLabel end = c.DefineLabel();
int num = default(int);
if (!c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[2]
{
(Instruction x) => ILPatternMatchingExt.MatchLdarg(x, ref num),
(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref end)
}))
{
DebugBreakpoint("GetCorpsebloomLabels", 2);
return;
}
poolEnd = end;
c.MarkLabel(poolStart);
}
private static void SwapLabel(ILCursor c, ILLabel location, ILLabel destination, out ILLabel newLabel)
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
c.GotoLabel(location, (MoveType)0, false);
c.Emit(OpCodes.Br, (object)destination);
int index = c.Index;
c.Index = index - 1;
newLabel = c.DefineLabel();
c.MarkLabel(newLabel);
}
private static void RedirectAllBranchesToLabel(ILCursor c, ILLabel labelOld, ILLabel labelNew, int count, ScreamingInternally screamingInternally = ScreamingInternally.Brfalse)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: 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_0092: Unknown result type (might be due to invalid IL or missing references)
//IL_0097: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
if (count <= 0)
{
return;
}
c.GotoLabel(labelOld, (MoveType)0, false);
bool flag = true;
ILLabel val5 = default(ILLabel);
ILLabel val2 = default(ILLabel);
ILLabel val4 = default(ILLabel);
ILLabel val3 = default(ILLabel);
ILLabel val6 = default(ILLabel);
for (int i = 0; i < count; i++)
{
OpCode val = OpCodes.Nop;
switch (screamingInternally)
{
default:
flag = false;
break;
case ScreamingInternally.Brfalse:
val = OpCodes.Brfalse_S;
flag = c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBrfalse(x, ref val5)
});
break;
case ScreamingInternally.Brtrue:
val = OpCodes.Brtrue_S;
flag = c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBrtrue(x, ref val2)
});
break;
case ScreamingInternally.Blt:
val = OpCodes.Blt_S;
flag = c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBlt(x, ref val4)
});
break;
case ScreamingInternally.Bne:
val = OpCodes.Bne_Un_S;
flag = c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBneUn(x, ref val3)
});
break;
case ScreamingInternally.Ble:
val = OpCodes.Ble_S;
flag = c.TryGotoPrev((MoveType)0, new Func<Instruction, bool>[1]
{
(Instruction x) => ILPatternMatchingExt.MatchBle(x, ref val6)
});
break;
}
if (!flag)
{
Debug.Log((object)"bia redirect exiting");
break;
}
c.Remove();
c.Emit(val, (object)labelNew);
int index = c.Index;
c.Index = index - 1;
OpCode opCode = c.Prev.OpCode;
Debug.Log((object)((object)(OpCode)(ref opCode)).ToString());
}
}
public static void RehabSingularityBand()
{
BadItemAcademyPlugin.LoadAsync<GameObject>(RoR2_DLC1_ElementalRingVoid.ElementalRingVoidBlackHole_prefab, (Action<GameObject>)delegate(GameObject prefab)
{
ProjectileExplosion component = prefab.GetComponent<ProjectileExplosion>();
if (Object.op_Implicit((Object)(object)component))
{
component.blastProcCoefficient = Bindings.VoidBandProcCoeff.Value;
component.blastDamageCoefficient = Bindings.VoidBandDamageMult.Value;
}
});
LanguageAPI.Add("ITEM_ELEMENTALRINGVOID_DESC", "Hits that deal <style=cIsDamage>more than 400% damage</style> also fire a black hole that <style=cIsUtility>draws enemies within 15m into its center</style>. Lasts <style=cIsUtility>5</style> seconds before collapsing, " + $"dealing <style=cIsDamage>{100f * Bindings.VoidBandDamageMult.Value}%</style> " + $"<style=cStack>(+{100f * Bindings.VoidBandDamageMult.Value} per stack)</style> TOTAL damage. " + "Recharges every <style=cIsUtility>20</style> seconds. <style=cIsVoid>Corrupts all Runald's and Kjaro's Bands</style>.");
}
}
public class AegisItemBehavior : BaseItemBodyBehavior, IOnTakeDamageServerReceiver
{
public float decayedBarrierCumulative = 0f;
private float aegisConversionStopwatch = 0f;
private bool isAtFullFortification = false;
public HealthComponent healthComponent => ((BaseItemBodyBehavior)this).body.healthComponent;
[ItemDefAssociation(useOnServer = true, useOnClient = false)]
private static ItemDef GetItemDef()
{
return Items.BarrierOnOverHeal;
}
private static BuffDef GetBuffDef()
{
return BadItemAcademyPlugin.AegisFortificationBuff;
}
private void Start()
{
if (!BadItemAcademyPlugin.AegisFortificationEnabled || !Bindings.AegisUseFortification.Value)
{
return;
}
CharacterBody body = ((BaseItemBodyBehavior)this).body;
if (body != null)
{
HealthComponent obj = body.healthComponent;
if (obj != null)
{
obj.AddOnTakeDamageServerReceiver((IOnTakeDamageServerReceiver)(object)this);
}
}
}
private void OnDestroy()
{
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
if (!BadItemAcademyPlugin.AegisFortificationEnabled)
{
return;
}
CharacterBody body = ((BaseItemBodyBehavior)this).body;
if (body != null)
{
HealthComponent obj = body.healthComponent;
if (obj != null)
{
obj.RemoveOnTakeDamageServerReceiver((IOnTakeDamageServerReceiver)(object)this);
}
}
((BaseItemBodyBehavior)this).body.SetBuffCount(GetBuffDef().buffIndex, 0);
}
public void CumulateBarrierDecay(HealthComponent healthComponent, float barrierDecayed)
{
if (BadItemAcademyPlugin.AegisFortificationEnabled && (Object)(object)healthComponent == (Object)(object)this.healthComponent)
{
OnBarrierDecayed(barrierDecayed);
}
}
public void OnBarrierDecayed(float barrierDecayed)
{
//IL_0132: Unknown result type (might be due to invalid IL or missing references)
//IL_017b: Unknown result type (might be due to invalid IL or missing references)
if (!BadItemAcademyPlugin.AegisFortificationEnabled || isAtFullFortification)
{
return;
}
decayedBarrierCumulative += barrierDecayed * Bindings.AegisConversionRate.Value;
aegisConversionStopwatch += Time.fixedDeltaTime;
if (healthComponent.barrier <= float.Epsilon || decayedBarrierCumulative >= healthComponent.fullCombinedHealth * Bindings.AegisForceConversionThreshold.Value || aegisConversionStopwatch >= Bindings.AegisConversionInterval.Value)
{
aegisConversionStopwatch = 0f;
int num = 0;
if (healthComponent.barrier <= float.Epsilon)
{
num = Mathf.CeilToInt(100f * decayedBarrierCumulative / healthComponent.fullCombinedHealth);
decayedBarrierCumulative = 0f;
}
else
{
float num2 = healthComponent.fullCombinedHealth / 100f;
num = Mathf.FloorToInt(decayedBarrierCumulative / num2);
decayedBarrierCumulative -= num2 * (float)num;
}
int buffCount = ((BaseItemBodyBehavior)this).body.GetBuffCount(GetBuffDef().buffIndex);
int num3 = buffCount + num;
if (num3 >= Bindings.AegisMaxFortificationStacks.Value)
{
num3 = Bindings.AegisMaxFortificationStacks.Value;
isAtFullFortification = true;
}
((BaseItemBodyBehavior)this).body.SetBuffCount(GetBuffDef().buffIndex, num3);
}
}
public void OnTakeDamageServer(DamageReport damageReport)
{
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Invalid comparison between Unknown and I4
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
if (!BadItemAcademyPlugin.AegisFortificationEnabled || (int)damageReport.damageInfo.damageType.damageType == 2048)
{
return;
}
CharacterBody victimBody = damageReport.victimBody;
HealthComponent val = ((victimBody != null) ? victimBody.healthComponent : null);
CharacterBody victimBody2 = damageReport.victimBody;
if (!((Object)(object)((victimBody2 != null) ? victimBody2.healthComponent : null) == (Object)null))
{
CharacterBody body = ((BaseItemBodyBehavior)this).body;
int num = ((body != null) ? body.GetBuffCount(GetBuffDef().buffIndex) : 0);
if (num != 0)
{
float num2 = damageReport.combinedHealthBeforeDamage - val.combinedHealth;
int num3 = Mathf.FloorToInt(100f * num2 * Bindings.AegisRemovalRate.Value / val.fullCombinedHealth);
damageReport.victimBody.SetBuffCount(GetBuffDef().buffIndex, Mathf.Max(num - num3, 0));
isAtFullFortification = false;
}
}
}
}
public class BottleChaosItemBehavior : BaseItemBodyBehavior
{
private GameObject bodyAttachmentObject;
private BottleChaosBodyAttachment _bodyAttachmentComponent;
public float equipmentCycleCountdown = 0f;
private bool starting = false;
public BottleChaosBodyAttachment bodyAttachmentComponent
{
get
{
if ((Object)(object)_bodyAttachmentComponent == (Object)null)
{
bodyAttachmentComponent = ((Component)((BaseItemBodyBehavior)this).body).GetComponentInChildren<BottleChaosBodyAttachment>();
}
return _bodyAttachmentComponent;
}
private set
{
_bodyAttachmentComponent = value;
}
}
private EquipmentSlot equipmentSlot
{
get
{
if ((Object)(object)((BaseItemBodyBehavior)this).body.inventory == (Object)null)
{
return null;
}
return ((BaseItemBodyBehavior)this).body.equipmentSlot;
}
}
[ItemDefAssociation(useOnServer = true, useOnClient = true)]
private static ItemDef GetItemDef()
{
return Items.RandomEquipmentTrigger;
}
public void UpdateNextEquipmentDef(bool updateAll = false)
{
if (NetworkServer.active)
{
if ((Object)(object)bodyAttachmentComponent == (Object)null)
{
Debug.LogError((object)"BIA: Bottled Chaos Networked Body Attachment not found!");
return;
}
starting = false;
equipmentCycleCountdown = 7f;
bodyAttachmentComponent.attachedBody = ((BaseItemBodyBehavior)this).body;
bodyAttachmentComponent.UpdateNextEquipmentDef(updateAll);
}
}
public override void OnInventoryRefresh()
{
((BaseItemBodyBehavior)this).OnInventoryRefresh();
BottleChaosWidget.RefreshAll();
}
private void OnEnable()
{
if (NetworkServer.active)
{
bodyAttachmentObject = Object.Instantiate<GameObject>(BadItemAcademyPlugin.bottleChaosNetworkedBodyAttachment, ((BaseItemBodyBehavior)this).body.transform);
bodyAttachmentObject.SetActive(true);
bodyAttachmentObject.GetComponent<NetworkedBodyAttachment>().AttachToGameObjectAndSpawn(((Component)((BaseItemBodyBehavior)this).body).gameObject, (string)null);
bodyAttachmentComponent = bodyAttachmentObject.GetComponent<BottleChaosBodyAttachment>();
bodyAttachmentComponent.attachedBody = ((BaseItemBodyBehavior)this).body;
UpdateNextEquipmentDef(updateAll: true);
equipmentCycleCountdown = 1f;
starting = true;
}
}
private void OnDisable()
{
if (NetworkServer.active)
{
UpdateNextEquipmentDef();
}
}
private void FixedUpdate()
{
if (NetworkServer.active && (BadItemAcademyPlugin.isExperimentalMode || starting))
{
equipmentCycleCountdown -= Time.fixedDeltaTime;
if (equipmentCycleCountdown <= 0f)
{
UpdateNextEquipmentDef(updateAll: true);
}
}
}
}
}
namespace BadItemAcademy.Modules
{
public static class CommonAssets
{
public static BuffDef AegisFortificationBuff;
public static void Init()
{
CreateAegisFortification();
}
private static void CreateAegisFortification()
{
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
AegisFortificationBuff = ScriptableObject.CreateInstance<BuffDef>();
((Object)AegisFortificationBuff).name = "bdBarrierFortification";
AegisFortificationBuff.iconSprite = BadItemAcademyPlugin.mainAssetBundle.LoadAsset<Sprite>("Assets/Textures/Icons/Buff/aegisbarrier.png");
AegisFortificationBuff.buffColor = Color.white;
AegisFortificationBuff.canStack = true;
AegisFortificationBuff.isDebuff = false;
AegisFortificationBuff.stackingDisplayMethod = (StackingDisplayMethod)1;
ContentAddition.AddBuffDef(AegisFortificationBuff);
}
}
public static class Tools
{
internal static bool isLoaded(string modguid)
{
foreach (KeyValuePair<string, PluginInfo> pluginInfo in Chainloader.PluginInfos)
{
string key = pluginInfo.Key;
PluginInfo value = pluginInfo.Value;
if (key == modguid)
{
return true;
}
}
return false;
}
}
public static class Assets
{
internal static Dictionary<string, AssetBundle> loadedBundles = new Dictionary<string, AssetBundle>();
internal static AssetBundle LoadAssetBundle(string bundleName)
{
if (loadedBundles.ContainsKey(bundleName))
{
return loadedBundles[bundleName];
}
AssetBundle val = null;
val = AssetBundle.LoadFromFile(Path.Combine(Path.GetDirectoryName(BadItemAcademyPlugin.PInfo.Location), bundleName));
loadedBundles[bundleName] = val;
return val;
}
}
public static class Bindings
{
internal static bool AprilFools;
internal static ConfigFile CustomConfigFile { get; set; }
internal static ConfigEntry<bool> PoolHealingBeforeModifiers { get; set; }
internal static ConfigEntry<bool> PoolHealingAfterIncrease { get; set; }
internal static ConfigEntry<float> VoidBandDamageMult { get; set; }
internal static ConfigEntry<float> VoidBandProcCoeff { get; set; }
internal static ConfigEntry<float> NkuhanaDamageMultiplier { get; set; }
internal static ConfigEntry<float> NkuhanaProcCoefficient { get; set; }
internal static ConfigEntry<float> NkuhanaMaxRange { get; set; }
internal static ConfigEntry<bool> ChangeNkuhanaHealthCalculation { get; set; }
internal static ConfigEntry<bool> ShouldBenthicWeighSelection { get; set; }
internal static ConfigEntry<bool> InvertBenthicWeightedSelection { get; set; }
internal static ConfigEntry<bool> BiasBenthicWeightedSelection { get; set; }
internal static ConfigEntry<float> AegisConversionInterval { get; set; }
internal static ConfigEntry<float> AegisConversionRate { get; set; }
internal static ConfigEntry<float> AegisRemovalRate { get; set; }
internal static ConfigEntry<float> AegisForceConversionThreshold { get; set; }
internal static ConfigEntry<int> AegisMaxFortificationStacks { get; set; }
internal static ConfigEntry<float> AegisMaxStatBonusBase { get; set; }
internal static ConfigEntry<float> AegisMaxStatBonusStack { get; set; }
internal static ConfigEntry<bool> AegisRevertHealingReduction { get; set; }
internal static ConfigEntry<bool> AegisUseFortification { get; set; }
internal static ConfigEntry<int> ChaosBonusBase { get; set; }
internal static ConfigEntry<int> ChaosBonusStack { get; set; }
internal static ConfigEntry<int> ChaosWidgetCount { get; set; }
internal static ConfigEntry<bool> ChaosBlacklistEgg { get; set; }
internal static ConfigEntry<bool> ChaosQueueAllowCapacitor { get; set; }
internal static ConfigEntry<bool> ChaosQueueAllowRecycler { get; set; }
internal static ConfigEntry<bool> ChaosQueueAllowTricorn { get; set; }
internal static ConfigEntry<bool> ChaosQueueAllowLunar { get; set; }
internal static ConfigEntry<bool> ChaosQueueAllowEgg { get; set; }
internal static ConfigEntry<bool> DontUseAprilFools { get; set; }
internal static ConfigEntry<bool> UseAprilFools { get; set; }
public static bool BindSection(string sectionName)
{
return CustomConfigFile.Bind<bool>("Bad Item Academy : Full Section Config", sectionName, true, "Vanilla is FALSE. Set to false if you wish to disable changes made to an entire item or group of items.").Value;
}
public static void Init()
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Expected O, but got Unknown
string text = "Bad Item Rehabilitation : ";
CustomConfigFile = new ConfigFile(Paths.ConfigPath + "\\BadItemRehabilitation.cfg", true);
CustomConfigFile.SaveOnConfigSet = false;
AegisConversionInterval = CustomConfigFile.Bind<float>(text + "Aegis", "Aegis Conversion to Fortification Interval", BadItemAcademyPlugin._AegisConversionInterval, "Determines the rate at which cumulated barrier decay is converted to Fortification. By default, this is made to be a fairly high value in order to reduce the performance cost of changing stats frequently. However, the Force Conversion Threshold makes sure that Fortification is not added too slowly for the changing stats.");
AegisConversionRate = CustomConfigFile.Bind<float>(text + "Aegis", "Aegis Rate Of Conversion To Fortification", BadItemAcademyPlugin._AegisConversionRate, "Determines the multiplier of barrier converted to Fortification. For example, with a value of 0.5, 100% barrier decay only gives 50% Fortification. ");
AegisRemovalRate = CustomConfigFile.Bind<float>(text + "Aegis", "Aegis Rate Of Conversion To Fortification", BadItemAcademyPlugin._AegisRemovalRate, "Determines the multiplier of Fortification removal when taking damage, proportional to maximum health. For example, with a value of 2, losing 50% of your max health will take away 100% Fortification. ");
AegisForceConversionThreshold = CustomConfigFile.Bind<float>(text + "Aegis", "Aegis Force Conversion To Fortification Threshold", BadItemAcademyPlugin._AegisForceConversionThreshold, "Determines the threshold at which cumulated barrier decay is forced to be converted to Fortification, bypassing the cooldown and adding all cumulated barrier to Fortification instantly. This is shown in the item's full description as the minimum value to convert to Fortification. ");
AegisMaxFortificationStacks = CustomConfigFile.Bind<int>(text + "Aegis", "Aegis Max Fortification Stacks", BadItemAcademyPlugin._AegisMaxFortificationStacks, "Determines the maximum stacks of Fortification required for the full bonus. ");
AegisMaxStatBonusBase = CustomConfigFile.Bind<float>(text + "Aegis", "Aegis Fortification Max Stat Bonus BASE", BadItemAcademyPlugin._AegisMaxStatBonusBase, "Determines the amount Aegis increases ALL STATS with full Fortification with your first stack of Aegis. Scales linearly, represented as a percent. ");
AegisMaxStatBonusStack = CustomConfigFile.Bind<float>(text + "Aegis", "Aegis Fortification Max Stat Bonus PER STACK", BadItemAcademyPlugin._AegisMaxStatBonusStack, "Determines the amount Aegis increases ALL STATS with full Fortification with additional stacks of Aegis. Scales linearly, represented as a percent. ");
AegisRevertHealingReduction = CustomConfigFile.Bind<bool>(text + "Aegis", "Should Aegis Revert Healing Reductions When Converting To Barrier?", BadItemAcademyPlugin._AegisRevertHealingReduction, "Vanilla is FALSE. If set to TRUE, Aegis will revert any healing cuts made by modifiers like Eclipse 5 when applying overheal to barrier.");
AegisUseFortification = CustomConfigFile.Bind<bool>(text + "Aegis", "Should Aegis Use Fortification?", BadItemAcademyPlugin._AegisUseFortification, "Vanilla is FALSE. If set to TRUE, Aegis will turn all decayed barrier into a stat buff called Fortification. Fortification boosts ALL stats, but is reduced when taking damage by an amount proportional to your max health.");
ShouldBenthicWeighSelection = CustomConfigFile.Bind<bool>(text + "Benthic Bloom", "Should Benthic Bloom Weigh Selection?", BadItemAcademyPlugin._ShouldBenthicWeighSelection, "Vanilla is FALSE. If set to TRUE, Benthic Bloom will be biased towards selecting item stacks with higher lower values. Otherwise, it will prefer item stacks with higher values. Neither of these options resemble vanilla behavior, but you can choose to configure it anyways!");
InvertBenthicWeightedSelection = CustomConfigFile.Bind<bool>(text + "Benthic Bloom", "Invert Benthic Bloom Weighted Selection", BadItemAcademyPlugin._InvertBenthicWeightedSelection, "If set to TRUE, Benthic Bloom will be biased towards selecting item stacks with lower values. Otherwise, it will prefer item stacks with higher values. Neither of these options resemble vanilla behavior, so do what you want!");
BiasBenthicWeightedSelection = CustomConfigFile.Bind<bool>(text + "Benthic Bloom", "Bias Benthic Bloom Weighted Selection", BadItemAcademyPlugin._BiasBenthicWeightedSelection, "If set to TRUE, Benthic Bloom will try to maintain equal ratios of upgrades between Common and Uncommon items. Due to selection weighting, Benthic will more often pick Uncommon-to-Rare upgrades than Common-to-Uncommon due to Uncommon items being harder to stack. This config presents a choice, if you would like to make Benthic adjust its weighted selection to account for the size of your inventory or allow it to choose whatever it wants. Neither of these options resemble vanilla behavior, so do what you want!");
PoolHealingBeforeModifiers = CustomConfigFile.Bind<bool>(text + "NKuhanas Opinion", "Pool Healing Before Modifiers (Affects Corpsebloom)", BadItemAcademyPlugin._PoolHealingBeforeModifiers, "Vanilla is FALSE. If set to TRUE, Nkuhanas Opinion and Corpsebloom will be changed to pool their healing before other healing modifiers. In Corpsebloom's case, this removes the double dipping effect with Rejuvenation Rack and Eclipse 5.");
PoolHealingAfterIncrease = CustomConfigFile.Bind<bool>(text + "NKuhanas Opinion", "Pool Healing After Increase (Affects Corpsebloom)", BadItemAcademyPlugin._PoolHealingAfterIncrease, "(Requires Pool Healing Before Modifiers to be TRUE) If set to TRUE, Nkuhanas Opinion and Corpsebloom will be changed to pool after Rejuvenation Rack is applied, but before Eclipse 5. ");
ChangeNkuhanaHealthCalculation = CustomConfigFile.Bind<bool>(text + "NKuhanas Opinion", "Change NKuhana Base Damage Calculation", BadItemAcademyPlugin._ChangeNkuhanaHealthCalculation, "Vanilla is FALSE. If set to TRUE, Nkuhanas Opinion will calculate the base damage of its attacks by using your survivor's base health (scaled with level) rather than max health. ");
NkuhanaDamageMultiplier = CustomConfigFile.Bind<float>(text + "NKuhanas Opinion", "NKuhanas Damage Coefficient", BadItemAcademyPlugin._NkuhanaDamageMultiplier, "Vanilla is 2.5. Determines the damage multiplier of skulls fired by healing with NKuhanas Opinion. Represented as a percent. ");
NkuhanaProcCoefficient = CustomConfigFile.Bind<float>(text + "NKuhanas Opinion", "NKuhanas Proc Coefficient", BadItemAcademyPlugin._NkuhanaProcCoefficient, "Vanilla is 0.2. Determines the proc effectivness of skulls fired by healing with NKuhanas Opinion. ");
NkuhanaMaxRange = CustomConfigFile.Bind<float>(text + "NKuhanas Opinion", "NKuhanas Max Range", BadItemAcademyPlugin._NkuhanaMaxRange, "Vanilla is 40. Determines the maximum range of skulls fired by healing with NKuhanas Opinion. Represented in meters.");
VoidBandDamageMult = CustomConfigFile.Bind<float>(text + "Singularity Band", "Void Band Damage Coefficient", BadItemAcademyPlugin._VoidBandDamageMult, "Vanilla is 1. Determines the damage multiplier of the explosion from the black hole created by Singularity Band. Scales linearly, represented as a percent. ");
VoidBandProcCoeff = CustomConfigFile.Bind<float>(text + "Singularity Band", "Void Band Proc Coefficient", BadItemAcademyPlugin._VoidBandProcCoeff, "Vanilla is 1. Determines the proc effectiveness of the explosion from the black hole created by Singularity Band.");
ChaosBonusBase = CustomConfigFile.Bind<int>(text + "Bottled Chaos", "Bottled Chaos Bonus Activations (Base)", BadItemAcademyPlugin._ChaosBonusBase, "Vanilla is 1. Determines the amount of random equipments to be activated with one stack of Bottled Chaos. Note that this value can be less than or higher than the number of equipments displayed by BIRs Bottled Chaos Queue-Widget.");
ChaosBonusStack = CustomConfigFile.Bind<int>(text + "Bottled Chaos", "Bottled Chaos Bonus Activations (Stack)", BadItemAcademyPlugin._ChaosBonusStack, "Vanilla is 1. Determines the amount of random equipments to be activated for each additional stack of Bottled Chaos. Note that this value can be less than or higher than the number of equipments displayed by BIRs Bottled Chaos Queue-Widget.");
ChaosWidgetCount = CustomConfigFile.Bind<int>(text + "Bottled Chaos", "Bottled Chaos Queue Display Count", BadItemAcademyPlugin._ChaosWidgetCount, "Vanilla is 0. Determines the amount of random equipments to be displayed above the equipment slot while Bottled Chaos is held. If the activation count is smaller than this number, the widget will behave as a queue, with equipments to the right being used after. If the activation count is higher than this number, or if the displayed equipment cannot be activated, additional random equipments will be triggered in order to fulfill the activation count. Note that the Widget is allowed to choose ALL equipments that can be triggered at random, as well as some equipments that cannot be triggered at random, such as Recycler.");
ChaosBlacklistEgg = CustomConfigFile.Bind<bool>(text + "Bottled Chaos : Random Activation Pool", "Allow Random Activations Of Volcanic Egg?", BadItemAcademyPlugin._ChaosBlacklistEgg, "Vanilla is FALSE. If set to TRUE, the equipment Volcanic Egg will not be allowed to activate at random.Note that the Widget may be allowed to choose Volcanic Egg unless the relevant setting is changed.");
ChaosQueueAllowLunar = CustomConfigFile.Bind<bool>(text + "Bottled Chaos : Queued Activation Pool", "Allow Queued Activations Of Lunar Equipments?", BadItemAcademyPlugin._ChaosQueueAllowLunar, "Vanilla is FALSE. If set to TRUE, all Lunar-tier equipments in the Enigma Artifact pool will be added to the pool of equipments that can be chosen by the Bottled Chaos Queue-Widget.");
ChaosQueueAllowEgg = CustomConfigFile.Bind<bool>(text + "Bottled Chaos : Queued Activation Pool", "Allow Queued Activations Of Volcanic Egg?", BadItemAcademyPlugin._ChaosQueueAllowEgg, "Vanilla is TRUE. If the equipment Volcanic Egg is disallowed from random activations, this setting controls whether it will continue to appear via the Bottled Chaos Queue-Widget. Set both to FALSE if you wish for Volcanic Egg to be eradicated from existence.");
ChaosQueueAllowRecycler = CustomConfigFile.Bind<bool>(text + "Bottled Chaos : Queued Activation Pool", "Allow Queued Activations Of Recycler?", BadItemAcademyPlugin._ChaosQueueAllowRecycler, "Vanilla is FALSE. If set to TRUE, the equipment Recycler will be added to the pool of equipments that can be chosen by the Bottled Chaos Queue-Widget.");
ChaosQueueAllowTricorn = CustomConfigFile.Bind<bool>(text + "Bottled Chaos : Queued Activation Pool", "Allow Queued Activations Of Trophy Hunters Tricorn?", BadItemAcademyPlugin._ChaosQueueAllowTricorn, "Vanilla is FALSE. If set to TRUE, the equipment Trophy Hunters Tricorn will be added to the pool of equipments that can be chosen by the Bottled Chaos Queue-Widget.");
AprilFools = DateTime.Now.Month == 4 && DateTime.Now.Day <= 7;
if (!AprilFools)
{
UseAprilFools = CustomConfigFile.Bind<bool>("April Fools", "Use April Fools", false, "Use April Fools' Day changes on days that are not April Fools' Day");
AprilFools = UseAprilFools.Value;
}
else
{
DontUseAprilFools = CustomConfigFile.Bind<bool>("April Fools", "Dont Use April Fools", false, "Dont use April Fools Day changes on days that are April Fools Day");
AprilFools = !DontUseAprilFools.Value;
}
}
public static void Save()
{
CustomConfigFile.SaveOnConfigSet = true;
CustomConfigFile.Save();
}
}
}
namespace BadItemAcademy.Components
{
public class BottleChaosBodyAttachment : NetworkBehaviour
{
public SyncListInt nextEquipments;
private CharacterBody _attachedBody;
public int cachedActivationCount;
public int cachedGestureCount;
private static int kListnextEquipments;
public CharacterBody attachedBody
{
get
{
return _attachedBody;
}
set
{
if ((Object)(object)attachedBody != (Object)(object)value)
{
Inventory.onInventoryChangedGlobal -= OnInventoryChangedGlobal;
}
_attachedBody = value;
if ((Object)(object)attachedBody != (Object)null && (Object)(object)attachedBody.inventory != (Object)null)
{
Inventory.onInventoryChangedGlobal += OnInventoryChangedGlobal;
RecalculateEquipmentFireCounts();
}
}
}
private void OnInventoryChangedGlobal(Inventory inv)
{
if (!((Object)(object)attachedBody == (Object)null) && !((Object)(object)inv.characterBody != (Object)(object)attachedBody))
{
RecalculateEquipmentFireCounts();
}
}
private void RecalculateEquipmentFireCounts()
{
if ((Object)(object)attachedBody == (Object)null)
{
return;
}
Inventory inventory = attachedBody.inventory;
if (!((Object)(object)inventory == (Object)null))
{
int bhaosActivationCountFromBhaosStacks = BadItemAcademyPlugin.GetBhaosActivationCountFromBhaosStacks(inventory.GetItemCountEffective(Items.RandomEquipmentTrigger));
if (cachedActivationCount != bhaosActivationCountFromBhaosStacks)
{
BottleChaosWidget.RefreshAll();
}
cachedActivationCount = bhaosActivationCountFromBhaosStacks;
cachedGestureCount = inventory.GetItemCountEffective(Items.AutoCastEquipment);
}
}
public void Awake()
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Expected O, but got Unknown
nextEquipments = new SyncListInt();
for (int i = 0; i < BadItemAcademyPlugin.ChaosWidgetCountFinal; i++)
{
((SyncList<int>)(object)nextEquipments).Add(0);
}
((SyncList<int>)(object)nextEquipments).InitializeBehaviour((NetworkBehaviour)(object)this, kListnextEquipments);
}
public void OnEnable()
{
RecalculateEquipmentFireCounts();
UpdateNextEquipmentDef(updateAll: true);
}
public void OnDisable()
{
UpdateNextEquipmentDef();
attachedBody = null;
Inventory.onInventoryChangedGlobal -= OnInventoryChangedGlobal;
}
public EquipmentIndex GetRandomEquipment(Xoroshiro128Plus rng, int offset)
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
List<EquipmentIndex> validEquipments = new List<EquipmentIndex>(BadItemAcademyPlugin.bottledChaosWidgetValidEquipment);
if (validEquipments == null)
{
return (EquipmentIndex)(-1);
}
TryRemove(attachedBody.equipmentSlot.equipmentIndex);
foreach (int item in (SyncList<int>)(object)nextEquipments)
{
TryRemove((EquipmentIndex)item);
}
if (validEquipments.Count == 0)
{
return (EquipmentIndex)(-1);
}
int count = validEquipments.Count;
int num = rng.RangeInt(0, count);
num += offset;
num %= count;
return validEquipments[num];
void TryRemove(EquipmentIndex index)
{
//IL_0007: 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)
if (validEquipments.Contains(index))
{
validEquipments.Remove(index);
}
}
}
public void UpdateNextEquipmentDef(bool updateAll = false)
{
//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Expected I4, but got Unknown
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00c6: Expected I4, but got Unknown
if (cachedActivationCount == 0 || nextEquipments == null || ((SyncList<int>)(object)nextEquipments).Count <= 0)
{
BottleChaosWidget.RefreshAll();
return;
}
for (int i = 0; i < ((SyncList<int>)(object)nextEquipments).Count; i++)
{
if (!updateAll && i + cachedActivationCount < ((SyncList<int>)(object)nextEquipments).Count && ((SyncList<int>)(object)nextEquipments)[i + cachedActivationCount] != -1)
{
((SyncList<int>)(object)nextEquipments)[i] = ((SyncList<int>)(object)nextEquipments)[i + cachedActivationCount];
continue;
}
EquipmentIndex randomEquipment = GetRandomEquipment(BadItemAcademyPlugin.globalBottledChaosEquipmentRng, i + attachedBody.bodyIndex);
((SyncList<int>)(object)nextEquipments)[i] = (int)randomEquipment;
}
BottleChaosWidget.RefreshAll();
}
private void LateUpdate()
{
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Invalid comparison between I4 and Unknown
if ((Object)(object)((Component)this).transform.GetParent() == (Object)null)
{
return;
}
EquipmentSlot equipmentSlot = attachedBody.equipmentSlot;
if (!Object.op_Implicit((Object)(object)equipmentSlot))
{
return;
}
for (int i = 0; i < cachedActivationCount && i < ((SyncList<int>)(object)nextEquipments).Count; i++)
{
if (equipmentSlot.targetIndicator.active)
{
break;
}
if ((Object)(object)equipmentSlot.currentTarget.transformToIndicateAt != (Object)null)
{
break;
}
if (((SyncList<int>)(object)nextEquipments)[i] != (int)equipmentSlot.equipmentIndex)
{
equipmentSlot.UpdateTargets((EquipmentIndex)((SyncList<int>)(object)nextEquipments)[i], equipmentSlot.stock + cachedGestureCount > 0);
}
}
}
public BottleChaosBodyAttachment()
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Expected O, but got Unknown
nextEquipments = new SyncListInt();
}
private void UNetVersion()
{
}
protected static void InvokeSyncListnextEquipments(NetworkBehaviour obj, NetworkReader reader)
{
if (!NetworkClient.active)
{
Debug.LogError((object)"SyncList nextEquipments called on server.");
}
else
{
((SyncList<int>)(object)((BottleChaosBodyAttachment)(object)obj).nextEquipments).HandleMsg(reader);
}
}
static BottleChaosBodyAttachment()
{
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Expected O, but got Unknown
kListnextEquipments = -1870331271;
NetworkBehaviour.RegisterSyncListDelegate(typeof(BottleChaosBodyAttachment), kListnextEquipments, new CmdDelegate(InvokeSyncListnextEquipments));
NetworkCRC.RegisterBehaviour("BottleChaosBodyAttachment", 0);
}
public override bool OnSerialize(NetworkWriter writer, bool forceAll)
{
if (forceAll)
{
SyncListInt.WriteInstance(writer, nextEquipments);
return true;
}
bool flag = false;
if ((((NetworkBehaviour)this).syncVarDirtyBits & (true ? 1u : 0u)) != 0)
{
if (!flag)
{
writer.WritePackedUInt32(((NetworkBehaviour)this).syncVarDirtyBits);
flag = true;
}
SyncListInt.WriteInstance(writer, nextEquipments);
}
if (!flag)
{
writer.WritePackedUInt32(((NetworkBehaviour)this).syncVarDirtyBits);
}
return flag;
}
public override void OnDeserialize(NetworkReader reader, bool initialState)
{
if (initialState)
{
SyncListInt.ReadReference(reader, nextEquipments);
return;
}
int num = (int)reader.ReadPackedUInt32();
if (((uint)num & (true ? 1u : 0u)) != 0)
{
SyncListInt.ReadReference(reader, nextEquipments);
}
}
}
public class BottleChaosWidget : MonoBehaviour
{
private class EquipmentIconSlot
{
public GameObject gameObject;
public CanvasGroup canvasGroup;
public Image image;
public void UpdateIcon(EquipmentDef def)
{
if (Object.op_Implicit((Object)(object)image))
{
image.sprite = def.pickupIconSprite;
}
}
}
private const float bgIconValue = 0.3f;
private const float bgIconAlpha = 0.8f;
private static float bgIconScale = 108f;
private const float iconScale = 48f;
private const float iconSpacing = 12f;
private static Sprite _bgSprite;
private static List<BottleChaosWidget> instancesList = new List<BottleChaosWidget>();
public static ReadOnlyCollection<BottleChaosWidget> readOnlyInstancesList = new ReadOnlyCollection<BottleChaosWidget>(instancesList);
private CharacterBody cachedBody = null;
private BodyIndex cachedBodyIndex = (BodyIndex)(-1);
private int cachedChaosCount = int.MinValue;
private HUD _sourceHud;
private EquipmentIconSlot[] iconSlots;
internal static Sprite bgSprite
{
get
{
//IL_0017: 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)
if (!Object.op_Implicit((Object)(object)_bgSprite))
{
_bgSprite = Addressables.LoadAssetAsync<Sprite>((object)RoR2_DLC1_RandomEquipmentTrigger.texBottledChaosIcon_png).WaitForCompletion();
}
return _bgSprite;
}
}
public static void RefreshAll()
{
if (readOnlyInstancesList == null || readOnlyInstancesList.Count == 0)
{
return;
}
foreach (BottleChaosWidget readOnlyInstances in readOnlyInstancesList)
{
readOnlyInstances.UpdateDisplay();
}
}
private void Awake()
{
//IL_0034: 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_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Expected O, but got Unknown
//IL_0104: Unknown result type (might be due to invalid IL or missing references)
instancesList.Add(this);
iconSlots = new EquipmentIconSlot[BadItemAcademyPlugin.ChaosWidgetCountFinal];
RectTransform val = ((Component)this).gameObject.AddComponent<RectTransform>();
val.anchorMin = new Vector2(1f, 0f);
val.anchorMax = new Vector2(1f, 0f);
val.pivot = new Vector2(1f, 0f);
val.anchoredPosition = new Vector2(-80f, 180f);
val.sizeDelta = new Vector2(bgIconScale, bgIconScale);
HorizontalLayoutGroup val2 = ((Component)this).gameObject.AddComponent<HorizontalLayoutGroup>();
((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = false;
((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = false;
((HorizontalOrVerticalLayoutGroup)val2).spacing = 12f;
((LayoutGroup)val2).childAlignment = (TextAnchor)4;
((LayoutGroup)val2).padding = new RectOffset(0, 0, 0, 0);
Image val3 = ((Component)this).gameObject.AddComponent<Image>();
val3.sprite = bgSprite;
((Graphic)val3).color = new Color(0.3f, 0.3f, 0.3f, 0.8f);
for (int i = 0; i < iconSlots.Length; i++)
{
iconSlots[i] = CreateEquipmentIconSlot(i, ((Component)this).transform);
}
}
private void OnDestroy()
{
instancesList.Remove(this);
}
private static EquipmentIconSlot CreateEquipmentIconSlot(int index, Transform parentContainer)
{
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Expected O, but got Unknown
//IL_004b: 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_0061: Unknown result type (might be due to invalid IL or missing references)
GameObject val = new GameObject("EquipmentIconSlot_" + index);
val.transform.SetParent(parentContainer);
val.SetActive(true);
CanvasGroup canvasGroup = val.AddComponent<CanvasGroup>();
Image val2 = val.AddComponent<Image>();
val2.sprite = null;
RectTransform component = val.GetComponent<RectTransform>();
component.sizeDelta = Vector2.one * 48f;
((Transform)component).localScale = Vector3.one;
return new EquipmentIconSlot
{
gameObject = val,
canvasGroup = canvasGroup,
image = val2
};
}
public void UpdateDisplay()
{
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
bool refreshed = false;
if (Object.op_Implicit((Object)(object)_sourceHud))
{
if ((Object)(object)cachedBody == (Object)null || (Object)(object)_sourceHud.targetBodyObject != (Object)(object)((Component)cachedBody).gameObject)
{
RefreshCachedBody();
}
if (!refreshed && cachedBody.bodyIndex != cachedBodyIndex)
{
RefreshCachedBody();
}
}
else
{
RefreshCachedBody();
}
cachedChaosCount = (((Object)(object)cachedBody != (Object)null && (Object)(object)cachedBody.inventory != (Object)null) ? cachedBody.inventory.GetItemCountEffective(Items.RandomEquipmentTrigger) : 0);
if (cachedChaosCount == 0)
{
((Component)this).gameObject.SetActive(false);
return;
}
((Component)this).gameObject.SetActive(true);
BottleChaosItemBehavior component = ((Component)cachedBody).GetComponent<BottleChaosItemBehavior>();
if ((Object)(object)component == (Object)null)
{
return;
}
BottleChaosBodyAttachment bodyAttachmentComponent = component.bodyAttachmentComponent;
if ((Object)(object)bodyAttachmentComponent == (Object)null)
{
Debug.LogError((object)"BIA: Bottled Chaos Body Attachment not found when refreshing HUD!");
return;
}
for (int i = 0; i < iconSlots.Length && i < ((SyncList<int>)(object)component.bodyAttachmentComponent.nextEquipments).Count; i++)
{
EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)((SyncList<int>)(object)component.bodyAttachmentComponent.nextEquipments)[i]);
iconSlots[i].UpdateIcon(equipmentDef);
}
void RefreshCachedBody()
{
//IL_0062: 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_0050: Unknown result type (might be due to invalid IL or missing references)
refreshed = true;
if (Object.op_Implicit((Object)(object)_sourceHud) && (Object)(object)_sourceHud.targetBodyObject != (Object)null)
{
cachedBody = _sourceHud.targetBodyObject.GetComponent<CharacterBody>();
cachedBodyIndex = cachedBody.bodyIndex;
}
else
{
cachedBody = null;
cachedBodyIndex = (BodyIndex)(-1);
}
}
}
internal void Initialize(HUD hud)
{
UpdateDisplay();
_sourceHud = hud;
}
}
}