Decompiled source of DrifterBossGrab v1.7.0
plugins/com.pwdcat.DrifterBossGrab.dll
Decompiled a week 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.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DrifterBossGrabMod.Balance; using DrifterBossGrabMod.Core; using DrifterBossGrabMod.Features; 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 Microsoft.CodeAnalysis; using RiskOfOptions; 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.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.pwdcat.DrifterBossGrab")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.7.0.0")] [assembly: AssemblyInformationalVersion("1.7.0")] [assembly: AssemblyProduct("com.pwdcat.DrifterBossGrab")] [assembly: AssemblyTitle("DrifterBossGrabMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.7.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.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.SearchRangeMultiplier.SettingChanged += configChangedHandler; PluginConfig.Instance.BreakoutTimeMultiplier.SettingChanged += configChangedHandler; PluginConfig.Instance.ForwardVelocityMultiplier.SettingChanged += configChangedHandler; PluginConfig.Instance.UpwardVelocityMultiplier.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.MassMultiplier.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.EnableComponentAnalysisLogs.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.BottomlessBagBaseCapacity.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableMouseWheelScrolling.SettingChanged += configChangedHandler; PluginConfig.Instance.ScrollUpKeybind.SettingChanged += configChangedHandler; PluginConfig.Instance.ScrollDownKeybind.SettingChanged += configChangedHandler; PluginConfig.Instance.CarouselSpacing.SettingChanged += configChangedHandler; PluginConfig.Instance.CarouselSideScale.SettingChanged += configChangedHandler; PluginConfig.Instance.CarouselSideOpacity.SettingChanged += configChangedHandler; } public static void Cleanup() { PluginConfig.Instance.SearchRangeMultiplier.SettingChanged -= configChangedHandler; PluginConfig.Instance.BreakoutTimeMultiplier.SettingChanged -= configChangedHandler; PluginConfig.Instance.ForwardVelocityMultiplier.SettingChanged -= configChangedHandler; PluginConfig.Instance.UpwardVelocityMultiplier.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.MassMultiplier.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.EnableComponentAnalysisLogs.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.BottomlessBagBaseCapacity.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableMouseWheelScrolling.SettingChanged -= configChangedHandler; PluginConfig.Instance.ScrollUpKeybind.SettingChanged -= configChangedHandler; PluginConfig.Instance.ScrollDownKeybind.SettingChanged -= configChangedHandler; PluginConfig.Instance.CarouselSpacing.SettingChanged -= configChangedHandler; PluginConfig.Instance.CarouselSideScale.SettingChanged -= configChangedHandler; PluginConfig.Instance.CarouselSideOpacity.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 { Full, Split } 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 class PluginConfig { private static PluginConfig _instance; 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<float> SearchRangeMultiplier { get; private set; } public ConfigEntry<float> BreakoutTimeMultiplier { get; private set; } public ConfigEntry<float> ForwardVelocityMultiplier { get; private set; } public ConfigEntry<float> UpwardVelocityMultiplier { get; private set; } 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<int> MaxSmacks { get; private set; } public ConfigEntry<string> MassMultiplier { get; private set; } public ConfigEntry<bool> EnableDebugLogs { 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<bool> EnableConfigSync { get; private set; } public ConfigEntry<bool> EnableComponentAnalysisLogs { 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> BottomlessBagEnabled { get; private set; } public ConfigEntry<int> BottomlessBagBaseCapacity { get; private set; } public ConfigEntry<bool> EnableStockRefreshClamping { get; private set; } public ConfigEntry<float> CycleCooldown { get; private set; } public ConfigEntry<bool> EnableMouseWheelScrolling { get; private set; } public ConfigEntry<bool> InverseMouseWheelScrolling { get; private set; } public ConfigEntry<KeyboardShortcut> ScrollUpKeybind { get; private set; } public ConfigEntry<KeyboardShortcut> ScrollDownKeybind { get; private set; } public ConfigEntry<float> CarouselSpacing { get; private set; } public ConfigEntry<float> CarouselCenterOffsetX { get; private set; } public ConfigEntry<float> CarouselCenterOffsetY { get; private set; } public ConfigEntry<float> CarouselSideOffsetX { get; private set; } public ConfigEntry<float> CarouselSideOffsetY { get; private set; } public ConfigEntry<float> CarouselSideScale { get; private set; } public ConfigEntry<float> CarouselSideOpacity { get; private set; } public ConfigEntry<float> CarouselAnimationDuration { get; private set; } public ConfigEntry<bool> BagUIShowIcon { get; private set; } public ConfigEntry<bool> BagUIShowWeight { get; private set; } public ConfigEntry<bool> BagUIShowName { get; private set; } public ConfigEntry<bool> BagUIShowHealthBar { get; private set; } public ConfigEntry<bool> EnableDamagePreview { get; private set; } public ConfigEntry<Color> DamagePreviewColor { 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> AutoPromoteMainSeat { get; private set; } public ConfigEntry<bool> UncapBagScale { get; private set; } public ConfigEntry<bool> UncapMass { get; private set; } public ConfigEntry<bool> EnableCarouselHUD { 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> EnableBalance { get; private set; } public ConfigEntry<bool> EnableAoESlamDamage { get; private set; } public ConfigEntry<AoEDamageMode> AoEDamageDistribution { get; private set; } public ConfigEntry<CapacityScalingMode> CapacityScalingMode { get; private set; } public ConfigEntry<ScalingType> CapacityScalingType { get; private set; } public ConfigEntry<float> CapacityScalingBonusPerCapacity { get; private set; } public ConfigEntry<bool> EliteMassBonusEnabled { get; private set; } public ConfigEntry<float> EliteMassBonusPercent { get; private set; } public ConfigEntry<bool> EnableOverencumbrance { get; private set; } public ConfigEntry<float> OverencumbranceMaxPercent { get; private set; } public ConfigEntry<bool> UncapCapacity { get; private set; } public ConfigEntry<bool> ToggleMassCapacity { get; private set; } public ConfigEntry<bool> StateCalculationModeEnabled { get; private set; } public ConfigEntry<StateCalculationMode> StateCalculationMode { get; private set; } public ConfigEntry<float> AllModeMassMultiplier { get; private set; } public ConfigEntry<float> MinMovespeedPenalty { get; private set; } public ConfigEntry<float> MaxMovespeedPenalty { get; private set; } public ConfigEntry<float> FinalMovespeedPenaltyLimit { 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Unknown result type (might be due to invalid IL or missing references) //IL_067a: Unknown result type (might be due to invalid IL or missing references) Instance.SearchRangeMultiplier = cfg.Bind<float>("Skill", "SearchRangeMultiplier", 1f, "Multiplier for Drifter's repossess search range.\nFormula: FinalRange = BaseRange × SearchRangeMultiplier"); Instance.ForwardVelocityMultiplier = cfg.Bind<float>("Skill", "ForwardVelocityMultiplier", 1f, "Multiplier for Drifter's repossess forward velocity.\nFormula: FinalForwardVelocity = BaseForwardVelocity × ForwardVelocityMultiplier"); Instance.UpwardVelocityMultiplier = cfg.Bind<float>("Skill", "UpwardVelocityMultiplier", 1f, "Multiplier for Drifter's repossess upward velocity.\nFormula: FinalUpwardVelocity = BaseUpwardVelocity × UpwardVelocityMultiplier"); Instance.BreakoutTimeMultiplier = cfg.Bind<float>("Skill", "BreakoutTimeMultiplier", 1f, "Multiplier for how long bagged enemies take to break out.\nFormula: FinalBreakoutTime = BaseBreakoutTime × BreakoutTimeMultiplier"); Instance.MaxSmacks = cfg.Bind<int>("Skill", "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.MassMultiplier = cfg.Bind<string>("Skill", "MassMultiplier", "1", "Multiplier for mass of bagged objects.\nFormula: FinalMass = BaseMass × MassMultiplier\nExample: 1.5 = 50% more mass, 0.5 = 50% less mass"); 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.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", "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.EnableConfigSync = cfg.Bind<bool>("General", "EnableConfigSync", true, "Enable synchronization of configuration settings from host to new clients.\nWhen enabled, clients joining a game will receive the host's configuration settings."); Instance.EnableComponentAnalysisLogs = cfg.Bind<bool>("General", "EnableComponentAnalysisLogs", false, "Enable scanning of all objects in the current scene to log component types.\nThis can be performance-intensive and should only be enabled for debugging.\nShows all unique component types found in the scene for potential grabbable objects."); 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 + BaseCapacity + (UtilityMaxStocks × CapacityScalingBonus)"); Instance.BottomlessBagBaseCapacity = cfg.Bind<int>("Bottomless Bag", "BaseCapacity", 0, "Base capacity for bottomless bag, added to utility max stocks.\nFormula: TotalCapacity = UtilityMaxStocks + BaseCapacity + 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.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.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.ScrollUpKeybind = cfg.Bind<KeyboardShortcut>("Bottomless Bag", "ScrollUpKeybind", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Keybind to scroll up through passengers.\nAlternative to mouse wheel for cycling to previous object."); Instance.ScrollDownKeybind = cfg.Bind<KeyboardShortcut>("Bottomless Bag", "ScrollDownKeybind", new KeyboardShortcut((KeyCode)0, Array.Empty<KeyCode>()), "Keybind to scroll down through passengers.\nAlternative to mouse wheel for cycling to next object."); 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.CarouselCenterOffsetX = cfg.Bind<float>("Hud", "CarouselCenterOffsetX", 25f, "Horizontal offset for center carousel item.\nX position offset for the currently selected item."); Instance.CarouselCenterOffsetY = cfg.Bind<float>("Hud", "CarouselCenterOffsetY", 50f, "Vertical offset for center carousel item.\nY position offset for the currently selected item."); Instance.CarouselSideOffsetX = cfg.Bind<float>("Hud", "CarouselSideOffsetX", 20f, "Horizontal offset for side carousel items.\nX position offset for adjacent items."); Instance.CarouselSideOffsetY = cfg.Bind<float>("Hud", "CarouselSideOffsetY", 5f, "Vertical offset for side carousel items.\nY position offset for adjacent items."); Instance.CarouselSideScale = cfg.Bind<float>("Hud", "CarouselSideScale", 0.8f, "Scale for side carousel items.\nSize multiplier for adjacent items (0.0 to 1.0)."); Instance.CarouselSideOpacity = cfg.Bind<float>("Hud", "CarouselSideOpacity", 0.3f, "Opacity for side carousel items.\nTransparency for adjacent items (0.0 to 1.0)."); 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.BagUIShowIcon = cfg.Bind<bool>("Hud", "BagUIShowIcon", true, "Show icon in additional Bag UI elements.\nWhen enabled, displays the object's icon in the UI."); Instance.BagUIShowWeight = cfg.Bind<bool>("Hud", "BagUIShowWeight", true, "Show weight indicator in additional Bag UI elements.\nWhen enabled, displays the object's weight/mass in the UI."); Instance.BagUIShowName = cfg.Bind<bool>("Hud", "BagUIShowName", true, "Show name in additional Bag UI elements.\nWhen enabled, displays the object's name in the UI."); Instance.BagUIShowHealthBar = cfg.Bind<bool>("Hud", "BagUIShowHealthBar", true, "Show health bar in additional Bag UI elements.\nWhen enabled, displays a health bar for the object in the UI."); Instance.EnableDamagePreview = cfg.Bind<bool>("Hud", "EnableDamagePreview", true, "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 mass.\nWhen enabled, weight icon color changes from green (light) to red (heavy) based on mass."); Instance.AutoPromoteMainSeat = cfg.Bind<bool>("Bottomless Bag", "AutoPromoteMainSeat", true, "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.UncapBagScale = cfg.Bind<bool>("Balance", "UncapBagScale", false, "When enabled, the bag visual size will not be capped and will continue to grow based on the mass of the stored object(s).\nFormula: BagScale = 0.5 + 0.5 × ((Mass - 1) / (MaxMass - 1))\nWhen disabled, bag scale is clamped between 1 and MaxMass."); Instance.UncapMass = cfg.Bind<bool>("Balance", "UncapMass", false, "When enabled, the mass cap of 700 is removed.\nWhen disabled, mass is clamped to a maximum of 700."); Instance.EnableMassCapacityUI = cfg.Bind<bool>("Hud", "EnableMassCapacityUI", true, "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.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.EnableAoESlamDamage = cfg.Bind<bool>("Balance", "EnableAoESlamDamage", false, "When enabled, slam/bluntforce actions damage every object in the bag.\nOnly active in 'All' calculation mode.\nAoEDamageDistribution determines how damage is split among objects."); Instance.AoEDamageDistribution = cfg.Bind<AoEDamageMode>("Balance", "AoEDamageDistribution", AoEDamageMode.Full, "Mode for AoE damage distribution:\n- Full: Each object takes full damage (total damage × object count)\n- Split: Damage is divided among objects (total damage ÷ object count)"); Instance.CapacityScalingMode = cfg.Bind<CapacityScalingMode>("Balance", "CapacityScalingMode", DrifterBossGrabMod.Balance.CapacityScalingMode.IncreaseCapacity, "Mode for capacity scaling:\n- IncreaseCapacity: Increases mass capacity based on utility stocks\n- HalveMass: Reduces mass of objects based on utility stocks"); Instance.CapacityScalingType = cfg.Bind<ScalingType>("Balance", "CapacityScalingType", ScalingType.Exponential, "Type of capacity scaling:\n- Linear: Capacity increases linearly with utility stocks\n- Exponential: Capacity increases exponentially with utility stocks"); Instance.CapacityScalingBonusPerCapacity = cfg.Bind<float>("Balance", "CapacityScalingBonusPerCapacity", 100f, "Bonus mass capacity per utility stock.\nFormula: CapacityBonus = UtilityStocks × CapacityScalingBonusPerCapacity\nExample: With 2 stocks and 100 bonus, capacity increases by 200"); Instance.EliteMassBonusEnabled = cfg.Bind<bool>("Balance", "EliteMassBonusEnabled", true, "Enable elite mass bonus.\nWhen enabled, elite enemies have increased mass when bagged."); Instance.EliteMassBonusPercent = cfg.Bind<float>("Balance", "EliteMassBonusPercent", 10f, "Percentage mass bonus for elites.\nFormula: EliteMass = BaseMass × (1 + EliteMassBonusPercent / 100)\nExample: With 10%, a 100 mass elite becomes 110 mass"); Instance.EnableOverencumbrance = cfg.Bind<bool>("Balance", "EnableOverencumbrance", true, "Enable overencumbrance penalties.\nWhen enabled, exceeding mass capacity incurs additional penalties."); Instance.OverencumbranceMaxPercent = cfg.Bind<float>("Balance", "OverencumbranceMaxPercent", 100f, "Maximum overencumbrance percentage.\n100% = double capacity, 50% = 1.5x capacity.\nFormula: MaxMass = Capacity × (1 + OverencumbranceMaxPercent / 100)"); Instance.UncapCapacity = cfg.Bind<bool>("Balance", "UncapCapacity", false, "When enabled, storage is practically infinite (slot count ignored).\nSlot count is ignored, only mass matters.\nWhen disabled, both slot and mass capacity are enforced."); Instance.ToggleMassCapacity = cfg.Bind<bool>("Balance", "ToggleMassCapacity", true, "When disabled, mass capacity is ignored and only slot capacity is used.\nWhen enabled, both slot and mass capacity are enforced."); Instance.StateCalculationModeEnabled = cfg.Bind<bool>("Balance", "StateCalculationModeEnabled", false, "Enable state calculation mode (Current vs All) in Balance tab.\nWhen enabled, allows choosing between Current and All calculation modes."); 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.AllModeMassMultiplier = cfg.Bind<float>("Balance", "AllModeMassMultiplier", 1f, "Multiplier for mass calculation in All mode.\nFormula: AllModeMass = SumOfAllMasses × AllModeMassMultiplier\nExamples:\n 1.0 = Full sum of all masses\n 0.5 = Half of all masses\n 2.0 = Double the sum of all masses"); Instance.MinMovespeedPenalty = cfg.Bind<float>("Balance", "MinMovespeedPenalty", 0f, "Minimum movement speed penalty (as a percentage of base movement speed).\nThis is the penalty when mass ratio is 0% (empty bag).\nFormula: BasePenalty = Lerp(MinMovespeedPenalty, MaxMovespeedPenalty, MassRatio)\nExample: 0.0 = no minimum penalty, 0.1 = minimum 10% penalty"); Instance.MaxMovespeedPenalty = cfg.Bind<float>("Balance", "MaxMovespeedPenalty", 0.5f, "Maximum movement speed penalty (as a percentage of base movement speed).\nThis is the penalty when mass ratio is 100% (at capacity).\nFormula: BasePenalty = Lerp(MinMovespeedPenalty, MaxMovespeedPenalty, MassRatio)\nExample: 0.5 = maximum 50% penalty at full capacity"); Instance.FinalMovespeedPenaltyLimit = cfg.Bind<float>("Balance", "FinalMovespeedPenaltyLimit", 0.8f, "Final limit for movement speed penalty (as a percentage of base movement speed).\nThis is a hard cap applied AFTER AllModePenaltyMultiplier is applied.\nFormula: FinalPenalty = Clamp(BasePenalty × AllModePenaltyMultiplier, Min, FinalMovespeedPenaltyLimit)\nExample: With MaxMovespeedPenalty=0.5, AllModePenaltyMultiplier=2.0:\n BasePenalty = 0.5, After Multiplier = 1.0, Clamped to FinalLimit = 0.8"); 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.BagUIShowIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.BagUIShowWeight.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.BagUIShowName.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.BagUIShowHealthBar.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.UseNewWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.WeightDisplayMode.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ScaleWeightColor.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.CapacityScalingMode.SettingChanged += delegate { DrifterBagController[] array13 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController11 in array13) { CapacityScalingSystem.RecalculateCapacity(bagController11); } }; Instance.CapacityScalingType.SettingChanged += delegate { DrifterBagController[] array12 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController10 in array12) { CapacityScalingSystem.RecalculateCapacity(bagController10); } }; Instance.CapacityScalingBonusPerCapacity.SettingChanged += delegate { DrifterBagController[] array11 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController9 in array11) { CapacityScalingSystem.RecalculateCapacity(bagController9); } }; Instance.BottomlessBagBaseCapacity.SettingChanged += delegate { DrifterBagController[] array10 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController8 in array10) { CapacityScalingSystem.RecalculateCapacity(bagController8); } }; Instance.UncapCapacity.SettingChanged += delegate { DrifterBagController[] array9 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController7 in array9) { CapacityScalingSystem.RecalculateCapacity(bagController7); } }; Instance.ToggleMassCapacity.SettingChanged += delegate { DrifterBagController[] array8 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController6 in array8) { CapacityScalingSystem.RecalculateCapacity(bagController6); } }; Instance.StateCalculationModeEnabled.SettingChanged += delegate { if (Instance.EnableBalance.Value) { DrifterBagController[] array7 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController5 in array7) { CapacityScalingSystem.RecalculateMass(bagController5); CapacityScalingSystem.RecalculateState(bagController5); } } }; Instance.StateCalculationMode.SettingChanged += delegate { DrifterBagController[] array6 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController4 in array6) { CapacityScalingSystem.RecalculateState(bagController4); } }; Instance.AllModeMassMultiplier.SettingChanged += delegate { DrifterBagController[] array5 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController3 in array5) { CapacityScalingSystem.RecalculateMass(bagController3); } }; Instance.MinMovespeedPenalty.SettingChanged += delegate { DrifterBagController[] array4 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController2 in array4) { CapacityScalingSystem.RecalculatePenalty(bagController2); } }; Instance.MaxMovespeedPenalty.SettingChanged += delegate { DrifterBagController[] array3 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController bagController in array3) { CapacityScalingSystem.RecalculatePenalty(bagController); } }; Instance.UncapBagScale.SettingChanged += delegate { DrifterBagController[] array2 = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller2 in array2) { BagPassengerManager.ForceRecalculateMass(controller2); } }; Instance.UncapMass.SettingChanged += delegate { DrifterBagController[] array = Object.FindObjectsByType<DrifterBagController>((FindObjectsSortMode)0); foreach (DrifterBagController controller in array) { BagPassengerManager.ForceRecalculateMass(controller); } }; 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 forwardVelHandler, EventHandler upwardVelHandler, 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.ForwardVelocityMultiplier.SettingChanged -= forwardVelHandler; Instance.UpwardVelocityMultiplier.SettingChanged -= upwardVelHandler; 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(); } 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.0"; } 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.0")] public class DrifterBossGrabPlugin : BaseUnityPlugin, IConfigObserver { [CompilerGenerated] private sealed class <DelayedBatchSpecialObjectAttributesInitialization>d__71 : 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__71(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__70 : 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__70(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__73 : 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__73(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 <DelayedUpdateDrifterPresence>d__72 : 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__72(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(); } } 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 ConfigurationComposite? _configurationComposite; private EventHandler? debugLogsHandler; private EventHandler? blacklistHandler; private EventHandler? forwardVelHandler; private EventHandler? upwardVelHandler; 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; _configurationComposite.AddComponent((IConfigurable)PatchFactory.Instance); _configurationComposite.AddComponent(new PersistenceManagerWrapper()); _configurationComposite.Initialize(); } public void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown InitializeInstance(); InitializeCoreSystems(); InitializeConfigurationComposite(); ConfigChangeNotifier.Init(); ConfigChangeNotifier.AddObserver(this); SetupConfigurationEventHandlers(); SetupFeatureToggleHandlers(); RegisterGameEvents(); BagStateSync.Init(new Harmony("pwdcat.DrifterBossGrab.networking")); ConfigSyncHandler.Init(); } private void RemoveConfigurationEventHandlers() { PluginConfig.RemoveEventHandlers(debugLogsHandler ?? ((EventHandler)delegate { }), blacklistHandler ?? ((EventHandler)delegate { }), forwardVelHandler ?? ((EventHandler)delegate { }), upwardVelHandler ?? ((EventHandler)delegate { }), recoveryBlacklistHandler ?? ((EventHandler)delegate { }), grabbableComponentTypesHandler ?? ((EventHandler)delegate { }), grabbableKeywordBlacklistHandler ?? ((EventHandler)delegate { }), bossGrabbingHandler ?? ((EventHandler)delegate { }), npcGrabbingHandler ?? ((EventHandler)delegate { }), environmentGrabbingHandler ?? ((EventHandler)delegate { }), lockedObjectGrabbingHandler ?? ((EventHandler)delegate { }), projectileGrabbingModeHandler ?? ((EventHandler)delegate { })); } private void RemovePersistenceEventHandlers() { PluginConfig.Instance.EnableObjectPersistence.SettingChanged -= persistenceHandler; PluginConfig.Instance.EnableAutoGrab.SettingChanged -= autoGrabHandler; } private void RemoveFeatureToggleHandlers() { PluginConfig.Instance.BottomlessBagEnabled.SettingChanged -= bottomlessBagToggleHandler; PluginConfig.Instance.EnableObjectPersistence.SettingChanged -= persistenceToggleHandler; PluginConfig.Instance.EnableBalance.SettingChanged -= balanceToggleHandler; } private void CleanupConfigurationComposite() { _configurationComposite?.Cleanup(); _drifterGrabFeature?.Cleanup(_drifterGrabHarmony); _bottomlessBagFeature?.Cleanup(_bottomlessBagHarmony); _persistenceFeature?.Cleanup(_persistenceHarmony); _balanceFeature?.Cleanup(_balanceHarmony); } private void StopCoroutines() { if (_grabbableComponentTypesUpdateCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_grabbableComponentTypesUpdateCoroutine); _grabbableComponentTypesUpdateCoroutine = null; } } private void SetupFeatureToggleHandlers() { bottomlessBagToggleHandler = delegate { bool value3 = PluginConfig.Instance.BottomlessBagEnabled.Value; if (value3 != _wasBottomlessBagEnabled) { _bottomlessBagFeature?.Toggle(_bottomlessBagHarmony, value3); _wasBottomlessBagEnabled = value3; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info("[FeatureToggle] BottomlessBag feature " + (value3 ? "enabled" : "disabled") + " at runtime"); } } }; PluginConfig.Instance.BottomlessBagEnabled.SettingChanged += bottomlessBagToggleHandler; persistenceToggleHandler = delegate { bool value2 = PluginConfig.Instance.EnableObjectPersistence.Value; if (value2 != _wasPersistenceEnabled) { _persistenceFeature?.Toggle(_persistenceHarmony, value2); _wasPersistenceEnabled = value2; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info("[FeatureToggle] Persistence feature " + (value2 ? "enabled" : "disabled") + " at runtime"); } } }; PluginConfig.Instance.EnableObjectPersistence.SettingChanged += persistenceToggleHandler; balanceToggleHandler = delegate { bool value = PluginConfig.Instance.EnableBalance.Value; if (value != _wasBalanceEnabled) { _balanceFeature?.Toggle(_balanceHarmony, value); _wasBalanceEnabled = value; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info("[FeatureToggle] Balance feature " + (value ? "enabled" : "disabled") + " at runtime"); } } }; PluginConfig.Instance.EnableBalance.SettingChanged += balanceToggleHandler; } public void OnDestroy() { RemoveConfigurationEventHandlers(); RemovePersistenceEventHandlers(); RemoveFeatureToggleHandlers(); CleanupConfigurationComposite(); StopCoroutines(); UIPatches.CleanupMassCapacityUI(); } public void OnConfigChanged(string key, object value) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info($"[OnConfigChanged] Config changed: {key} = {value}"); } } public void Start() { SetupRiskOfOptions(); } public void Update() { if (FeatureState.IsCyclingEnabled) { BottomlessBagPatches.HandleInput(); } } private void SetupConfigurationEventHandlers() { SetupDebugLogsHandler(); SetupBlacklistHandlers(); SetupVelocityHandlers(); SetupGrabbableHandlers(); SetupGrabbingHandlers(); SetupPersistenceHandlers(); PersistenceManager.UpdateCachedConfig(); } private void SetupDebugLogsHandler() { debugLogsHandler = delegate { Log.EnableDebugLogs = PluginConfig.Instance.EnableDebugLogs.Value; StateManagement.UpdateDebugLogging(PluginConfig.Instance.EnableDebugLogs.Value); }; PluginConfig.Instance.EnableDebugLogs.SettingChanged += debugLogsHandler; } private void SetupBlacklistHandlers() { blacklistHandler = delegate { PluginConfig.ClearBlacklistCache(); }; PluginConfig.Instance.BodyBlacklist.SettingChanged += blacklistHandler; recoveryBlacklistHandler = delegate { PluginConfig.ClearRecoveryBlacklistCache(); }; PluginConfig.Instance.RecoveryObjectBlacklist.SettingChanged += recoveryBlacklistHandler; } private void SetupVelocityHandlers() { forwardVelHandler = RepossessPatches.OnForwardVelocityChanged; PluginConfig.Instance.ForwardVelocityMultiplier.SettingChanged += forwardVelHandler; upwardVelHandler = RepossessPatches.OnUpwardVelocityChanged; PluginConfig.Instance.UpwardVelocityMultiplier.SettingChanged += upwardVelHandler; } private void SetupGrabbableHandlers() { grabbableComponentTypesHandler = delegate { if (_grabbableComponentTypesUpdateCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_grabbableComponentTypesUpdateCoroutine); } _grabbableComponentTypesUpdateCoroutine = ((MonoBehaviour)this).StartCoroutine(DelayedGrabbableComponentTypesUpdate()); }; PluginConfig.Instance.GrabbableComponentTypes.SettingChanged += grabbableComponentTypesHandler; grabbableKeywordBlacklistHandler = delegate { PluginConfig.ClearGrabbableKeywordBlacklistCache(); }; PluginConfig.Instance.GrabbableKeywordBlacklist.SettingChanged += grabbableKeywordBlacklistHandler; } private void SetupGrabbingHandlers() { bossGrabbingHandler = delegate { if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } }; PluginConfig.Instance.EnableBossGrabbing.SettingChanged += bossGrabbingHandler; npcGrabbingHandler = delegate { if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } }; PluginConfig.Instance.EnableNPCGrabbing.SettingChanged += npcGrabbingHandler; environmentGrabbingHandler = delegate { if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } }; PluginConfig.Instance.EnableEnvironmentGrabbing.SettingChanged += environmentGrabbingHandler; lockedObjectGrabbingHandler = delegate { if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } }; PluginConfig.Instance.EnableLockedObjectGrabbing.SettingChanged += lockedObjectGrabbingHandler; projectileGrabbingModeHandler = delegate { if (IsDrifterPresent) { GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); } }; PluginConfig.Instance.ProjectileGrabbingMode.SettingChanged += projectileGrabbingModeHandler; } private void SetupPersistenceHandlers() { persistenceHandler = delegate { PersistenceManager.UpdateCachedConfig(); }; PluginConfig.Instance.EnableObjectPersistence.SettingChanged += persistenceHandler; autoGrabHandler = delegate { PersistenceManager.UpdateCachedConfig(); }; PluginConfig.Instance.EnableAutoGrab.SettingChanged += autoGrabHandler; } private void RegisterGameEvents() { Run.onPlayerFirstCreatedServer += OnPlayerFirstCreated; SceneManager.activeSceneChanged += OnSceneChanged; CharacterBody.onBodyStartGlobal += OnBodyStart; } private void OnBodyStart(CharacterBody body) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)body) && body.bodyIndex == BodyCatalog.FindBodyIndex("DrifterBody")) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Info("[Plugin] Drifter body spawned: " + ((Object)body).name + ". Triggering object scan."); } IsDrifterPresent = true; GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); UIPatches.InitializeMassCapacityUI(); } } private static void OnPlayerFirstCreated(Run run, PlayerCharacterMasterController pcm) { if ((Object)(object)pcm != (Object)null && (Object)(object)pcm.networkUser != (Object)null && ((NetworkBehaviour)pcm.networkUser).connectionToClient != null) { ConfigSyncHandler.SendConfigToClient(((NetworkBehaviour)pcm.networkUser).connectionToClient); } } private static void OnSceneChanged(Scene oldScene, Scene newScene) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) IsDrifterPresent = false; OtherPatches.ResetZoneInversionDetection(); PersistenceSceneHandler.Instance.OnSceneChanged(oldScene, newScene); if ((Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StartCoroutine(DelayedUpdateDrifterPresence()); ((MonoBehaviour)Instance).StartCoroutine(DelayedEnsureSpecialObjectAttributes()); ((MonoBehaviour)Instance).StartCoroutine(DelayedBatchSpecialObjectAttributesInitialization()); } } [IteratorStateMachine(typeof(<DelayedEnsureSpecialObjectAttributes>d__70))] private static IEnumerator DelayedEnsureSpecialObjectAttributes() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedEnsureSpecialObjectAttributes>d__70(0); } [IteratorStateMachine(typeof(<DelayedBatchSpecialObjectAttributesInitialization>d__71))] private static IEnumerator DelayedBatchSpecialObjectAttributesInitialization() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedBatchSpecialObjectAttributesInitialization>d__71(0); } [IteratorStateMachine(typeof(<DelayedUpdateDrifterPresence>d__72))] private static IEnumerator DelayedUpdateDrifterPresence() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedUpdateDrifterPresence>d__72(0); } [IteratorStateMachine(typeof(<DelayedGrabbableComponentTypesUpdate>d__73))] private static IEnumerator DelayedGrabbableComponentTypesUpdate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedGrabbableComponentTypesUpdate>d__73(0); } private void SetupRiskOfOptions() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (RooInstalled) { ModSettingsManager.SetModDescription("Allows Drifter to grab bosses, NPCs, and environment objects.", "pwdcat.DrifterBossGrab", "DrifterBossGrab"); try { byte[] array = File.ReadAllBytes(Path.Combine(DirectoryName, "icon.png")); Texture2D val = new Texture2D(256, 256); ImageConversion.LoadImage(val, array); ModSettingsManager.SetModIcon(Sprite.Create(val, new Rect(0f, 0f, 256f, 256f), new Vector2(0.5f, 0.5f))); } catch (Exception) { } AddConfigurationOptions(); } } private void AddConfigurationOptions() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Expected O, but got Unknown //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Expected O, but got Unknown //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Expected O, but got Unknown //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Expected O, but got Unknown //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Expected O, but got Unknown //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Expected O, but got Unknown //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Expected O, but got Unknown //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Expected O, but got Unknown //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Expected O, but got Unknown //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01b4: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Expected O, but got Unknown //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Expected O, but got Unknown //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Expected O, but got Unknown //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0236: Expected O, but got Unknown //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Expected O, but got Unknown //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Expected O, but got Unknown //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Expected O, but got Unknown //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Expected O, but got Unknown //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Expected O, but got Unknown //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Expected O, but got Unknown //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Expected O, but got Unknown //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Expected O, but got Unknown //IL_02f2: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Expected O, but got Unknown //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Expected O, but got Unknown //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Expected O, but got Unknown //IL_032e: Unknown result type (might be due to invalid IL or missing references) //IL_0338: Expected O, but got Unknown //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Expected O, but got Unknown //IL_0356: Unknown result type (might be due to invalid IL or missing references) //IL_0360: Expected O, but got Unknown //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Expected O, but got Unknown //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Expected O, but got Unknown //IL_0392: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Expected O, but got Unknown //IL_03a6: Unknown result type (might be due to invalid IL or missing references) //IL_03b0: Expected O, but got Unknown //IL_03ba: Unknown result type (might be due to invalid IL or missing references) //IL_03c4: Expected O, but got Unknown //IL_03ce: Unknown result type (might be due to invalid IL or missing references) //IL_03d8: Expected O, but got Unknown //IL_03e2: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Expected O, but got Unknown //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_0400: Expected O, but got Unknown //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Expected O, but got Unknown //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_0428: Expected O, but got Unknown //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Expected O, but got Unknown //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0450: Expected O, but got Unknown //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_0464: Expected O, but got Unknown //IL_046e: Unknown result type (might be due to invalid IL or missing references) //IL_0478: Expected O, but got Unknown //IL_0482: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Expected O, but got Unknown //IL_0496: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Expected O, but got Unknown //IL_04aa: Unknown result type (might be due to invalid IL or missing references) //IL_04b4: Expected O, but got Unknown //IL_04be: Unknown result type (might be due to invalid IL or missing references) //IL_04c8: Expected O, but got Unknown //IL_04d2: Unknown result type (might be due to invalid IL or missing references) //IL_04dc: Expected O, but got Unknown //IL_04e6: Unknown result type (might be due to invalid IL or missing references) //IL_04f0: Expected O, but got Unknown //IL_04fa: Unknown result type (might be due to invalid IL or missing references) //IL_0504: Expected O, but got Unknown //IL_050e: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Expected O, but got Unknown //IL_0522: Unknown result type (might be due to invalid IL or missing references) //IL_052c: Expected O, but got Unknown //IL_0536: Unknown result type (might be due to invalid IL or missing references) //IL_0540: Expected O, but got Unknown //IL_054a: Unknown result type (might be due to invalid IL or missing references) //IL_0554: Expected O, but got Unknown //IL_055e: Unknown result type (might be due to invalid IL or missing references) //IL_0568: Expected O, but got Unknown //IL_0572: Unknown result type (might be due to invalid IL or missing references) //IL_057c: Expected O, but got Unknown //IL_0586: Unknown result type (might be due to invalid IL or missing references) //IL_0590: Expected O, but got Unknown //IL_059a: Unknown result type (might be due to invalid IL or missing references) //IL_05a4: Expected O, but got Unknown //IL_05ae: Unknown result type (might be due to invalid IL or missing references) //IL_05b8: Expected O, but got Unknown //IL_05c2: Unknown result type (might be due to invalid IL or missing references) //IL_05cc: Expected O, but got Unknown //IL_05d6: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Expected O, but got Unknown //IL_05ea: Unknown result type (might be due to invalid IL or missing references) //IL_05f4: Expected O, but got Unknown //IL_05fe: Unknown result type (might be due to invalid IL or missing references) //IL_0608: Expected O, but got Unknown //IL_0612: Unknown result type (might be due to invalid IL or missing references) //IL_061c: Expected O, but got Unknown //IL_0626: Unknown result type (might be due to invalid IL or missing references) //IL_0630: Expected O, but got Unknown //IL_063a: Unknown result type (might be due to invalid IL or missing references) //IL_0644: Expected O, but got Unknown if (RooInstalled) { ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableBossGrabbing)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableNPCGrabbing)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableEnvironmentGrabbing)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableLockedObjectGrabbing)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.ProjectileGrabbingMode)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableObjectPersistence)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableAutoGrab)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PersistBaggedBosses)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PersistBaggedNPCs)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PersistBaggedEnvironmentObjects)); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.PersistenceBlacklist)); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.AutoGrabDelay, new StepSliderConfig { min = 0f, max = 10f, increment = 0.1f })); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.SearchRangeMultiplier)); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.ForwardVelocityMultiplier)); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.UpwardVelocityMultiplier)); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.BreakoutTimeMultiplier)); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(PluginConfig.Instance.MaxSmacks)); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.MassMultiplier)); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.BodyBlacklist)); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.GrabbableComponentTypes)); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.GrabbableKeywordBlacklist)); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.RecoveryObjectBlacklist)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableDebugLogs)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableComponentAnalysisLogs)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableConfigSync)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.BottomlessBagEnabled)); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(PluginConfig.Instance.BottomlessBagBaseCapacity)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableStockRefreshClamping)); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.CycleCooldown, new StepSliderConfig { min = 0f, max = 1f, increment = 0.01f })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableMouseWheelScrolling)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.InverseMouseWheelScrolling)); ModSettingsManager.AddOption((BaseOption)new KeyBindOption(PluginConfig.Instance.ScrollUpKeybind)); ModSettingsManager.AddOption((BaseOption)new KeyBindOption(PluginConfig.Instance.ScrollDownKeybind)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableCarouselHUD)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselSpacing)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselCenterOffsetX)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselCenterOffsetY)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselSideOffsetX)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselSideOffsetY)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselSideScale)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselSideOpacity)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselAnimationDuration)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.BagUIShowIcon)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.BagUIShowWeight)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.BagUIShowName)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.BagUIShowHealthBar)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableDamagePreview)); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.DamagePreviewColor)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.UseNewWeightIcon)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.WeightDisplayMode)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.ScaleWeightColor)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.AutoPromoteMainSeat)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableMassCapacityUI)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MassCapacityUIPositionX)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MassCapacityUIPositionY)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MassCapacityUIScale)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableBalance)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.UncapCapacity)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.UncapBagScale)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.UncapMass)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.ToggleMassCapacity)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.CapacityScalingMode)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.CapacityScalingType)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CapacityScalingBonusPerCapacity)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EliteMassBonusEnabled)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.EliteMassBonusPercent)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableOverencumbrance)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.OverencumbranceMaxPercent)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.StateCalculationModeEnabled)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.StateCalculationMode)); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableAoESlamDamage)); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.AoEDamageDistribution)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.AllModeMassMultiplier)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MinMovespeedPenalty)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MaxMovespeedPenalty)); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.FinalMovespeedPenaltyLimit)); } } } public static class StateManagement { internal static bool cachedDebugLogsEnabled; public static void Initialize(bool debugLogsEnabled) { cachedDebugLogsEnabled = debugLogsEnabled; } public static void UpdateDebugLogging(bool debugLogsEnabled) { cachedDebugLogsEnabled = debugLogsEnabled; } public static void DisableMovementColliders(GameObject obj, Dictionary<GameObject, bool> originalStates) { ModelLocator component = obj.GetComponent<ModelLocator>(); if (!Object.op_Implicit((Object)(object)component) || !Object.op_Implicit((Object)(object)component.modelTransform)) { return; } Transform[] componentsInChildren = ((Component)component.modelTransform).GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { Collider component2 = ((Component)val).GetComponent<Collider>(); if ((Object)(object)component2 != (Object)null) { if (!originalStates.ContainsKey(((Component)val).gameObject)) { originalStates[((Component)val).gameObject] = ((Component)val).gameObject.activeSelf; } ((Component)val).gameObject.SetActive(false); } } } public static void RestoreMovementColliders(Dictionary<GameObject, bool> originalStates) { foreach (KeyValuePair<GameObject, bool> originalState in originalStates) { if ((Object)(object)originalState.Key != (Object)null) { originalState.Key.SetActive(originalState.Value); } } originalStates.Clear(); } } public class BalanceFeature : FeatureToggleBase { public override string FeatureName => "Balance"; public override bool IsEnabled => PluginConfig.Instance.EnableBalance.Value; protected override void ApplyPatches(Harmony harmony) { Log.Info("[" + FeatureName + "] Applying balance patches..."); harmony.CreateClassProcessor(typeof(BalancePatches.DrifterBagController_CalculateBaggedObjectMass_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.CharacterBody_RecalculateStats_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.CharacterBody_OnDestroy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(StateCalculationPatches)).Patch(); harmony.CreateClassProcessor(typeof(CmdDamageBaggedObject_AoE)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.BaggedObject_UpdateBaggedObjectMass)).Patch(); Log.Info("[" + FeatureName + "] Balance patches applied successfully."); } } public class BottomlessBagFeature : FeatureToggleBase { public override string FeatureName => "BottomlessBag"; public ov