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 DrifterBossGrab v1.7.2
plugins/com.pwdcat.DrifterBossGrab.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DrifterBossGrabMod.Balance; using DrifterBossGrabMod.Config; using DrifterBossGrabMod.Config.UI; using DrifterBossGrabMod.Core; using DrifterBossGrabMod.Features; using DrifterBossGrabMod.Input; using DrifterBossGrabMod.Interfaces; using DrifterBossGrabMod.Networking; using DrifterBossGrabMod.Patches; using DrifterBossGrabMod.UI; using EntityStates; using EntityStates.CaptainSupplyDrop; using EntityStates.Drifter; using EntityStates.Drifter.Bag; using EntityStates.SurvivorPod; using HarmonyLib; using KinematicCharacterController; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using Rewired; using Rewired.Data; using Rewired.Data.Mapping; using RiskOfOptions; using RiskOfOptions.Components.Options; using RiskOfOptions.Components.Panel; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RoR2; using RoR2.HudOverlay; using RoR2.Networking; using RoR2.Projectile; using RoR2.Skills; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Rewired_Core")] [assembly: IgnoresAccessChecksTo("RoR2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.pwdcat.DrifterBossGrab")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.7.2.0")] [assembly: AssemblyInformationalVersion("1.7.2")] [assembly: AssemblyProduct("com.pwdcat.DrifterBossGrab")] [assembly: AssemblyTitle("DrifterBossGrabMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.7.2.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace BepInEx { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class BepInAutoPluginAttribute : Attribute { public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace BepInEx.Preloader.Core.Patching { [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)] [Conditional("CodeGeneration")] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace DrifterBossGrabMod { public static class ConfigChangeNotifier { private static readonly List<IConfigObserver> observers = new List<IConfigObserver>(); private static readonly EventHandler configChangedHandler = OnConfigChanged; public static void AddObserver(IConfigObserver observer) { observers.Add(observer); } public static void RemoveObserver(IConfigObserver observer) { observers.Remove(observer); } private static void OnConfigChanged(object sender, EventArgs e) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown ConfigEntryBase val = (ConfigEntryBase)sender; NotifyObservers(val.Definition.Key, val.BoxedValue); } private static void NotifyObservers(string key, object value) { foreach (IConfigObserver observer in observers) { observer.OnConfigChanged(key, value); } } public static void Init() { PluginConfig.Instance.BreakoutTimeMultiplier.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableBossGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableNPCGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableEnvironmentGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableLockedObjectGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.ProjectileGrabbingMode.SettingChanged += configChangedHandler; PluginConfig.Instance.MaxSmacks.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableDebugLogs.SettingChanged += configChangedHandler; PluginConfig.Instance.BodyBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.RecoveryObjectBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.GrabbableComponentTypes.SettingChanged += configChangedHandler; PluginConfig.Instance.GrabbableKeywordBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableObjectPersistence.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableAutoGrab.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistBaggedBosses.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistBaggedNPCs.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistBaggedEnvironmentObjects.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistenceBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.BottomlessBagEnabled.SettingChanged += configChangedHandler; PluginConfig.Instance.AddedCapacity.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableMouseWheelScrolling.SettingChanged += configChangedHandler; PluginConfig.Instance.CarouselSpacing.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotScale.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotOpacity.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotScale.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotOpacity.SettingChanged += configChangedHandler; } public static void Cleanup() { PluginConfig.Instance.BreakoutTimeMultiplier.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableBossGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableNPCGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableEnvironmentGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableLockedObjectGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.ProjectileGrabbingMode.SettingChanged -= configChangedHandler; PluginConfig.Instance.MaxSmacks.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableDebugLogs.SettingChanged -= configChangedHandler; PluginConfig.Instance.BodyBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.RecoveryObjectBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.GrabbableComponentTypes.SettingChanged -= configChangedHandler; PluginConfig.Instance.GrabbableKeywordBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableObjectPersistence.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableAutoGrab.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistBaggedBosses.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistBaggedNPCs.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistBaggedEnvironmentObjects.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistenceBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.BottomlessBagEnabled.SettingChanged -= configChangedHandler; PluginConfig.Instance.AddedCapacity.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableMouseWheelScrolling.SettingChanged -= configChangedHandler; PluginConfig.Instance.CarouselSpacing.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotScale.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotOpacity.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotScale.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotOpacity.SettingChanged -= configChangedHandler; } } public class ConfigurationComposite : IConfigurable { private readonly List<IConfigurable> _components = new List<IConfigurable>(); public void AddComponent(IConfigurable component) { if (component == null) { throw new ArgumentNullException("component"); } _components.Add(component); } public bool RemoveComponent(IConfigurable component) { return _components.Remove(component); } public IReadOnlyCollection<IConfigurable> GetComponents() { return _components.AsReadOnly(); } public void Initialize() { foreach (IConfigurable component in _components) { try { component.Initialize(); } catch (Exception ex) { Log.Error("Failed to initialize component " + component.GetType().Name + ": " + ex.Message); } } } public void Cleanup() { foreach (IConfigurable component in _components) { try { component.Cleanup(); } catch (Exception ex) { Log.Error("Failed to cleanup component " + component.GetType().Name + ": " + ex.Message); } } _components.Clear(); } } public enum ProjectileGrabbingMode { None, SurvivorOnly, AllProjectiles } public enum WeightDisplayMode { None, Multiplier, Pounds, KiloGrams } public enum StateCalculationMode { Current, All } public enum AoEDamageMode { None, Full, Split } public enum CharacterFlagType { All, Elite, Boss, Champion, Player, Minion, Drone, Mechanical, Void } public enum HudElementType { All, SelectedSlot, AdjacentSlot, WeightDisplay, DamagePreview, CapacityUI, BaggedObjectInfo } public enum BalanceSubTabType { All, Capacity, TagScaling, Penalty, Other } public enum PresetType { Vanilla, Intended, Minimal, Default, Balance, Hardcore, Caveman, Custom } public interface ICachedValue<T> { T Value { get; } void Invalidate(); } public class LazyCachedValue<T> : ICachedValue<T> { private readonly Func<T> _factory; private T? _value; private bool _isValid; private readonly object _lock = new object(); public T Value { get { lock (_lock) { if (!_isValid) { _value = _factory(); _isValid = true; } return _value; } } } public void Invalidate() { lock (_lock) { _isValid = false; _value = default(T); } } public LazyCachedValue(Func<T> factory) { _factory = factory ?? throw new ArgumentNullException("factory"); } } public enum ComponentChooserDummy { SelectToToggle } public enum ComponentChooserSortMode { ByFrequency, ByProximity, ByRaycast } public class PluginConfig { private static PluginConfig _instance = null; public static readonly Dictionary<string, HudElementType[]> HudSettingToSubTab = new Dictionary<string, HudElementType[]> { ["PWDCAT.DRIFTERBOSSGRAB.HUD.SELECTEDHUDELEMENT.CHOICE"] = new HudElementType[7] { HudElementType.All, HudElementType.SelectedSlot, HudElementType.AdjacentSlot, HudElementType.WeightDisplay, HudElementType.DamagePreview, HudElementType.CapacityUI, HudElementType.BaggedObjectInfo }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLECAROUSELHUD.CHECKBOX"] = new HudElementType[2] { HudElementType.SelectedSlot, HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CAROUSELSPACING.FLOAT_FIELD"] = new HudElementType[2] { HudElementType.SelectedSlot, HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CAROUSELANIMATIONDURATION.FLOAT_FIELD"] = new HudElementType[2] { HudElementType.SelectedSlot, HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTX.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTSCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTOPACITY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTSHOWICON.CHECKBOX"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTSHOWWEIGHTICON.CHECKBOX"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTSHOWNAME.CHECKBOX"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTSHOWHEALTHBAR.CHECKBOX"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CENTERSLOTSHOWSLOTNUMBER.CHECKBOX"] = new HudElementType[1] { HudElementType.SelectedSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTX.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTSCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTOPACITY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTSHOWICON.CHECKBOX"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTSHOWWEIGHTICON.CHECKBOX"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTSHOWNAME.CHECKBOX"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTSHOWHEALTHBAR.CHECKBOX"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SIDESLOTSHOWSLOTNUMBER.CHECKBOX"] = new HudElementType[1] { HudElementType.AdjacentSlot }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.USENEWWEIGHTICON.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightDisplay }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.WEIGHTDISPLAYMODE.CHOICE"] = new HudElementType[1] { HudElementType.WeightDisplay }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SCALEWEIGHTCOLOR.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightDisplay }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SHOWTOTALMASSONWEIGHTICON.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightDisplay }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.SHOWOLDWEIGHTICONOVERNEW.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightDisplay }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLEMASSCAPACITYUI.CHECKBOX"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.MASSCAPACITYUIPOSITIONX.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.MASSCAPACITYUIPOSITIONY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.MASSCAPACITYUISCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLESEPARATORS.CHECKBOX"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.GRADIENTINTENSITY.STEP_SLIDER"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CAPACITYGRADIENTCOLORSTART.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CAPACITYGRADIENTCOLORMID.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.CAPACITYGRADIENTCOLOREND.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.OVERENCUMBRANCEGRADIENTCOLORSTART.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.OVERENCUMBRANCEGRADIENTCOLORMID.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.OVERENCUMBRANCEGRADIENTCOLOREND.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLEDAMAGEPREVIEW.CHECKBOX"] = new HudElementType[1] { HudElementType.DamagePreview }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.DAMAGEPREVIEWCOLOR.COLOR"] = new HudElementType[1] { HudElementType.DamagePreview }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLEBAGGEDOBJECTINFO.CHECKBOX"] = new HudElementType[1] { HudElementType.BaggedObjectInfo }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.BAGGEDOBJECTINFOX.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.BaggedObjectInfo }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.BAGGEDOBJECTINFOY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.BaggedObjectInfo }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.BAGGEDOBJECTINFOSCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.BaggedObjectInfo }, ["PWDCAT.DRIFTERBOSSGRAB.HUD.BAGGEDOBJECTINFOCOLOR.COLOR"] = new HudElementType[1] { HudElementType.BaggedObjectInfo } }; public static readonly Dictionary<string, BalanceSubTabType> BalanceSettingToSubTab = new Dictionary<string, BalanceSubTabType> { ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.ENABLEBALANCE.CHECKBOX"] = BalanceSubTabType.Capacity, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.UNCAPCAPACITY.CHECKBOX"] = BalanceSubTabType.Capacity, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.SLOTSCALINGFORMULA.STRING_INPUT_FIELD"] = BalanceSubTabType.Capacity, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.MASSCAPACITYFORMULA.STRING_INPUT_FIELD"] = BalanceSubTabType.Capacity, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.SELECTEDFLAG.CHOICE"] = BalanceSubTabType.TagScaling, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.FLAGMULTIPLIER.STRING_INPUT_FIELD"] = BalanceSubTabType.TagScaling, ["PWDCAT.DRIFTERBOSSGRAB.CHARACTER_FLAGS.ALL_FLAG_MULTIPLIER.STRING_INPUT_FIELD"] = BalanceSubTabType.TagScaling, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.OVERENCUMBRANCEMAX.FLOAT_FIELD"] = BalanceSubTabType.Penalty, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.STATECALCULATIONMODE.CHOICE"] = BalanceSubTabType.Penalty, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.MASSMULTIPLIERFORMULA.STRING_INPUT_FIELD"] = BalanceSubTabType.Penalty, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.MOVESPEEDPENALTYFORMULA.STRING_INPUT_FIELD"] = BalanceSubTabType.Penalty, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.BAGSCALECAP.STRING_INPUT_FIELD"] = BalanceSubTabType.Other, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.MASSCAP.STRING_INPUT_FIELD"] = BalanceSubTabType.Other, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.AOEDAMAGEDISTRIBUTION.CHOICE"] = BalanceSubTabType.Other, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.SEARCHRADIUSMULTIPLIER.STEP_SLIDER"] = BalanceSubTabType.Other, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.BREAKOUTTIMEMULTIPLIER.STEP_SLIDER"] = BalanceSubTabType.Other, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.MAXSMACKS.INT_SLIDER"] = BalanceSubTabType.Other, ["PWDCAT.DRIFTERBOSSGRAB.BALANCE.MAXLAUNCHSPEED.STRING_INPUT_FIELD"] = BalanceSubTabType.Other }; internal ICachedValue<HashSet<string>> _blacklistCache; internal ICachedValue<HashSet<string>> _blacklistCacheWithClones; internal ICachedValue<HashSet<string>> _recoveryBlacklistCache; internal ICachedValue<HashSet<string>> _recoveryBlacklistCacheWithClones; internal ICachedValue<HashSet<string>> _grabbableComponentTypesCache; internal ICachedValue<HashSet<string>> _grabbableKeywordBlacklistCache; private readonly List<IGrabbingStrategy> _grabbingStrategies = new List<IGrabbingStrategy> { new BossGrabbingStrategy(), new NPCGrabbingStrategy(), new EnvironmentGrabbingStrategy() }; public static PluginConfig Instance => _instance ?? (_instance = new PluginConfig()); public ConfigEntry<bool> EnableBossGrabbing { get; private set; } public ConfigEntry<bool> EnableNPCGrabbing { get; private set; } public ConfigEntry<bool> EnableEnvironmentGrabbing { get; private set; } public ConfigEntry<bool> EnableLockedObjectGrabbing { get; private set; } public ConfigEntry<ProjectileGrabbingMode> ProjectileGrabbingMode { get; private set; } public ConfigEntry<string> BodyBlacklist { get; private set; } public ConfigEntry<string> RecoveryObjectBlacklist { get; private set; } public ConfigEntry<string> GrabbableComponentTypes { get; private set; } public ConfigEntry<string> GrabbableKeywordBlacklist { get; private set; } public ConfigEntry<float> SearchRadiusMultiplier { get; private set; } public ConfigEntry<bool> EnableDebugLogs { get; private set; } public ConfigEntry<ComponentChooserSortMode> ComponentChooserSortModeEntry { get; private set; } public ConfigEntry<ComponentChooserDummy> ComponentChooserDummyEntry { get; private set; } public ConfigEntry<bool> EnableConfigSync { get; private set; } public ConfigEntry<PresetType> SelectedPreset { get; private set; } public ConfigEntry<PresetType> LastSelectedPreset { get; private set; } public ConfigEntry<bool> BottomlessBagEnabled { get; private set; } public ConfigEntry<string> AddedCapacity { get; private set; } public ConfigEntry<bool> EnableStockRefreshClamping { get; private set; } public ConfigEntry<bool> EnableSuccessiveGrabStockRefresh { get; private set; } public ConfigEntry<float> CycleCooldown { get; private set; } public ConfigEntry<bool> PlayAnimationOnCycle { get; private set; } public ConfigEntry<bool> EnableMouseWheelScrolling { get; private set; } public ConfigEntry<bool> InverseMouseWheelScrolling { get; private set; } public ConfigEntry<bool> AutoPromoteMainSeat { get; private set; } public ConfigEntry<bool> PrioritizeMainSeat { get; private set; } public ConfigEntry<bool> EnableObjectPersistence { get; private set; } public ConfigEntry<bool> EnableAutoGrab { get; private set; } public ConfigEntry<bool> PersistBaggedBosses { get; private set; } public ConfigEntry<bool> PersistBaggedNPCs { get; private set; } public ConfigEntry<bool> PersistBaggedEnvironmentObjects { get; private set; } public ConfigEntry<string> PersistenceBlacklist { get; private set; } public ConfigEntry<float> AutoGrabDelay { get; private set; } public ConfigEntry<bool> EnableCarouselHUD { get; private set; } public ConfigEntry<float> CarouselSpacing { get; private set; } public ConfigEntry<float> CarouselAnimationDuration { get; private set; } public ConfigEntry<HudElementType> SelectedHudElement { get; private set; } public ConfigEntry<float> CenterSlotX { get; private set; } public ConfigEntry<float> CenterSlotY { get; private set; } public ConfigEntry<float> CenterSlotScale { get; private set; } public ConfigEntry<float> CenterSlotOpacity { get; private set; } public ConfigEntry<bool> CenterSlotShowIcon { get; private set; } public ConfigEntry<bool> CenterSlotShowWeightIcon { get; private set; } public ConfigEntry<bool> CenterSlotShowName { get; private set; } public ConfigEntry<bool> CenterSlotShowHealthBar { get; private set; } public ConfigEntry<bool> CenterSlotShowSlotNumber { get; private set; } public ConfigEntry<float> SideSlotX { get; private set; } public ConfigEntry<float> SideSlotY { get; private set; } public ConfigEntry<float> SideSlotScale { get; private set; } public ConfigEntry<float> SideSlotOpacity { get; private set; } public ConfigEntry<bool> SideSlotShowIcon { get; private set; } public ConfigEntry<bool> SideSlotShowWeightIcon { get; private set; } public ConfigEntry<bool> SideSlotShowName { get; private set; } public ConfigEntry<bool> SideSlotShowHealthBar { get; private set; } public ConfigEntry<bool> SideSlotShowSlotNumber { get; private set; } public ConfigEntry<bool> EnableBaggedObjectInfo { get; private set; } public ConfigEntry<float> BaggedObjectInfoX { get; private set; } public ConfigEntry<float> BaggedObjectInfoY { get; private set; } public ConfigEntry<float> BaggedObjectInfoScale { get; private set; } public ConfigEntry<Color> BaggedObjectInfoColor { get; private set; } public ConfigEntry<bool> UseNewWeightIcon { get; private set; } public ConfigEntry<WeightDisplayMode> WeightDisplayMode { get; private set; } public ConfigEntry<bool> ScaleWeightColor { get; private set; } public ConfigEntry<bool> ShowTotalMassOnWeightIcon { get; private set; } public ConfigEntry<bool> ShowOverencumberIcon { get; private set; } public ConfigEntry<bool> EnableDamagePreview { get; private set; } public ConfigEntry<Color> DamagePreviewColor { get; private set; } public ConfigEntry<bool> EnableMassCapacityUI { get; private set; } public ConfigEntry<float> MassCapacityUIPositionX { get; private set; } public ConfigEntry<float> MassCapacityUIPositionY { get; private set; } public ConfigEntry<float> MassCapacityUIScale { get; private set; } public ConfigEntry<bool> EnableSeparators { get; private set; } public ConfigEntry<float> GradientIntensity { get; private set; } public ConfigEntry<Color> CapacityGradientColorStart { get; private set; } public ConfigEntry<Color> CapacityGradientColorMid { get; private set; } public ConfigEntry<Color> CapacityGradientColorEnd { get; private set; } public ConfigEntry<Color> OverencumbranceGradientColorStart { get; private set; } public ConfigEntry<Color> OverencumbranceGradientColorMid { get; private set; } public ConfigEntry<Color> OverencumbranceGradientColorEnd { get; private set; } public ConfigEntry<bool> EnableBalance { get; private set; } public ConfigEntry<AoEDamageMode> AoEDamageDistribution { get; private set; } public ConfigEntry<float> BreakoutTimeMultiplier { get; private set; } public ConfigEntry<int> MaxSmacks { get; private set; } public ConfigEntry<string> BagScaleCap { get; private set; } public ConfigEntry<string> MassCap { get; private set; } public ConfigEntry<string> MaxLaunchSpeed { get; private set; } public ConfigEntry<StateCalculationMode> StateCalculationMode { get; private set; } public ConfigEntry<float> OverencumbranceMax { get; private set; } public ConfigEntry<string> SlotScalingFormula { get; private set; } public ConfigEntry<string> MassCapacityFormula { get; private set; } public ConfigEntry<string> MovespeedPenaltyFormula { get; private set; } public ConfigEntry<string> EliteFlagMultiplier { get; private set; } public ConfigEntry<string> BossFlagMultiplier { get; private set; } public ConfigEntry<string> ChampionFlagMultiplier { get; private set; } public ConfigEntry<string> PlayerFlagMultiplier { get; private set; } public ConfigEntry<string> MinionFlagMultiplier { get; private set; } public ConfigEntry<string> DroneFlagMultiplier { get; private set; } public ConfigEntry<string> MechanicalFlagMultiplier { get; private set; } public ConfigEntry<string> VoidFlagMultiplier { get; private set; } public ConfigEntry<string> AllFlagMultiplier { get; private set; } public ConfigEntry<CharacterFlagType> SelectedFlag { get; private set; } public ConfigEntry<string> SelectedFlagMultiplier { get; private set; } public ConfigEntry<BalanceSubTabType> SelectedBalanceSubTab { get; private set; } public static bool IsBlacklisted(string? name) { if (string.IsNullOrEmpty(name)) { return false; } return Instance._blacklistCacheWithClones.Value.Contains(name); } public static bool IsRecoveryBlacklisted(string? name) { if (string.IsNullOrEmpty(name)) { return false; } return Instance._recoveryBlacklistCacheWithClones.Value.Contains(name); } public static bool IsKeywordBlacklisted(string? name) { if (string.IsNullOrEmpty(name)) { return false; } foreach (string item in Instance._grabbableKeywordBlacklistCache.Value) { if (name.Contains(item, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } public static bool IsGrabbable(GameObject? obj) { if ((Object)(object)obj == (Object)null) { return false; } if (IsKeywordBlacklisted(((Object)obj).name)) { return false; } if (IsBlacklisted(((Object)obj).name)) { return false; } bool flag = false; foreach (string item in Instance._grabbableComponentTypesCache.Value) { Component component = obj.GetComponent(item); if ((Object)(object)component != (Object)null) { flag = true; break; } } if (!flag) { return false; } foreach (IGrabbingStrategy grabbingStrategy in Instance._grabbingStrategies) { if (grabbingStrategy.CanGrab(obj)) { return true; } } return false; } public static void Init(ConfigFile cfg) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Expected O, but got Unknown //IL_07e6: Unknown result type (might be due to invalid IL or missing references) //IL_083e: Unknown result type (might be due to invalid IL or missing references) //IL_0a6e: Unknown result type (might be due to invalid IL or missing references) //IL_0aa6: Unknown result type (might be due to invalid IL or missing references) //IL_0ade: Unknown result type (might be due to invalid IL or missing references) //IL_0b16: Unknown result type (might be due to invalid IL or missing references) //IL_0b4e: Unknown result type (might be due to invalid IL or missing references) //IL_0b86: Unknown result type (might be due to invalid IL or missing references) //IL_0df2: Unknown result type (might be due to invalid IL or missing references) //IL_0e07: Unknown result type (might be due to invalid IL or missing references) //IL_0e11: Expected O, but got Unknown //IL_0e11: Expected O, but got Unknown Instance.BreakoutTimeMultiplier = cfg.Bind<float>("Balance", "BreakoutTimeMultiplier", 1f, "Multiplier for how long bagged enemies take to break out.\nFormula: FinalBreakoutTime = BaseBreakoutTime × BreakoutTimeMultiplier"); Instance.MaxSmacks = cfg.Bind<int>("Balance", "MaxSmacks", 3, new ConfigDescription("Maximum number of hits before bagged enemies break out.\nBagged enemies will break out after receiving this many hits.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 100), Array.Empty<object>())); Instance.MaxLaunchSpeed = cfg.Bind<string>("Balance", "MaxLaunchSpeed", "30", "Maximum launch speed for broken-out enemies.\nUse 'INF' or 'INFINITY' for no cap.\nUseful when uncapping mass to prevent enemies from launching across the map."); Instance.EnableBossGrabbing = cfg.Bind<bool>("General", "EnableBossGrabbing", true, "Enable grabbing of boss enemies.\nWhen disabled, boss enemies cannot be repossessed."); Instance.EnableNPCGrabbing = cfg.Bind<bool>("General", "EnableNPCGrabbing", false, "Enable grabbing of NPCs with ungrabbable flag.\nWhen enabled, allows grabbing NPCs that are normally marked as ungrabbable."); Instance.EnableEnvironmentGrabbing = cfg.Bind<bool>("General", "EnableEnvironmentGrabbing", false, "Enable grabbing of environment objects like teleporters, chests, shrines.\nWhen enabled, allows repossessing interactable world objects."); Instance.EnableLockedObjectGrabbing = cfg.Bind<bool>("General", "EnableLockedObjectGrabbing", false, "Enable grabbing of locked objects.\nWhen enabled, allows grabbing objects that are currently locked (e.g., locked chests)."); Instance.ProjectileGrabbingMode = cfg.Bind<ProjectileGrabbingMode>("General", "ProjectileGrabbingMode", DrifterBossGrabMod.ProjectileGrabbingMode.None, "Mode for projectile grabbing:\n- None: Cannot grab projectiles\n- SurvivorOnly: Can only grab survivor projectiles\n- AllProjectiles: Can grab all projectiles"); Instance.SearchRadiusMultiplier = cfg.Bind<float>("Balance", "SearchRadiusMultiplier", 1f, "Multiplier for the grab reach distance.\nIncrease this to more easily grab large objects like rocks and teleporters."); Instance.EnableDebugLogs = cfg.Bind<bool>("General", "EnableDebugLogs", false, "Enable debug logging.\nWhen enabled, logs detailed information about grabbing mechanics for debugging."); Instance.BodyBlacklist = cfg.Bind<string>("General", "Blacklist", "HeaterPodBodyNoRespawn,ThrownObjectProjectile,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang", "Comma-separated list of body and projectile names to never grab.\nExample: SolusWingBody,Teleporter1,ShrineHalcyonite,PortalShop,RailgunnerPistolProjectile,SyringeProjectile\nAutomatically handles (Clone) - just enter the base name.\nUse debug logs to see body/projectile names, case-insensitive matching"); Instance.RecoveryObjectBlacklist = cfg.Bind<string>("General", "RecoveryObjectBlacklist", "", "Comma-separated list of object names to never recover from the abyss.\nExample: Teleporter1,Chest1,ShrineChance\nAutomatically handles (Clone) - just enter the base name.\nUse debug logs to see object names, case-insensitive matching"); Instance.GrabbableComponentTypes = cfg.Bind<string>("General", "GrabbableComponentTypes", "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController", "Comma-separated list of component type names that make objects grabbable.\nObjects must have at least one of these components to be grabbable.\nExample: SurfaceDefProvider,EntityStateMachine,JumpVolume\nUse exact component type names (case-sensitive)."); Instance.GrabbableKeywordBlacklist = cfg.Bind<string>("General", "GrabbableKeywordBlacklist", "Master,Controller", "Comma-separated list of keywords that make objects NOT grabbable if found in their name.\nObjects with these keywords in their name will be excluded from grabbing.\nExample: 'Master' prevents grabbing enemy masters\nCase-insensitive matching, partial matches allowed."); Instance.ComponentChooserSortModeEntry = cfg.Bind<ComponentChooserSortMode>("General", "ComponentChooserSortMode", ComponentChooserSortMode.ByFrequency, "How to sort the components when clicking the Component Chooser.\nByFrequency: Sorts by how many times the component appears in the scene.\nByProximity: Sorts by how close the component's GameObject is to the player's camera.\nByRaycast: Sorts by components hit directly by looking at them (raycast)."); Instance.ComponentChooserDummyEntry = cfg.Bind<ComponentChooserDummy>("General", "ComponentChooserDummy", ComponentChooserDummy.SelectToToggle, "Dummy setting for the Component Chooser UI."); Instance.EnableConfigSync = cfg.Bind<bool>("General", "EnableConfigSync", true, "Enable synchronization of configuration settings.\nHost: When enabled, sends config to clients when they join.\nClient: When enabled, receives and applies config from the host.\nWhen disabled, keeps your local configuration settings."); Instance.EnableObjectPersistence = cfg.Bind<bool>("Persistence", "EnableObjectPersistence", false, "Enable persistence of grabbed objects across stage transitions.\nWhen enabled, bagged objects are saved and restored when changing stages."); Instance.EnableAutoGrab = cfg.Bind<bool>("Persistence", "EnableAutoGrab", false, "Automatically re-grab persisted objects on Drifter respawn.\nWhen enabled, persisted objects are automatically repossessed after Drifter respawns."); Instance.PersistBaggedBosses = cfg.Bind<bool>("Persistence", "PersistBaggedBosses", true, "Allow persistence of bagged boss enemies.\nWhen disabled, boss enemies will not persist across stages."); Instance.PersistBaggedNPCs = cfg.Bind<bool>("Persistence", "PersistBaggedNPCs", true, "Allow persistence of bagged NPCs.\nWhen disabled, NPCs will not persist across stages."); Instance.PersistBaggedEnvironmentObjects = cfg.Bind<bool>("Persistence", "PersistBaggedEnvironmentObjects", true, "Allow persistence of bagged environment objects.\nWhen disabled, environment objects will not persist across stages."); Instance.PersistenceBlacklist = cfg.Bind<string>("Persistence", "PersistenceBlacklist", "", "Comma-separated list of object names to never persist.\nExample: Teleporter1,Chest1,ShrineChance\nAutomatically handles (Clone) - just enter the base name.\nUse debug logs to see object names, case-insensitive matching"); Instance.AutoGrabDelay = cfg.Bind<float>("Persistence", "AutoGrabDelay", 1f, "Delay before auto-grabbing persisted objects on stage start (seconds).\nDetermines how long to wait after stage start before auto-grabbing persisted objects."); Instance.BottomlessBagEnabled = cfg.Bind<bool>("Bottomless Bag", "EnableBottomlessBag", false, "Allows the scroll wheel to cycle through stored passengers.\nWhen enabled, bag capacity scales with the number of repossesses.\nFormula: TotalCapacity = UtilityMaxStocks + AddedCapacity + (UtilityMaxStocks × CapacityScalingBonus)"); Instance.AddedCapacity = cfg.Bind<string>("Bottomless Bag", "AddedCapacity", "0", "Added capacity for bottomless bag, added to utility max stocks. Use 'INF' for infinity.\nFormula: TotalCapacity = UtilityMaxStocks + AddedCapacity + CapacityScalingBonus"); Instance.EnableStockRefreshClamping = cfg.Bind<bool>("Bottomless Bag", "EnableStockRefreshClamping", false, "When enabled, Repossess stock refresh is clamped to max stocks minus number of bagged items.\nFormula: RefreshedStocks = MaxStocks - BaggedItemCount\nPrevents refreshing more stocks than available slots."); Instance.EnableSuccessiveGrabStockRefresh = cfg.Bind<bool>("Bottomless Bag", "EnableSuccessiveGrabStockRefresh", false, "When enabled, utility stock only refreshes after a successful grab if stock is 0.\nThis allows successive grabs to refresh your stock.\nWhen disabled, stock refreshes normally based on recharge timer."); Instance.CycleCooldown = cfg.Bind<float>("Bottomless Bag", "CycleCooldown", 0.2f, "Cooldown between passenger cycles (seconds).\nMinimum time between scroll wheel cycles to prevent rapid switching."); Instance.PlayAnimationOnCycle = cfg.Bind<bool>("Bottomless Bag", "PlayAnimationOnCycle", false, "When enabled, plays the bag grab animation when cycling to a new passenger.\nDisabled by default to reduce visual noise when cycling."); Instance.EnableMouseWheelScrolling = cfg.Bind<bool>("Bottomless Bag", "EnableMouseWheelScrolling", true, "Enable mouse wheel scrolling for cycling passengers.\nWhen enabled, mouse wheel can be used to cycle through bagged objects."); Instance.InverseMouseWheelScrolling = cfg.Bind<bool>("Bottomless Bag", "InverseMouseWheelScrolling", false, "Invert the mouse wheel scrolling direction.\nWhen enabled, scrolling up goes to previous object, down goes to next."); Instance.EnableCarouselHUD = cfg.Bind<bool>("Hud", "EnableCarouselHUD", false, "Enable the custom Carousel HUD for Drifter's bag.\nWhen disabled, reverts to vanilla UI behavior.\nNote: Automatically enabled when BottomlessBag is enabled."); Instance.CarouselSpacing = cfg.Bind<float>("Hud", "CarouselSpacing", 45f, "Vertical spacing for carousel items.\nDistance between adjacent items in the carousel."); Instance.CarouselAnimationDuration = cfg.Bind<float>("Hud", "CarouselAnimationDuration", 0.4f, "Duration of carousel animation in seconds.\nTime for carousel items to animate into position when cycling."); Instance.CenterSlotX = cfg.Bind<float>("Hud", "CenterSlotX", 25f, "X position offset for center slot."); Instance.CenterSlotY = cfg.Bind<float>("Hud", "CenterSlotY", 50f, "Y position offset for center slot."); Instance.CenterSlotScale = cfg.Bind<float>("Hud", "CenterSlotScale", 1f, "Scale for center slot (0.0 to 2.0)."); Instance.CenterSlotOpacity = cfg.Bind<float>("Hud", "CenterSlotOpacity", 1f, "Opacity for center slot (0.0 to 1.0)."); Instance.CenterSlotShowIcon = cfg.Bind<bool>("Hud", "CenterSlotShowIcon", true, "Show icon in center slot."); Instance.CenterSlotShowWeightIcon = cfg.Bind<bool>("Hud", "CenterSlotShowWeightIcon", true, "Show weight icon in center slot."); Instance.CenterSlotShowName = cfg.Bind<bool>("Hud", "CenterSlotShowName", true, "Show name in center slot."); Instance.CenterSlotShowHealthBar = cfg.Bind<bool>("Hud", "CenterSlotShowHealthBar", true, "Show health bar in center slot."); Instance.CenterSlotShowSlotNumber = cfg.Bind<bool>("Hud", "CenterSlotShowSlotNumber", true, "Show slot number in center slot."); Instance.SideSlotX = cfg.Bind<float>("Hud", "SideSlotX", 20f, "X position offset for side slots."); Instance.SideSlotY = cfg.Bind<float>("Hud", "SideSlotY", 5f, "Y position offset for side slots."); Instance.SideSlotScale = cfg.Bind<float>("Hud", "SideSlotScale", 0.8f, "Scale for side slots (0.0 to 2.0)."); Instance.SideSlotOpacity = cfg.Bind<float>("Hud", "SideSlotOpacity", 0.3f, "Opacity for side slots (0.0 to 1.0)."); Instance.SideSlotShowIcon = cfg.Bind<bool>("Hud", "SideSlotShowIcon", true, "Show icon in side slots."); Instance.SideSlotShowWeightIcon = cfg.Bind<bool>("Hud", "SideSlotShowWeightIcon", true, "Show weight icon in side slots."); Instance.SideSlotShowName = cfg.Bind<bool>("Hud", "SideSlotShowName", true, "Show name in side slots."); Instance.SideSlotShowHealthBar = cfg.Bind<bool>("Hud", "SideSlotShowHealthBar", true, "Show health bar in side slots."); Instance.SideSlotShowSlotNumber = cfg.Bind<bool>("Hud", "SideSlotShowSlotNumber", true, "Show slot number in side slots."); Instance.SelectedHudElement = cfg.Bind<HudElementType>("Hud", "SelectedHudElement", HudElementType.All, "Select which HUD element group to configure (UI only).\n- SelectedSlot: Center slot settings\n- AdjacentSlot: Side slot settings\n- WeightDisplay: Weight icon and display settings\n- DamagePreview: Damage preview overlay settings\n- CapacityUI: Mass capacity bar and gradient settings\n- BaggedObjectInfo: Bagged object info panel settings"); Instance.SelectedHudElement.Value = HudElementType.All; Instance.EnableBaggedObjectInfo = cfg.Bind<bool>("Hud", "EnableBaggedObjectInfo", false, "Enable the Bagged Object Info stats panel on the Info Screen (Tab)."); Instance.BaggedObjectInfoX = cfg.Bind<float>("Hud", "BaggedObjectInfoX", 20f, "X position offset for the Bagged Object Info panel."); Instance.BaggedObjectInfoY = cfg.Bind<float>("Hud", "BaggedObjectInfoY", 0f, "Y position offset for the Bagged Object Info panel."); Instance.BaggedObjectInfoScale = cfg.Bind<float>("Hud", "BaggedObjectInfoScale", 1f, "Scale value for the Bagged Object Info panel."); Instance.BaggedObjectInfoColor = cfg.Bind<Color>("Hud", "BaggedObjectInfoColor", new Color(1f, 1f, 1f, 0.9f), "Main text color for the Bagged Object Info panel."); Instance.EnableDamagePreview = cfg.Bind<bool>("Hud", "EnableDamagePreview", false, "Show a damage preview overlay on bagged object health bars.\nIndicates predicted slam damage to the object."); Instance.DamagePreviewColor = cfg.Bind<Color>("Hud", "DamagePreviewColor", new Color(1f, 0.15f, 0.15f, 0.8f), "Color for the damage preview overlay.\nRGBA color for the damage preview indicator."); Instance.UseNewWeightIcon = cfg.Bind<bool>("Hud", "UseNewWeightIcon", false, "Use the new custom weight icon instead of the original.\nWhen enabled, uses a custom weight icon design."); Instance.WeightDisplayMode = cfg.Bind<WeightDisplayMode>("Hud", "WeightDisplayMode", DrifterBossGrabMod.WeightDisplayMode.Multiplier, "Mode for displaying weight:\n- None: No weight display\n- Multiplier: Show as mass multiplier (e.g., 2.5x)\n- Pounds: Show in pounds (lb)\n- KiloGrams: Show in kilograms (kg)"); Instance.ScaleWeightColor = cfg.Bind<bool>("Hud", "ScaleWeightColor", true, "Scale the weight icon color based on capacity usage.\nWhen enabled, weight icon color uses the capacity gradient (green to red) based on mass/capacity ratio."); Instance.ShowTotalMassOnWeightIcon = cfg.Bind<bool>("Hud", "ShowTotalMassOnWeightIcon", false, "Show total bag mass on the center slot weight icon.\nWhen enabled, the center slot displays total bag mass instead of the selected object's mass.\nThe icon color uses the overencumbrance gradient based on capacity percentage."); Instance.ShowOverencumberIcon = cfg.Bind<bool>("Hud", "ShowOverencumberIcon", false, "Show the overencumbrance icon over the new weight icon when overencumbered.\nReplaces the weight text with a scaled down version of the custom arrow icon.\nOnly applies when ShowTotalMassOnWeightIcon is enabled."); Instance.AutoPromoteMainSeat = cfg.Bind<bool>("Bottomless Bag", "AutoPromoteMainSeat", false, "Automatically promote the next object in the bag to the main seat when the current main object is removed.\nWhen enabled, cycling through the bag automatically updates the main seat."); Instance.PrioritizeMainSeat = cfg.Bind<bool>("Bottomless Bag", "PrioritizeMainSeat", false, "When enabled, newly grabbed objects are placed in the main seat first instead of additional seats.\nWhen disabled (default), new objects go directly to additional seats."); Instance.BagScaleCap = cfg.Bind<string>("Balance", "BagScaleCap", "1", "Bag visual size cap. Set to 'INF' or 'Infinity' to uncap completely, continuing to grow based on mass.\nFormula: BagScale = 0.5 + 0.5 × ((Mass - 1) / (MaxMass - 1))"); Instance.MassCap = cfg.Bind<string>("Balance", "MassCap", "700", "Mass cap for caught entities. Set to 'INF' or 'Infinity' to remove the mass cap."); Instance.EnableMassCapacityUI = cfg.Bind<bool>("Hud", "EnableMassCapacityUI", false, "Enable the Mass Capacity UI for displaying bag capacity status.\nShows current mass vs capacity as a progress bar."); Instance.MassCapacityUIPositionX = cfg.Bind<float>("Hud", "MassCapacityUIPositionX", -20f, "Horizontal position offset for the Mass Capacity UI.\nX position offset from the default location."); Instance.MassCapacityUIPositionY = cfg.Bind<float>("Hud", "MassCapacityUIPositionY", 0f, "Vertical position offset for the Mass Capacity UI.\nY position offset from the default location."); Instance.MassCapacityUIScale = cfg.Bind<float>("Hud", "MassCapacityUIScale", 0.8f, "Scale multiplier for the Mass Capacity UI.\nSize multiplier for the UI element."); Instance.EnableSeparators = cfg.Bind<bool>("Hud", "EnableSeparators", true, "Enable dynamic separators (threshold pips) on the Mass Capacity UI.\nShows boundaries for each slot, or dynamically based on mass."); Instance.GradientIntensity = cfg.Bind<float>("Hud", "GradientIntensity", 1f, "Intensity of the gradient color on the Mass Capacity UI.\n0.0 is no gradient (solid mid color), 1.0 is full intensity."); Instance.CapacityGradientColorStart = cfg.Bind<Color>("Hud", "CapacityGradientColorStart", new Color(0f, 1f, 0f, 1f), "Start color (low mass) for standard capacity gradient."); Instance.CapacityGradientColorMid = cfg.Bind<Color>("Hud", "CapacityGradientColorMid", new Color(1f, 1f, 0f, 1f), "Mid color (medium mass) for standard capacity gradient."); Instance.CapacityGradientColorEnd = cfg.Bind<Color>("Hud", "CapacityGradientColorEnd", new Color(1f, 0f, 0f, 1f), "End color (high mass) for standard capacity gradient."); Instance.OverencumbranceGradientColorStart = cfg.Bind<Color>("Hud", "OverencumbranceGradientColorStart", new Color(0f, 1f, 1f, 1f), "Start color (low encumbrance) for overencumbrance gradient."); Instance.OverencumbranceGradientColorMid = cfg.Bind<Color>("Hud", "OverencumbranceGradientColorMid", new Color(0f, 0f, 0.5f, 1f), "Mid color (medium encumbrance) for overencumbrance gradient."); Instance.OverencumbranceGradientColorEnd = cfg.Bind<Color>("Hud", "OverencumbranceGradientColorEnd", new Color(0f, 0f, 1f, 1f), "End color (high encumbrance) for overencumbrance gradient."); Instance.EnableBalance = cfg.Bind<bool>("Balance", "EnableBalance", false, "Enable balance features (capacity scaling, elite mass bonus, overencumbrance).\nWhen disabled, all balance features are bypassed and vanilla behavior is used."); Instance.AoEDamageDistribution = cfg.Bind<AoEDamageMode>("Balance", "AoEDamageDistribution", AoEDamageMode.Full, "Mode for AoE damage distribution:\n- None: AoE slam damage disabled\n- Full: Each object takes full damage (total damage × object count)\n- Split: Damage is divided among objects (total damage ÷ object count)"); Instance.SlotScalingFormula = cfg.Bind<string>("Balance", "SlotScalingFormula", "0", "Formula for extra bag slots. Result is auto-floored to an integer.\nVariables: H = max health, L = level, C = utility stocks, MC = mass cap, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: 'H/100 + L' = 1 slot per 100 HP + 1 per level, 'floor(H/200) + floor(L/3)' = discrete steps\nSet to '0' to disable extra slot scaling."); Instance.MassCapacityFormula = cfg.Bind<string>("Balance", "MassCapacityFormula", "C * MC", "Formula for mass capacity limit.\nVariables: H = max health, L = level, C = utility stocks, MC = mass cap, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: 'C * MC' = linear 100 per stock, 'MC * 1.5^(C-1)' = exponential\nUse 'INF' for unlimited mass capacity."); Instance.EliteFlagMultiplier = cfg.Bind<string>("Balance", "EliteFlagMultiplier", "1", "Formula-based mass multiplier for Elite entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.EliteFlagMultiplier.Value = "1"; Instance.BossFlagMultiplier = cfg.Bind<string>("Balance", "BossFlagMultiplier", "1", "Formula-based mass multiplier for Boss entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.BossFlagMultiplier.Value = "1"; Instance.ChampionFlagMultiplier = cfg.Bind<string>("Balance", "ChampionFlagMultiplier", "1", "Formula-based mass multiplier for Champion entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.ChampionFlagMultiplier.Value = "1"; Instance.PlayerFlagMultiplier = cfg.Bind<string>("Balance", "PlayerFlagMultiplier", "1", "Formula-based mass multiplier for Player-controlled entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.PlayerFlagMultiplier.Value = "1"; Instance.MinionFlagMultiplier = cfg.Bind<string>("Balance", "MinionFlagMultiplier", "1", "Formula-based mass multiplier for Minion entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.MinionFlagMultiplier.Value = "1"; Instance.DroneFlagMultiplier = cfg.Bind<string>("Balance", "DroneFlagMultiplier", "1", "Formula-based mass multiplier for Drone entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.DroneFlagMultiplier.Value = "1"; Instance.MechanicalFlagMultiplier = cfg.Bind<string>("Balance", "MechanicalFlagMultiplier", "1", "Formula-based mass multiplier for Mechanical entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.MechanicalFlagMultiplier.Value = "1"; Instance.VoidFlagMultiplier = cfg.Bind<string>("Balance", "VoidFlagMultiplier", "1", "Formula-based mass multiplier for Void entities.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.VoidFlagMultiplier.Value = "1"; Instance.AllFlagMultiplier = cfg.Bind<string>(new ConfigDefinition("Character Flags", "All Flag Multiplier"), "1", new ConfigDescription("Universal multiplier that applies to ALL enemies. Stacks with specific flags.\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1' = no change, 'BH/max(B,1)' = base health becomes mass, 'H/max(B,1)' = scaled health becomes mass", (AcceptableValueBase)null, Array.Empty<object>())); Instance.SelectedFlag = cfg.Bind<CharacterFlagType>("Balance", "SelectedFlag", CharacterFlagType.All, "Select which flag to modify (UI only)"); Instance.SelectedFlag.Value = CharacterFlagType.All; Instance.SelectedFlagMultiplier = cfg.Bind<string>("Balance", "FlagMultiplier", "1", "Mass Multiplier for selected flag (UI only).\nVariables: H = max health (scaled), BH = base max health (unscaled), L = level, B = base mass, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '1.5' = 1.5x mass, 'H/1000' = 0.1% of max health, 'H/max(B,1)' = Health becomes mass"); Instance.SelectedFlagMultiplier.Value = "1"; Instance.SelectedBalanceSubTab = cfg.Bind<BalanceSubTabType>("Balance", "SelectedBalanceSubTab", BalanceSubTabType.All, "Select which Balance settings group to view (UI only)"); Instance.SelectedBalanceSubTab.Value = BalanceSubTabType.All; Instance.SelectedPreset = cfg.Bind<PresetType>("General", "SelectedPreset", PresetType.Intended, "Select a preset to apply all settings at once.\n- Vanilla: All features disabled, vanilla behavior\n- Intended: Boss grab only\n- Default: All features in DrifterGrabFeature + bottomless bag and persistence\n- Balance: Default + balance features\n- Custom: User has modified settings (auto-switched)"); Instance.LastSelectedPreset = cfg.Bind<PresetType>("Hidden", "LastSelectedPreset", PresetType.Intended, "Internal tracker of the last applied preset"); Instance.OverencumbranceMax = cfg.Bind<float>("Balance", "OverencumbranceMax", 100f, "Maximum overencumbrance percentage.\n0 = no overencumbrance allowed, 100% = double capacity, 50% = 1.5x capacity.\nFormula: MaxMass = Capacity × (1 + OverencumbranceMax / 100)"); Instance.StateCalculationMode = cfg.Bind<StateCalculationMode>("Balance", "StateCalculationMode", DrifterBossGrabMod.StateCalculationMode.Current, "Mode for calculating bagged object state:\n- Current: Only the currently selected object affects Drifter's stats\n- All: All bagged objects are aggregated for stat calculation"); Instance.MovespeedPenaltyFormula = cfg.Bind<string>("Balance", "MovespeedPenaltyFormula", "0", "Formula for movement speed penalty.\nVariables: T = Total mass, M = Mass capacity, C = Bag capacity (slots), H = Max health, L = Level, MC = mass cap, S = current stage\nFunctions: floor, ceil, round, min, max, abs, sqrt, log, ln, clamp, sin, cos, pow\nConstants: pi, e, INF\nExamples: '0' = no penalty, 'clamp((T/M) * 0.5, 0, 0.8)' = 50% at full capacity, capped at 80%\nSet to '0' for no penalty."); if (Instance.BottomlessBagEnabled.Value && !Instance.EnableCarouselHUD.Value) { Instance.EnableCarouselHUD.Value = true; } Instance.BottomlessBagEnabled.SettingChanged += delegate { if (Instance.BottomlessBagEnabled.Value && !Instance.EnableCarouselHUD.Value) { Instance.EnableCarouselHUD.Value = true; } }; Instance.EnableCarouselHUD.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowName.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowHealthBar.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowSlotNumber.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowName.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowHealthBar.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowSlotNumber.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.UseNewWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.WeightDisplayMode.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ScaleWeightColor.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ShowTotalMassOnWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ShowOverencumberIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.DamagePreviewColor.SettingChanged += delegate { UpdateDamagePreviewColors(); }; Instance.EnableMassCapacityUI.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.MassCapacityUIPositionX.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.MassCapacityUIPositionY.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.MassCapacityUIScale.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.EnableSeparators.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.GradientIntensity.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.CapacityGradientColorStart.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.CapacityGradientColorMid.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.CapacityGradientColorEnd.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.OverencumbranceGradientColorStart.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.OverencumbranceGradientColorMid.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.OverencumbranceGradientColorEnd.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.SlotScalingFormula.SettingChanged += delegate { string text12 = FormulaParser.Validate(Instance.SlotScalingFormula.Value); if (text12 != null) { Log.Warning("[PluginConfig] Invalid SlotScalingFormula: " + text12); } DrifterBagController[] array15 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController5 in array15) { CapacityScalingSystem.RecalculateCapacity(bagController5); CapacityScalingSystem.RecalculateState(bagController5); } }; Instance.MassCapacityFormula.SettingChanged += delegate { string text11 = FormulaParser.Validate(Instance.MassCapacityFormula.Value); if (text11 != null) { Log.Warning("[PluginConfig] Invalid MassCapacityFormula: " + text11); } DrifterBagController[] array14 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController4 in array14) { CapacityScalingSystem.RecalculateCapacity(bagController4); } }; Instance.AddedCapacity.SettingChanged += delegate { DrifterBagController[] array13 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController3 in array13) { CapacityScalingSystem.RecalculateCapacity(bagController3); } }; Instance.StateCalculationMode.SettingChanged += delegate { DrifterBagController[] array12 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController2 in array12) { CapacityScalingSystem.RecalculateState(bagController2); } }; Instance.MovespeedPenaltyFormula.SettingChanged += delegate { string text10 = FormulaParser.Validate(Instance.MovespeedPenaltyFormula.Value); if (text10 != null) { Log.Warning("[PluginConfig] Invalid MovespeedPenaltyFormula: " + text10); } DrifterBagController[] array11 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController in array11) { CapacityScalingSystem.RecalculatePenalty(bagController); } }; Instance.BagScaleCap.SettingChanged += delegate { DrifterBagController[] array10 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller10 in array10) { BagPassengerManager.ForceRecalculateMass(controller10); } }; Instance.MassCap.SettingChanged += delegate { DrifterBagController[] array9 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller9 in array9) { BagPassengerManager.ForceRecalculateMass(controller9); } }; Instance.EliteFlagMultiplier.SettingChanged += delegate { string text9 = FormulaParser.Validate(Instance.EliteFlagMultiplier.Value); if (text9 != null) { Log.Warning("[PluginConfig] Invalid EliteFlagMultiplier: " + text9); } DrifterBagController[] array8 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller8 in array8) { BagPassengerManager.ForceRecalculateMass(controller8); } }; Instance.BossFlagMultiplier.SettingChanged += delegate { string text8 = FormulaParser.Validate(Instance.BossFlagMultiplier.Value); if (text8 != null) { Log.Warning("[PluginConfig] Invalid BossFlagMultiplier: " + text8); } DrifterBagController[] array7 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller7 in array7) { BagPassengerManager.ForceRecalculateMass(controller7); } }; Instance.ChampionFlagMultiplier.SettingChanged += delegate { string text7 = FormulaParser.Validate(Instance.ChampionFlagMultiplier.Value); if (text7 != null) { Log.Warning("[PluginConfig] Invalid ChampionFlagMultiplier: " + text7); } DrifterBagController[] array6 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller6 in array6) { BagPassengerManager.ForceRecalculateMass(controller6); } }; Instance.PlayerFlagMultiplier.SettingChanged += delegate { string text6 = FormulaParser.Validate(Instance.PlayerFlagMultiplier.Value); if (text6 != null) { Log.Warning("[PluginConfig] Invalid PlayerFlagMultiplier: " + text6); } DrifterBagController[] array5 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller5 in array5) { BagPassengerManager.ForceRecalculateMass(controller5); } }; Instance.MinionFlagMultiplier.SettingChanged += delegate { string text5 = FormulaParser.Validate(Instance.MinionFlagMultiplier.Value); if (text5 != null) { Log.Warning("[PluginConfig] Invalid MinionFlagMultiplier: " + text5); } DrifterBagController[] array4 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller4 in array4) { BagPassengerManager.ForceRecalculateMass(controller4); } }; Instance.DroneFlagMultiplier.SettingChanged += delegate { string text4 = FormulaParser.Validate(Instance.DroneFlagMultiplier.Value); if (text4 != null) { Log.Warning("[PluginConfig] Invalid DroneFlagMultiplier: " + text4); } DrifterBagController[] array3 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller3 in array3) { BagPassengerManager.ForceRecalculateMass(controller3); } }; Instance.MechanicalFlagMultiplier.SettingChanged += delegate { string text3 = FormulaParser.Validate(Instance.MechanicalFlagMultiplier.Value); if (text3 != null) { Log.Warning("[PluginConfig] Invalid MechanicalFlagMultiplier: " + text3); } DrifterBagController[] array2 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller2 in array2) { BagPassengerManager.ForceRecalculateMass(controller2); } }; Instance.VoidFlagMultiplier.SettingChanged += delegate { string text2 = FormulaParser.Validate(Instance.VoidFlagMultiplier.Value); if (text2 != null) { Log.Warning("[PluginConfig] Invalid VoidFlagMultiplier: " + text2); } DrifterBagController[] array = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller in array) { BagPassengerManager.ForceRecalculateMass(controller); } }; Instance.SelectedFlagMultiplier.SettingChanged += delegate { string text = FormulaParser.Validate(Instance.SelectedFlagMultiplier.Value); if (text != null) { Log.Warning("[PluginConfig] Invalid FlagMultiplier formula: " + text); } else { CharacterFlagType value5 = Instance.SelectedFlag.Value; string value6 = Instance.SelectedFlagMultiplier.Value; switch (value5) { case CharacterFlagType.Elite: Instance.EliteFlagMultiplier.Value = value6; break; case CharacterFlagType.Boss: Instance.BossFlagMultiplier.Value = value6; break; case CharacterFlagType.Champion: Instance.ChampionFlagMultiplier.Value = value6; break; case CharacterFlagType.Player: Instance.PlayerFlagMultiplier.Value = value6; break; case CharacterFlagType.Minion: Instance.MinionFlagMultiplier.Value = value6; break; case CharacterFlagType.Drone: Instance.DroneFlagMultiplier.Value = value6; break; case CharacterFlagType.Mechanical: Instance.MechanicalFlagMultiplier.Value = value6; break; case CharacterFlagType.Void: Instance.VoidFlagMultiplier.Value = value6; break; case CharacterFlagType.All: Instance.AllFlagMultiplier.Value = value6; break; } } }; Instance.SelectedFlag.SettingChanged += delegate { CharacterFlagType value3 = Instance.SelectedFlag.Value; string value4 = "0"; switch (value3) { case CharacterFlagType.Elite: value4 = Instance.EliteFlagMultiplier.Value; break; case CharacterFlagType.Boss: value4 = Instance.BossFlagMultiplier.Value; break; case CharacterFlagType.Champion: value4 = Instance.ChampionFlagMultiplier.Value; break; case CharacterFlagType.Player: value4 = Instance.PlayerFlagMultiplier.Value; break; case CharacterFlagType.Minion: value4 = Instance.MinionFlagMultiplier.Value; break; case CharacterFlagType.Drone: value4 = Instance.DroneFlagMultiplier.Value; break; case CharacterFlagType.Mechanical: value4 = Instance.MechanicalFlagMultiplier.Value; break; case CharacterFlagType.Void: value4 = Instance.VoidFlagMultiplier.Value; break; case CharacterFlagType.All: value4 = Instance.AllFlagMultiplier.Value; break; } Instance.SelectedFlagMultiplier.Value = value4; }; Instance._blacklistCache = new LazyCachedValue<HashSet<string>>(() => (!string.IsNullOrEmpty(Instance.BodyBlacklist.Value)) ? (from s in Instance.BodyBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet<string>(StringComparer.OrdinalIgnoreCase) : new HashSet<string>()); Instance._blacklistCacheWithClones = new LazyCachedValue<HashSet<string>>(delegate { HashSet<string> value2 = Instance._blacklistCache.Value; HashSet<string> hashSet2 = new HashSet<string>(value2, StringComparer.OrdinalIgnoreCase); foreach (string item in value2) { hashSet2.Add(item + "(Clone)"); } return hashSet2; }); Instance._recoveryBlacklistCache = new LazyCachedValue<HashSet<string>>(() => (!string.IsNullOrEmpty(Instance.RecoveryObjectBlacklist.Value)) ? (from s in Instance.RecoveryObjectBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet<string>(StringComparer.OrdinalIgnoreCase) : new HashSet<string>()); Instance._recoveryBlacklistCacheWithClones = new LazyCachedValue<HashSet<string>>(delegate { HashSet<string> value = Instance._recoveryBlacklistCache.Value; HashSet<string> hashSet = new HashSet<string>(value, StringComparer.OrdinalIgnoreCase); foreach (string item2 in value) { hashSet.Add(item2 + "(Clone)"); } return hashSet; }); Instance._grabbableComponentTypesCache = new LazyCachedValue<HashSet<string>>(() => (!string.IsNullOrEmpty(Instance.GrabbableComponentTypes.Value)) ? (from s in Instance.GrabbableComponentTypes.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet<string>(StringComparer.Ordinal) : new HashSet<string>()); Instance._grabbableKeywordBlacklistCache = new LazyCachedValue<HashSet<string>>(() => (!string.IsNullOrEmpty(Instance.GrabbableKeywordBlacklist.Value)) ? (from s in Instance.GrabbableKeywordBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet<string>(StringComparer.OrdinalIgnoreCase) : new HashSet<string>()); Instance.BodyBlacklist.SettingChanged += delegate { Instance._blacklistCache.Invalidate(); Instance._blacklistCacheWithClones.Invalidate(); }; Instance.RecoveryObjectBlacklist.SettingChanged += delegate { Instance._recoveryBlacklistCache.Invalidate(); Instance._recoveryBlacklistCacheWithClones.Invalidate(); }; Instance.GrabbableComponentTypes.SettingChanged += delegate { Instance._grabbableComponentTypesCache.Invalidate(); }; Instance.GrabbableKeywordBlacklist.SettingChanged += delegate { Instance._grabbableKeywordBlacklistCache.Invalidate(); }; } public static void RemoveEventHandlers(EventHandler debugLogsHandler, EventHandler blacklistHandler, EventHandler recoveryBlacklistHandler, EventHandler grabbableComponentTypesHandler, EventHandler grabbableKeywordBlacklistHandler, EventHandler bossGrabbingHandler, EventHandler npcGrabbingHandler, EventHandler environmentGrabbingHandler, EventHandler lockedObjectGrabbingHandler, EventHandler projectileGrabbingModeHandler) { Instance.EnableDebugLogs.SettingChanged -= debugLogsHandler; Instance.BodyBlacklist.SettingChanged -= blacklistHandler; Instance.RecoveryObjectBlacklist.SettingChanged -= recoveryBlacklistHandler; Instance.GrabbableComponentTypes.SettingChanged -= grabbableComponentTypesHandler; Instance.GrabbableKeywordBlacklist.SettingChanged -= grabbableKeywordBlacklistHandler; Instance.EnableBossGrabbing.SettingChanged -= bossGrabbingHandler; Instance.EnableNPCGrabbing.SettingChanged -= npcGrabbingHandler; Instance.EnableEnvironmentGrabbing.SettingChanged -= environmentGrabbingHandler; Instance.EnableLockedObjectGrabbing.SettingChanged -= lockedObjectGrabbingHandler; Instance.ProjectileGrabbingMode.SettingChanged -= projectileGrabbingModeHandler; } public static void ClearBlacklistCache() { Instance._blacklistCache.Invalidate(); Instance._blacklistCacheWithClones.Invalidate(); } public static void ClearRecoveryBlacklistCache() { Instance._recoveryBlacklistCache.Invalidate(); Instance._recoveryBlacklistCacheWithClones.Invalidate(); } public static void ClearGrabbableComponentTypesCache() { Instance._grabbableComponentTypesCache.Invalidate(); } public static void ClearGrabbableKeywordBlacklistCache() { Instance._grabbableKeywordBlacklistCache.Invalidate(); } public static void InvalidateAllCaches() { Instance._blacklistCache.Invalidate(); Instance._blacklistCacheWithClones.Invalidate(); Instance._recoveryBlacklistCache.Invalidate(); Instance._recoveryBlacklistCacheWithClones.Invalidate(); Instance._grabbableComponentTypesCache.Invalidate(); Instance._grabbableKeywordBlacklistCache.Invalidate(); } public static ConfigEntry<string> GetFlagMultiplierConfig(CharacterFlagType flag) { return (ConfigEntry<string>)(flag switch { CharacterFlagType.Elite => Instance.EliteFlagMultiplier, CharacterFlagType.Boss => Instance.BossFlagMultiplier, CharacterFlagType.Champion => Instance.ChampionFlagMultiplier, CharacterFlagType.Player => Instance.PlayerFlagMultiplier, CharacterFlagType.Minion => Instance.MinionFlagMultiplier, CharacterFlagType.Drone => Instance.DroneFlagMultiplier, CharacterFlagType.Mechanical => Instance.MechanicalFlagMultiplier, CharacterFlagType.Void => Instance.VoidFlagMultiplier, CharacterFlagType.All => Instance.AllFlagMultiplier, _ => Instance.AllFlagMultiplier, }); } public static string GetFlagDisplayName(CharacterFlagType flag) { return flag switch { CharacterFlagType.Elite => "Elite", CharacterFlagType.Boss => "Boss", CharacterFlagType.Champion => "Champion", CharacterFlagType.Player => "Player", CharacterFlagType.Minion => "Minion", CharacterFlagType.Drone => "Drone", CharacterFlagType.Mechanical => "Mechanical", CharacterFlagType.Void => "Void", CharacterFlagType.All => "All", _ => "All", }; } public static ConfigEntry<float> GetSlotXConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotX; } return Instance.CenterSlotX; } public static ConfigEntry<float> GetSlotYConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotY; } return Instance.CenterSlotY; } public static ConfigEntry<float> GetSlotScaleConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotScale; } return Instance.CenterSlotScale; } public static ConfigEntry<float> GetSlotOpacityConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotOpacity; } return Instance.CenterSlotOpacity; } public static ConfigEntry<bool> GetSlotShowIconConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotShowIcon; } return Instance.CenterSlotShowIcon; } public static ConfigEntry<bool> GetSlotShowWeightIconConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotShowWeightIcon; } return Instance.CenterSlotShowWeightIcon; } public static ConfigEntry<bool> GetSlotShowNameConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotShowName; } return Instance.CenterSlotShowName; } public static ConfigEntry<bool> GetSlotShowHealthBarConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotShowHealthBar; } return Instance.CenterSlotShowHealthBar; } public static ConfigEntry<bool> GetSlotShowSlotNumberConfig(HudElementType slot) { if (slot != HudElementType.SelectedSlot) { return Instance.SideSlotShowSlotNumber; } return Instance.CenterSlotShowSlotNumber; } private static void UpdateBagUIToggles() { BaggedObjectCarousel[] array = Object.FindObjectsByType<BaggedObjectCarousel>((FindObjectsSortMode)0); BaggedObjectCarousel[] array2 = array; foreach (BaggedObjectCarousel baggedObjectCarousel in array2) { baggedObjectCarousel.UpdateToggles(); } } private static void UpdateMassCapacityUIToggles() { MassCapacityUIController[] array = Object.FindObjectsByType<MassCapacityUIController>((FindObjectsSortMode)0); MassCapacityUIController[] array2 = array; foreach (MassCapacityUIController massCapacityUIController in array2) { massCapacityUIController.UpdateConfig(); } } private static void UpdateDamagePreviewColors() { DamagePreviewOverlay[] array = Object.FindObjectsByType<DamagePreviewOverlay>((FindObjectsSortMode)0); DamagePreviewOverlay[] array2 = array; foreach (DamagePreviewOverlay damagePreviewOverlay in array2) { damagePreviewOverlay.UpdateColor(); } } private static Transform? FindDeepChild(Transform parent, string name) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown foreach (Transform item in parent) { Transform val = item; if (((Object)val).name == name) { return val; } Transform val2 = FindDeepChild(val, name); if ((Object)(object)val2 != (Object)null) { return val2; } } return null; } } internal static class Constants { public static class Timeouts { public const float SyncStateTimeout = 2f; public const float AutoGrabDelay = 0.5f; public const float OverencumbranceDebuffRemovalDelay = 1.5f; public const int MaxWaitFramesForPlayerBody = 120; public const float SyncWaitIncrement = 0.1f; } public static class Limits { public const float MaxMass = 700f; public const int MaxCapacity = 100; public const float MinimumMassPercentage = 0.1f; public const float MinimumMass = 1f; public const float PositionOffset = 0.5f; public const float CameraForwardOffset = 2f; public const float OriginYOffset = 1f; public const int SingleCapacity = 1; } public static class Multipliers { public const float DefaultMassMultiplier = 1f; public const float DefaultVelocityMultiplier = 1f; public const float ExponentialScalingBase = 0.5f; public const float WalkSpeedPenaltyMax = 0.5f; public const float PercentageDivisor = 100f; public const float CapacityRatioThreshold = 1f; public const float ScalingMultiplierBase = 1f; } public static class Network { public const short UpdateBagStateMessageType = 206; public const short GrabObjectMessageType = 208; } public const string CloneSuffix = "(Clone)"; public const string PluginGuid = "pwdcat.DrifterBossGrab"; public const string PluginName = "DrifterBossGrab"; public const string PluginVersion = "1.7.2"; } public static class FeatureState { public static bool IsCyclingEnabled => PluginConfig.Instance.BottomlessBagEnabled.Value; } public abstract class FeatureToggleBase : IFeatureToggle { private bool _isPatchesApplied; public abstract string FeatureName { get; } public abstract bool IsEnabled { get; } protected abstract void ApplyPatches(Harmony harmony); public void Initialize(Harmony harmony) { if (IsEnabled) { ApplyPatches(harmony); _isPatchesApplied = true; } } public virtual void Cleanup(Harmony harmony) { Log.Info("[" + FeatureName + "] Cleaning up patches..."); harmony.UnpatchSelf(); _isPatchesApplied = false; Log.Info("[" + FeatureName + "] Cleanup complete."); } public void Enable(Harmony harmony) { if (!IsEnabled) { Log.Info("[" + FeatureName + "] Enable called but IsEnabled is false. Aborting."); return; } if (_isPatchesApplied) { Log.Info("[" + FeatureName + "] Patches already applied, skipping."); return; } Log.Info("[" + FeatureName + "] Enabling feature and applying patches..."); ApplyPatches(harmony); _isPatchesApplied = true; } public void Disable(Harmony harmony) { Log.Info("[" + FeatureName + "] Disabling feature..."); Cleanup(harmony); } public void Toggle(Harmony harmony, bool enable) { Log.Info($"[{FeatureName}] Toggle called with enable={enable}"); if (enable) { Enable(harmony); } else { Disable(harmony); } } } public class PatchFactory : IPatchFactory, IConfigurable { private readonly List<Type> registeredPatchTypes = new List<Type>(); private Harmony? harmonyInstance; public static IPatchFactory Instance { get; } = new PatchFactory(); public void RegisterPatch(Type patchType) { if (patchType == null) { throw new ArgumentNullException("patchType"); } registeredPatchTypes.Add(patchType); } public void ApplyPatches() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected O, but got Unknown harmonyInstance = new Harmony("pwdcat.DrifterBossGrab"); foreach (Type registeredPatchType in registeredPatchTypes) { try { MethodInfo method = registeredPatchType.GetMethod("Initialize", BindingFlags.Static | BindingFlags.Public); if (method != null) { method.Invoke(null, null); } } catch (Exception ex) { Log.Error("Failed to initialize patch " + registeredPatchType.Name + ": " + ex.Message); } } } public void CleanupPatches() { foreach (Type registeredPatchType in registeredPatchTypes) { try { MethodInfo method = registeredPatchType.GetMethod("Cleanup", BindingFlags.Static | BindingFlags.Public); if (method != null) { method.Invoke(null, null); } } catch (Exception ex) { Log.Error("Failed to cleanup patch " + registeredPatchType.Name + ": " + ex.Message); } } registeredPatchTypes.Clear(); if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); harmonyInstance = null; } } public IEnumerable<Type> GetRegisteredPatchTypes() { return registeredPatchTypes.AsReadOnly(); } void IConfigurable.Initialize() { ApplyPatches(); } void IConfigurable.Cleanup() { CleanupPatches(); } } [BepInPlugin("pwdcat.DrifterBossGrab", "DrifterBossGrab", "1.7.2")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DrifterBossGrabPlugin : BaseUnityPlugin, IConfigObserver { public static class Timing { public const float BatchInitializationDelay = 0.2f; public const float GrabbableComponentTypesUpdateDelay = 0.5f; public const float HudSubTabVisibilityUpdateDelay = 0.5f; public const float BalanceSubTabVisibilityUpdateDelay = 0.5f; } public static class BatchProcessing { public const int BatchSize = 50; } public static class UI { public const int IconTextureSize = 256; public const float IconRectX = 0f; public const float IconRectY = 0f; public const float IconPivotX = 0.5f; public const float IconPivotY = 0.5f; } [CompilerGenerated] private sealed class <DelayedBatchSpecialObjectAttributesInitialization>d__85 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private GameObject[] <allObjects>5__2; private int <i>5__3; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedBatchSpecialObjectAttributesInitialization>d__85(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <allObjects>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.2f); <>1__state = 1; return true; case 1: <>1__state = -1; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info($"[DelayedBatchSpecialObjectAttributesInitialization] IsDrifterPresent: {IsDrifterPresent}"); } if (!IsDrifterPresent) { return false; } <allObjects>5__2 = Object.FindObjectsByType<GameObject>((FindObjectsSortMode)0); <i>5__3 = 0; goto IL_0103; case 2: { <>1__state = -1; goto IL_00f4; } IL_00f4: <i>5__3 += 50; goto IL_0103; IL_0103: if (<i>5__3 < <allObjects>5__2.Length) { int num = Mathf.Min(<i>5__3 + 50, <allObjects>5__2.Length); for (int i = <i>5__3; i < num; i++) { GameObject val = <allObjects>5__2[i]; if ((Object)(object)val != (Object)null && PluginConfig.IsGrabbable(val)) { GrabbableObjectPatches.AddSpecialObjectAttributesToGrabbableObject(val); } } if (num < <allObjects>5__2.Length) { <>2__current = null; <>1__state = 2; return true; } goto IL_00f4; } if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info($"[DelayedBatchSpecialObjectAttributesInitialization] Completed batched SpecialObjectAttributes initialization for {<allObjects>5__2.Length} objects"); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DelayedEnsureSpecialObjectAttributes>d__84 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedEnsureSpecialObjectAttributes>d__84(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DelayedGrabbableComponentTypesUpdate>d__87 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedGrabbableComponentTypesUpdate>d__87(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; PluginConfig.ClearGrabbableComponentTypesCache(); if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } _grabbableComponentTypesUpdateCoroutine = null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DelayedUpdateBalanceSubTabVisibility>d__89 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedUpdateBalanceSubTabVisibility>d__89(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateBalanceSubTabVisibility(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DelayedUpdateDrifterPresence>d__86 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedUpdateDrifterPresence>d__86(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; IsDrifterPresent = (Object)(object)Object.FindAnyObjectByType<DrifterBagController>() != (Object)null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DelayedUpdateHudSubTabVisibility>d__88 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedUpdateHudSubTabVisibility>d__88(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateHudSubTabVisibility(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <DelayedUpdateRooVisibility>d__92 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedUpdateRooVisibility>d__92(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateHudSubTabVisibility(); Instance.UpdateBalanceSubTabVisibility(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static Coroutine? _grabbableComponentTypesUpdateCoroutine; public static bool _isSwappingPassengers; private DrifterGrabFeature? _drifterGrabFeature; private BottomlessBagFeature? _bottomlessBagFeature; private PersistenceFeature? _persistenceFeature; private BalanceFeature? _balanceFeature; private Harmony? _drifterGrabHarmony; private Harmony? _bottomlessBagHarmony; private Harmony? _persistenceHarmony; private Harmony? _balanceHarmony; private bool _wasBottomlessBagEnabled; private bool _wasPersistenceEnabled; private bool _wasBalanceEnabled; private bool _wasDrifterGrabEnabled; private ConfigurationComposite? _configurationComposite; private EventHandler? debugLogsHandler; private EventHandler? blacklistHandler; private EventHandler? recoveryBlacklistHandler; private EventHandler? grabbableComponentTypesHandler; private EventHandler? grabbableKeywordBlacklistHandler; private EventHandler? bossGrabbingHandler; private EventHandler? npcGrabbingHandler; private EventHandler? environmentGrabbingHandler; private EventHandler? lockedObjectGrabbingHandler; private EventHandler? projectileGrabbingModeHandler; private EventHandler? persistenceHandler; private EventHandler? autoGrabHandler; private EventHandler? bottomlessBagToggleHandler; private EventHandler? persistenceToggleHandler; private EventHandler? balanceToggleHandler; public static DrifterBossGrabPlugin? Instance { get; private set; } public static bool RooInstalled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); public string DirectoryName => Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); public static bool IsSwappingPassengers => _isSwappingPassengers; public static bool IsDrifterPresent { get; set; } private void InitializeInstance() { Instance = this; } private void InitializeCoreSystems() { Log.Init(((BaseUnityPlugin)this).Logger); PluginConfig.Init(((BaseUnityPlugin)this).Config); StateManagement.Initialize(PluginConfig.Instance.EnableDebugLogs.Value); Log.EnableDebugLogs = PluginConfig.Instance.EnableDebugLogs.Value; } private void InitializeConfigurationComposite() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown _configurationComposite = new ConfigurationComposite(); _drifterGrabHarmony = new Harmony("pwdcat.DrifterBossGrab.driftergrab"); _bottomlessBagHarmony = new Harmony("pwdcat.DrifterBossGrab.bottomlessbag"); _persistenceHarmony = new Harmony("pwdcat.DrifterBossGrab.persistence"); _balanceHarmony = new Harmony("pwdcat.DrifterBossGrab.balance"); _drifterGrabFeature = new DrifterGrabFeature(); _drifterGrabFeature.Initialize(_drifterGrabHarmony); _bottomlessBagFeature = new BottomlessBagFeature(); _bottomlessBagFeature.Initialize(_bottomlessBagHarmony); _persistenceFeature = new PersistenceFeature(); _persistenceFeature.Initialize(_persistenceHarmony); _balanceFeature = new BalanceFeature(); _balanceFeature.Initialize(_balanceHarmony); _wasBottomlessBagEnabled = PluginConfig.Instance.BottomlessBagEnabled.Value; _wasPersistenceEnabled = PluginConfig.Instance.EnableObjectPersistence.Value; _wasBalanceEnabled = PluginConfig.Instance.EnableBalance.Value; _wasDrifterGrabEnabled = PluginConfig.Instance.SelectedPreset.Value != PresetType.Vanilla; _configurationComposite.AddComponent((IConfigurable)PatchFactory.Instance); _configurationComposite.AddComponent(new PersistenceManagerWrapper()); _configurationComposite.Initialize(); } public void Awake() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown InitializeInstance(); InitializeCoreSystems(); InitializeConfigurationComposite(); ConfigChangeNotifier.Init(); ConfigChangeNotifier.AddObserver(this); SetupConfigurationEventHandlers(); SetupFeatureToggleHandlers(); PresetManager.CheckAndApplyPresetOnStartup(); SyncFeatureTrackingState(); RegisterGameEvents(); BagStateSync.Init(new Harmony("pwdcat.DrifterBossGrab.networking")); ConfigSyncHandler.Init(); InputSetup.Init(); } private void RemoveConfigurationEventHandlers() { PluginConfig.RemoveEventHandlers(deb