using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DrifterBossGrabMod.API; using DrifterBossGrabMod.Balance; using DrifterBossGrabMod.Config; using DrifterBossGrabMod.Config.UI; using DrifterBossGrabMod.Core; using DrifterBossGrabMod.Features; using DrifterBossGrabMod.Input; using DrifterBossGrabMod.Networking; using DrifterBossGrabMod.Patches; using DrifterBossGrabMod.ProperSave; using DrifterBossGrabMod.ProperSave.Core; using DrifterBossGrabMod.ProperSave.Data; using DrifterBossGrabMod.ProperSave.Serializers; using DrifterBossGrabMod.ProperSave.Serializers.Plugins; using DrifterBossGrabMod.ProperSave.Spawning; using DrifterBossGrabMod.UI; using EntityStates; using EntityStates.CaptainSupplyDrop; using EntityStates.Drifter; using EntityStates.Drifter.Bag; using EntityStates.SurvivorPod; using HarmonyLib; using KinematicCharacterController; using Microsoft.CodeAnalysis; using MonoMod.RuntimeDetour; using Rewired; using Rewired.Data; using Rewired.Data.Mapping; using RiskOfOptions; using RiskOfOptions.Components.Options; using RiskOfOptions.Components.Panel; using RiskOfOptions.Components.RuntimePrefabs; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RiskOfOptions.Resources; using RoR2; using RoR2.HudOverlay; using RoR2.Networking; using RoR2.Projectile; using RoR2.Skills; using RoR2.UI; using TMPro; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("Rewired_Core")] [assembly: IgnoresAccessChecksTo("RoR2")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("DrifterBossGrab")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.8.0.0")] [assembly: AssemblyInformationalVersion("1.8.0")] [assembly: AssemblyProduct("DrifterBossGrab")] [assembly: AssemblyTitle("DrifterBossGrab")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.8.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 class PluginConfig { private static PluginConfig _instance = null; public static readonly Dictionary HudSettingToSubTab = new Dictionary { ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.HUD_FILTER.CHOICE"] = new HudElementType[7] { HudElementType.All, HudElementType.MainSlot, HudElementType.SideSlots, HudElementType.WeightIcon, HudElementType.DamagePreview, HudElementType.CapacityUI, HudElementType.StatsPanel }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLE_HUD_EDITOR.CHECKBOX"] = new HudElementType[7] { HudElementType.All, HudElementType.MainSlot, HudElementType.SideSlots, HudElementType.WeightIcon, HudElementType.DamagePreview, HudElementType.CapacityUI, HudElementType.StatsPanel }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLE_CAROUSEL_HUD.CHECKBOX"] = new HudElementType[2] { HudElementType.MainSlot, HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.VERTICAL_SPACING.FLOAT_FIELD"] = new HudElementType[2] { HudElementType.MainSlot, HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ANIMATION_DURATION.FLOAT_FIELD"] = new HudElementType[2] { HudElementType.MainSlot, HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.MAIN_SLOT_X_OFFSET.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.MAIN_SLOT_Y_OFFSET.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.MAIN_SLOT_SCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.MAIN_SLOT_OPACITY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_ICON_(MAIN).CHECKBOX"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_WEIGHT_ICON_(MAIN).CHECKBOX"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_NAME_(MAIN).CHECKBOX"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_HEALTH_(MAIN).CHECKBOX"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_SLOT_#_(MAIN).CHECKBOX"] = new HudElementType[1] { HudElementType.MainSlot }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SIDE_SLOT_X_OFFSET.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SIDE_SLOT_Y_OFFSET.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SIDE_SLOT_SCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SIDE_SLOT_OPACITY.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_ICON_(SIDE).CHECKBOX"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_WEIGHT_ICON_(SIDE).CHECKBOX"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_NAME_(SIDE).CHECKBOX"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_HEALTH_(SIDE).CHECKBOX"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_SLOT_#_(SIDE).CHECKBOX"] = new HudElementType[1] { HudElementType.SideSlots }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.USE_NEW_WEIGHT_ICON.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightIcon }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.WEIGHT_DISPLAY_MODE.CHOICE"] = new HudElementType[1] { HudElementType.WeightIcon }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SCALE_WEIGHT_COLOR.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightIcon }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_TOTAL_MASS.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightIcon }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.SHOW_OVERENCUMBERED_ICON.CHECKBOX"] = new HudElementType[1] { HudElementType.WeightIcon }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLE_DAMAGE_PREVIEW.CHECKBOX"] = new HudElementType[1] { HudElementType.DamagePreview }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.DAMAGE_PREVIEW_COLOR.COLOR"] = new HudElementType[1] { HudElementType.DamagePreview }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLE_CAPACITY_UI.CHECKBOX"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.CAPACITY_UI_X_POS.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.CAPACITY_UI_Y_POS.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.CAPACITY_UI_SCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLE_SEPARATORS.CHECKBOX"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.GRADIENT_INTENSITY.STEP_SLIDER"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.GRADIENT_COLOR_START.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.GRADIENT_COLOR_MID.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.GRADIENT_COLOR_END.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.OVERENCUMBRANCE_START.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.OVERENCUMBRANCE_MID.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.OVERENCUMBRANCE_END.COLOR"] = new HudElementType[1] { HudElementType.CapacityUI }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.ENABLE_STATS_PANEL.CHECKBOX"] = new HudElementType[1] { HudElementType.StatsPanel }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.STATS_PANEL_X_POS.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.StatsPanel }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.STATS_PANEL_Y_POS.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.StatsPanel }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.STATS_PANEL_SCALE.FLOAT_FIELD"] = new HudElementType[1] { HudElementType.StatsPanel }, ["COM.PWDCAT.DRIFTERBOSSGRAB.HUD.STATS_PANEL_COLOR.COLOR"] = new HudElementType[1] { HudElementType.StatsPanel } }; public static readonly Dictionary BalanceSettingToSubTab = new Dictionary { ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.MASS_CAPACITY_FORMULA.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Formulas }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.FLAG.CHOICE"] = new BalanceSubTabType[1] { BalanceSubTabType.Multipliers }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.MULTIPLIER.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Multipliers }, ["COM.PWDCAT.DRIFTERBOSSGRAB.CHARACTER_FLAGS.ALL_FLAG_MULTIPLIER.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Multipliers }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.MAX_OVERENCUMBRANCE_(%).FLOAT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Limits }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.STATE_CALCULATION.CHOICE"] = new BalanceSubTabType[1] { BalanceSubTabType.Formulas }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.MASS_MULTIPLIER_FORMULA.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Formulas }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.SPEED_PENALTY_FORMULA.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Formulas }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.BAG_VISUAL_SIZE_CAP.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Limits }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.BAGGED_ENTITY_MASS_CAP.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Limits }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.AOE_DAMAGE.CHOICE"] = new BalanceSubTabType[1] { BalanceSubTabType.Limits }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.GRAB_RANGE_MULTIPLIER.STEP_SLIDER"] = new BalanceSubTabType[1] { BalanceSubTabType.Multipliers }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.BREAKOUT_TIME_MULTIPLIER.STEP_SLIDER"] = new BalanceSubTabType[1] { BalanceSubTabType.Multipliers }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.MAX_HITS_BEFORE_BREAKOUT.INT_SLIDER"] = new BalanceSubTabType[1] { BalanceSubTabType.Limits }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.MAX_LAUNCH_SPEED.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Limits }, ["COM.PWDCAT.DRIFTERBOSSGRAB.BALANCE.SLAM_DAMAGE_FORMULA.STRING_INPUT_FIELD"] = new BalanceSubTabType[1] { BalanceSubTabType.Formulas } }; internal ICachedValue> _blacklistCache; internal ICachedValue> _blacklistCacheWithClones; internal ICachedValue> _recoveryBlacklistCache; internal ICachedValue> _recoveryBlacklistCacheWithClones; internal ICachedValue> _persistenceBlacklistCache; internal ICachedValue> _persistenceBlacklistCacheWithClones; internal ICachedValue> _grabbableComponentTypesCache; internal ICachedValue> _grabbableKeywordBlacklistCache; private readonly List _grabbingStrategies = new List { new BossGrabbingStrategy(), new NPCGrabbingStrategy(), new EnvironmentGrabbingStrategy() }; private bool _isBagScaleCapInfinite; private bool _isMassCapInfinite; private bool _isAddedCapacityInfinite; private bool _isMaxLaunchSpeedInfinite; private float _parsedMassCap = 700f; private float _parsedBagScaleCap = 1f; private float _parsedMaxLaunchSpeed = 30f; public static PluginConfig Instance => _instance ?? (_instance = new PluginConfig()); public ConfigEntry EnableBossGrabbing { get; private set; } public ConfigEntry EnableNPCGrabbing { get; private set; } public ConfigEntry EnableEnvironmentGrabbing { get; private set; } public ConfigEntry EnableLockedObjectGrabbing { get; private set; } public ConfigEntry ProjectileGrabbingMode { get; private set; } public ConfigEntry BodyBlacklist { get; private set; } public ConfigEntry RecoveryObjectBlacklist { get; private set; } public ConfigEntry GrabbableComponentTypes { get; private set; } public ConfigEntry GrabbableKeywordBlacklist { get; private set; } public ConfigEntry SearchRadiusMultiplier { get; private set; } public ConfigEntry EnableDebugLogs { get; private set; } public ConfigEntry EnableCombatDirectorPatches { get; private set; } public ConfigEntry ComponentChooserSortModeEntry { get; private set; } public ConfigEntry ComponentChooserDummyEntry { get; private set; } public ConfigEntry EnableConfigSync { get; private set; } public ConfigEntry SelectedPreset { get; private set; } public ConfigEntry LastSelectedPreset { get; private set; } public ConfigEntry EnableRecoveryFeature { get; private set; } public ConfigEntry EnemyRecoveryMode { get; private set; } public ConfigEntry RecoverBaggedBosses { get; private set; } public ConfigEntry RecoverBaggedNPCs { get; private set; } public ConfigEntry RecoverBaggedEnvironmentObjects { get; private set; } public ConfigEntry BottomlessBagEnabled { get; private set; } public ConfigEntry EnableStockRefreshClamping { get; private set; } public ConfigEntry EnableSuccessiveGrabStockRefresh { get; private set; } public ConfigEntry CycleCooldown { get; private set; } public ConfigEntry PlayAnimationOnCycle { get; private set; } public ConfigEntry EnableMouseWheelScrolling { get; private set; } public ConfigEntry InverseMouseWheelScrolling { get; private set; } public ConfigEntry AutoPromoteMainSeat { get; private set; } public ConfigEntry PrioritizeMainSeat { get; private set; } public ConfigEntry EnableObjectPersistence { get; private set; } public ConfigEntry EnableAutoGrab { get; private set; } public ConfigEntry PersistBaggedBosses { get; private set; } public ConfigEntry PersistBaggedNPCs { get; private set; } public ConfigEntry PersistBaggedEnvironmentObjects { get; private set; } public ConfigEntry PersistenceBlacklist { get; private set; } public ConfigEntry AutoGrabDelay { get; private set; } public ConfigEntry EnableCarouselHUD { get; private set; } public ConfigEntry CarouselSpacing { get; private set; } public ConfigEntry CarouselAnimationDuration { get; private set; } public ConfigEntry SelectedHudElement { get; private set; } public ConfigEntry CenterSlotX { get; private set; } public ConfigEntry CenterSlotY { get; private set; } public ConfigEntry CenterSlotScale { get; private set; } public ConfigEntry CenterSlotOpacity { get; private set; } public ConfigEntry CenterSlotShowIcon { get; private set; } public ConfigEntry CenterSlotShowWeightIcon { get; private set; } public ConfigEntry CenterSlotShowName { get; private set; } public ConfigEntry CenterSlotShowHealthBar { get; private set; } public ConfigEntry CenterSlotShowSlotNumber { get; private set; } public ConfigEntry SideSlotX { get; private set; } public ConfigEntry SideSlotY { get; private set; } public ConfigEntry SideSlotScale { get; private set; } public ConfigEntry SideSlotOpacity { get; private set; } public ConfigEntry SideSlotShowIcon { get; private set; } public ConfigEntry SideSlotShowWeightIcon { get; private set; } public ConfigEntry SideSlotShowName { get; private set; } public ConfigEntry SideSlotShowHealthBar { get; private set; } public ConfigEntry SideSlotShowSlotNumber { get; private set; } public ConfigEntry EnableBaggedObjectInfo { get; private set; } public ConfigEntry BaggedObjectInfoX { get; private set; } public ConfigEntry BaggedObjectInfoY { get; private set; } public ConfigEntry BaggedObjectInfoScale { get; private set; } public ConfigEntry BaggedObjectInfoColor { get; private set; } public ConfigEntry UseNewWeightIcon { get; private set; } public ConfigEntry WeightDisplayMode { get; private set; } public ConfigEntry ScaleWeightColor { get; private set; } public ConfigEntry ShowTotalMassOnWeightIcon { get; private set; } public ConfigEntry ShowOverencumberIcon { get; private set; } public ConfigEntry EnableDamagePreview { get; private set; } public ConfigEntry DamagePreviewColor { get; private set; } public ConfigEntry EnableMassCapacityUI { get; private set; } public ConfigEntry MassCapacityUIPositionX { get; private set; } public ConfigEntry MassCapacityUIPositionY { get; private set; } public ConfigEntry MassCapacityUIScale { get; private set; } public ConfigEntry EnableSeparators { get; private set; } public ConfigEntry GradientIntensity { get; private set; } public ConfigEntry CapacityGradientColorStart { get; private set; } public ConfigEntry CapacityGradientColorMid { get; private set; } public ConfigEntry CapacityGradientColorEnd { get; private set; } public ConfigEntry OverencumbranceGradientColorStart { get; private set; } public ConfigEntry OverencumbranceGradientColorMid { get; private set; } public ConfigEntry OverencumbranceGradientColorEnd { get; private set; } public ConfigEntry IsHudEditorEnabled { get; private set; } public ConfigEntry EnableBalance { get; private set; } public ConfigEntry AoEDamageDistribution { get; private set; } public ConfigEntry BreakoutTimeMultiplier { get; private set; } public ConfigEntry MaxSmacks { get; private set; } public ConfigEntry BagScaleCap { get; private set; } public ConfigEntry MassCap { get; private set; } public ConfigEntry MaxLaunchSpeed { get; private set; } public ConfigEntry StateCalculationMode { get; private set; } public ConfigEntry OverencumbranceMax { get; private set; } public ConfigEntry SlotScalingFormula { get; private set; } public ConfigEntry MassCapacityFormula { get; private set; } public ConfigEntry MovespeedPenaltyFormula { get; private set; } public ConfigEntry SlamDamageFormula { get; private set; } public ConfigEntry EliteFlagMultiplier { get; private set; } public ConfigEntry BossFlagMultiplier { get; private set; } public ConfigEntry ChampionFlagMultiplier { get; private set; } public ConfigEntry PlayerFlagMultiplier { get; private set; } public ConfigEntry MinionFlagMultiplier { get; private set; } public ConfigEntry DroneFlagMultiplier { get; private set; } public ConfigEntry MechanicalFlagMultiplier { get; private set; } public ConfigEntry VoidFlagMultiplier { get; private set; } public ConfigEntry AllFlagMultiplier { get; private set; } public ConfigEntry SelectedFlag { get; private set; } public ConfigEntry SelectedFlagMultiplier { get; private set; } public ConfigEntry SelectedBalanceSubTab { get; private set; } public bool IsBagScaleCapInfinite => _isBagScaleCapInfinite; public bool IsMassCapInfinite => _isMassCapInfinite; public bool IsAddedCapacityInfinite => _isAddedCapacityInfinite; public bool IsMaxLaunchSpeedInfinite => _isMaxLaunchSpeedInfinite; public float ParsedMassCap => _parsedMassCap; public float ParsedBagScaleCap => _parsedBagScaleCap; public float ParsedMaxLaunchSpeed => _parsedMaxLaunchSpeed; private static void InitBalanceConfig(ConfigFile cfg) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Expected O, but got Unknown Instance.EnableBalance = cfg.Bind("Balance", "EnableBalance", false, "Enable mass and penalty systems."); Instance.MassCapacityFormula = cfg.Bind("Balance", "MassCapacityFormula", "C * MC", "Formula for mass capacity limit. Supported: H (Max HP), L (Level), C (Stocks), MC (Mass Cap config), S (Stage)."); Instance.MovespeedPenaltyFormula = cfg.Bind("Balance", "MovespeedPenaltyFormula", "0", "Formula for movement speed penalty. Supported: T (Total Mass), M (Mass Cap limit), C (Total Cap), H (Max HP), L (Level), MC (Mass Cap config), S (Stage)."); Instance.SlamDamageFormula = cfg.Bind("Balance", "SlamDamageFormula", "BASE_COEF + (MASS_SCALING * BM / MC)", "Formula for slam damage coefficient. Supported: BASE_COEF, MASS_SCALING, BM (Bagged Mass), MC (Mass Cap)."); Instance.StateCalculationMode = cfg.Bind("Balance", "StateCalculationMode", DrifterBossGrabMod.StateCalculationMode.Current, "State calculation mode for stats."); Instance.AoEDamageDistribution = cfg.Bind("Balance", "AoEDamageDistribution", AoEDamageMode.Full, "Mode for AoE damage distribution."); Instance.OverencumbranceMax = cfg.Bind("Balance", "OverencumbranceMax", 100f, "Maximum overencumbrance percentage."); Instance.BreakoutTimeMultiplier = cfg.Bind("Balance", "BreakoutTimeMultiplier", 1f, "Multiplier for breakout time."); Instance.MaxSmacks = cfg.Bind("Balance", "MaxSmacks", 3, new ConfigDescription("Hits before breakout.", (AcceptableValueBase)(object)new AcceptableValueRange(1, 100), Array.Empty())); Instance.MaxLaunchSpeed = cfg.Bind("Balance", "MaxLaunchSpeed", "30", "Maximum launch speed for breakout."); Instance.BagScaleCap = cfg.Bind("Balance", "BagScaleCap", "1", "Bag visual size cap."); Instance.MassCap = cfg.Bind("Balance", "MassCap", "700", "Mass cap for caught entities."); WireBalanceEventHandlers(); } private static void WireBalanceEventHandlers() { Instance.MassCapacityFormula.SettingChanged += delegate { string text3 = FormulaParser.Validate(Instance.MassCapacityFormula.Value); if (text3 != null) { Log.Warning("[PluginConfig] Invalid MassCapacityFormula: " + text3); } DrifterBagController[] array7 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController bagController3 in array7) { CapacityScalingSystem.RecalculateCapacity(bagController3); } }; Instance.StateCalculationMode.SettingChanged += delegate { DrifterBagController[] array6 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController bagController2 in array6) { CapacityScalingSystem.RecalculateState(bagController2); } }; Instance.MovespeedPenaltyFormula.SettingChanged += delegate { string text2 = FormulaParser.Validate(Instance.MovespeedPenaltyFormula.Value); if (text2 != null) { Log.Warning("[PluginConfig] Invalid MovespeedPenaltyFormula: " + text2); } DrifterBagController[] array5 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController bagController in array5) { CapacityScalingSystem.RecalculatePenalty(bagController); } }; Instance.BagScaleCap.SettingChanged += delegate { Instance.RefreshCachedConfigStrings(); DrifterBagController[] array4 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller2 in array4) { BagPassengerManager.ForceRecalculateMass(controller2); } }; Instance.MassCap.SettingChanged += delegate { Instance.RefreshCachedConfigStrings(); DrifterBagController[] array3 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller in array3) { BagPassengerManager.ForceRecalculateMass(controller); } }; Instance.SlamDamageFormula.SettingChanged += delegate { string text = FormulaParser.Validate(Instance.SlamDamageFormula.Value); if (text != null) { Log.Warning("[PluginConfig] Invalid SlamDamageFormula: " + text); } DamagePreviewOverlay[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DamagePreviewOverlay[] array2 = array; foreach (DamagePreviewOverlay damagePreviewOverlay in array2) { damagePreviewOverlay.InvalidateCache(); } }; } private static void InitBottomlessBagConfig(ConfigFile cfg) { Instance.BottomlessBagEnabled = cfg.Bind("Bottomless Bag", "EnableBottomlessBag", false, "Store multiple objects and cycle through them."); Instance.EnableStockRefreshClamping = cfg.Bind("Bottomless Bag", "EnableStockRefreshClamping", false, "Clamp stock refresh to empty slots."); Instance.EnableSuccessiveGrabStockRefresh = cfg.Bind("Bottomless Bag", "EnableSuccessiveGrabStockRefresh", false, "Refresh stock only after a successful grab at 0."); Instance.CycleCooldown = cfg.Bind("Bottomless Bag", "CycleCooldown", 0.2f, "Cooldown between passenger cycles."); Instance.PlayAnimationOnCycle = cfg.Bind("Bottomless Bag", "PlayAnimationOnCycle", false, "Play grab animation when cycling."); Instance.EnableMouseWheelScrolling = cfg.Bind("Bottomless Bag", "EnableMouseWheelScrolling", true, "Cycle passengers via mouse wheel."); Instance.InverseMouseWheelScrolling = cfg.Bind("Bottomless Bag", "InverseMouseWheelScrolling", false, "Invert mouse wheel cycle direction."); Instance.AutoPromoteMainSeat = cfg.Bind("Bottomless Bag", "AutoPromoteMainSeat", false, "Auto-promote next object when main is removed."); Instance.PrioritizeMainSeat = cfg.Bind("Bottomless Bag", "PrioritizeMainSeat", false, "New objects go to main seat first."); Instance.SlotScalingFormula = cfg.Bind("Bottomless Bag", "SlotScalingFormula", "C + 2", "Formula for total bag slots. Supported: H (Max HP), L (Level), C (Stocks), MC (Mass Cap), S (Stage). Set to INF for infinite."); if (Instance.BottomlessBagEnabled.Value && !Instance.EnableCarouselHUD.Value) { Instance.EnableCarouselHUD.Value = true; } WireBottomlessBagEventHandlers(); } private static void WireBottomlessBagEventHandlers() { Instance.BottomlessBagEnabled.SettingChanged += delegate { if (Instance.BottomlessBagEnabled.Value && !Instance.EnableCarouselHUD.Value) { Instance.EnableCarouselHUD.Value = true; } }; Instance.SlotScalingFormula.SettingChanged += delegate { Instance.RefreshCachedConfigStrings(); string text = FormulaParser.Validate(Instance.SlotScalingFormula.Value); if (text != null) { Log.Warning("[PluginConfig] Invalid SlotScalingFormula: " + text); } DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController bagController in array) { CapacityScalingSystem.RecalculateCapacity(bagController); CapacityScalingSystem.RecalculateState(bagController); } }; } private static void InitCharacterFlagsConfig(ConfigFile cfg) { //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Expected O, but got Unknown //IL_014f: Expected O, but got Unknown Instance.EliteFlagMultiplier = cfg.Bind("Character Flags", "EliteFlagMultiplier", "1", "Mass multiplier for Elite entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.BossFlagMultiplier = cfg.Bind("Character Flags", "BossFlagMultiplier", "1", "Mass multiplier for Boss entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.ChampionFlagMultiplier = cfg.Bind("Character Flags", "ChampionFlagMultiplier", "1", "Mass multiplier for Champion entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.PlayerFlagMultiplier = cfg.Bind("Character Flags", "PlayerFlagMultiplier", "1", "Mass multiplier for Player entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.MinionFlagMultiplier = cfg.Bind("Character Flags", "MinionFlagMultiplier", "1", "Mass multiplier for Minion entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.DroneFlagMultiplier = cfg.Bind("Character Flags", "DroneFlagMultiplier", "1", "Mass multiplier for Drone entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.MechanicalFlagMultiplier = cfg.Bind("Character Flags", "MechanicalFlagMultiplier", "1", "Mass multiplier for Mechanical entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.VoidFlagMultiplier = cfg.Bind("Character Flags", "VoidFlagMultiplier", "1", "Mass multiplier for Void entities. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.AllFlagMultiplier = cfg.Bind(new ConfigDefinition("Character Flags", "all Flag Multiplier"), "1", new ConfigDescription("Universal multiplier for all enemies. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity).", (AcceptableValueBase)null, Array.Empty())); Instance.SelectedFlag = cfg.Bind("Hidden", "SelectedFlag", CharacterFlagType.All, "Select which flag to modify."); Instance.SelectedFlagMultiplier = cfg.Bind("Hidden", "FlagMultiplier", "1", "Mass multiplier for selected flag. Supported: B (Base Mass), H (Max HP), BH (Base Max HP), L (Level), C (Utility Stock Count), S (Stage Number), MC (Mass Capacity)."); Instance.SelectedBalanceSubTab = cfg.Bind("Hidden", "SelectedBalanceSubTab", BalanceSubTabType.All, "Select which Balance settings group to view."); CharacterFlagType value = Instance.SelectedFlag.Value; ConfigEntry flagMultiplierConfig = GetFlagMultiplierConfig(value); if (flagMultiplierConfig != null) { Instance.SelectedFlagMultiplier.Value = flagMultiplierConfig.Value; } WireCharacterFlagEventHandlers(); } private static void WireCharacterFlagEventHandlers() { Instance.EliteFlagMultiplier.SettingChanged += delegate { string text9 = FormulaParser.Validate(Instance.EliteFlagMultiplier.Value); if (text9 != null) { Log.Warning("[PluginConfig] Invalid EliteFlagMultiplier: " + text9); } DrifterBagController[] array8 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller8 in array8) { BagPassengerManager.ForceRecalculateMass(controller8); } }; Instance.BossFlagMultiplier.SettingChanged += delegate { string text8 = FormulaParser.Validate(Instance.BossFlagMultiplier.Value); if (text8 != null) { Log.Warning("[PluginConfig] Invalid BossFlagMultiplier: " + text8); } DrifterBagController[] array7 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller7 in array7) { BagPassengerManager.ForceRecalculateMass(controller7); } }; Instance.ChampionFlagMultiplier.SettingChanged += delegate { string text7 = FormulaParser.Validate(Instance.ChampionFlagMultiplier.Value); if (text7 != null) { Log.Warning("[PluginConfig] Invalid ChampionFlagMultiplier: " + text7); } DrifterBagController[] array6 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller6 in array6) { BagPassengerManager.ForceRecalculateMass(controller6); } }; Instance.PlayerFlagMultiplier.SettingChanged += delegate { string text6 = FormulaParser.Validate(Instance.PlayerFlagMultiplier.Value); if (text6 != null) { Log.Warning("[PluginConfig] Invalid PlayerFlagMultiplier: " + text6); } DrifterBagController[] array5 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller5 in array5) { BagPassengerManager.ForceRecalculateMass(controller5); } }; Instance.MinionFlagMultiplier.SettingChanged += delegate { string text5 = FormulaParser.Validate(Instance.MinionFlagMultiplier.Value); if (text5 != null) { Log.Warning("[PluginConfig] Invalid MinionFlagMultiplier: " + text5); } DrifterBagController[] array4 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller4 in array4) { BagPassengerManager.ForceRecalculateMass(controller4); } }; Instance.DroneFlagMultiplier.SettingChanged += delegate { string text4 = FormulaParser.Validate(Instance.DroneFlagMultiplier.Value); if (text4 != null) { Log.Warning("[PluginConfig] Invalid DroneFlagMultiplier: " + text4); } DrifterBagController[] array3 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller3 in array3) { BagPassengerManager.ForceRecalculateMass(controller3); } }; Instance.MechanicalFlagMultiplier.SettingChanged += delegate { string text3 = FormulaParser.Validate(Instance.MechanicalFlagMultiplier.Value); if (text3 != null) { Log.Warning("[PluginConfig] Invalid MechanicalFlagMultiplier: " + text3); } DrifterBagController[] array2 = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller2 in array2) { BagPassengerManager.ForceRecalculateMass(controller2); } }; Instance.VoidFlagMultiplier.SettingChanged += delegate { string text2 = FormulaParser.Validate(Instance.VoidFlagMultiplier.Value); if (text2 != null) { Log.Warning("[PluginConfig] Invalid VoidFlagMultiplier: " + text2); } DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller in array) { BagPassengerManager.ForceRecalculateMass(controller); } }; Instance.SelectedFlagMultiplier.SettingChanged += delegate { string text = FormulaParser.Validate(Instance.SelectedFlagMultiplier.Value); if (text != null) { Log.Warning("[PluginConfig] Invalid FlagMultiplier formula: " + text); } else { CharacterFlagType value3 = Instance.SelectedFlag.Value; string value4 = Instance.SelectedFlagMultiplier.Value; switch (value3) { case CharacterFlagType.Elite: Instance.EliteFlagMultiplier.Value = value4; break; case CharacterFlagType.Boss: Instance.BossFlagMultiplier.Value = value4; break; case CharacterFlagType.Champion: Instance.ChampionFlagMultiplier.Value = value4; break; case CharacterFlagType.Player: Instance.PlayerFlagMultiplier.Value = value4; break; case CharacterFlagType.Minion: Instance.MinionFlagMultiplier.Value = value4; break; case CharacterFlagType.Drone: Instance.DroneFlagMultiplier.Value = value4; break; case CharacterFlagType.Mechanical: Instance.MechanicalFlagMultiplier.Value = value4; break; case CharacterFlagType.Void: Instance.VoidFlagMultiplier.Value = value4; break; case CharacterFlagType.All: Instance.AllFlagMultiplier.Value = value4; break; } } }; Instance.SelectedFlag.SettingChanged += delegate { CharacterFlagType value = Instance.SelectedFlag.Value; string value2 = "0"; switch (value) { case CharacterFlagType.Elite: value2 = Instance.EliteFlagMultiplier.Value; break; case CharacterFlagType.Boss: value2 = Instance.BossFlagMultiplier.Value; break; case CharacterFlagType.Champion: value2 = Instance.ChampionFlagMultiplier.Value; break; case CharacterFlagType.Player: value2 = Instance.PlayerFlagMultiplier.Value; break; case CharacterFlagType.Minion: value2 = Instance.MinionFlagMultiplier.Value; break; case CharacterFlagType.Drone: value2 = Instance.DroneFlagMultiplier.Value; break; case CharacterFlagType.Mechanical: value2 = Instance.MechanicalFlagMultiplier.Value; break; case CharacterFlagType.Void: value2 = Instance.VoidFlagMultiplier.Value; break; case CharacterFlagType.All: value2 = Instance.AllFlagMultiplier.Value; break; } Instance.SelectedFlagMultiplier.Value = value2; }; } private static void InitGeneralConfig(ConfigFile cfg) { Instance.SelectedPreset = cfg.Bind("General", "SelectedPreset", PresetType.Intended, "Preset to load. Changes are auto-applied."); Instance.LastSelectedPreset = cfg.Bind("Hidden", "LastSelectedPreset", PresetType.Intended, "Internal tracker of the last applied preset."); Instance.EnableBossGrabbing = cfg.Bind("General", "EnableBossGrabbing", true, "Allow grabbing bosses."); Instance.EnableNPCGrabbing = cfg.Bind("General", "EnableNPCGrabbing", false, "Allow grabbing normally-ungrabbable NPCs."); Instance.EnableEnvironmentGrabbing = cfg.Bind("General", "EnableEnvironmentGrabbing", false, "Allow grabbing environment objects."); Instance.EnableLockedObjectGrabbing = cfg.Bind("General", "EnableLockedObjectGrabbing", false, "Allow grabbing locked objects."); Instance.ProjectileGrabbingMode = cfg.Bind("General", "ProjectileGrabbingMode", DrifterBossGrabMod.ProjectileGrabbingMode.None, "Projectile grab mode."); Instance.EnableDebugLogs = cfg.Bind("General", "EnableDebugLogs", false, "Log grab mechanics for debugging."); Instance.BodyBlacklist = cfg.Bind("General", "Blacklist", "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang", "Bodies and projectiles to never grab. Comma-separated."); Instance.RecoveryObjectBlacklist = cfg.Bind("General", "RecoveryObjectBlacklist", "", "Objects to never recover from the abyss. Comma-separated."); Instance.GrabbableComponentTypes = cfg.Bind("General", "GrabbableComponentTypes", "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController", "Component type names that make objects grabbable. Comma-separated."); Instance.GrabbableKeywordBlacklist = cfg.Bind("General", "GrabbableKeywordBlacklist", "Master,Controller", "Keywords that prevent grabbing if found in name. Comma-separated."); Instance.ComponentChooserSortModeEntry = cfg.Bind("Hidden", "ComponentChooserSortMode", ComponentChooserSortMode.ByFrequency, "How to sort components in the UI."); Instance.ComponentChooserDummyEntry = cfg.Bind("Hidden", "ComponentChooserDummy", ComponentChooserDummy.SelectToToggle, "Dummy setting for UI."); Instance.EnableConfigSync = cfg.Bind("General", "EnableConfigSync", true, "Sync configuration from host to clients."); Instance.SearchRadiusMultiplier = cfg.Bind("Balance", "SearchRadiusMultiplier", 1f, "Multiplier for grab reach distance."); } private static void InitHudConfig(ConfigFile cfg) { //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_05a8: Unknown result type (might be due to invalid IL or missing references) //IL_05e0: Unknown result type (might be due to invalid IL or missing references) //IL_0618: Unknown result type (might be due to invalid IL or missing references) //IL_0650: Unknown result type (might be due to invalid IL or missing references) //IL_0688: Unknown result type (might be due to invalid IL or missing references) //IL_06c0: Unknown result type (might be due to invalid IL or missing references) Instance.EnableCarouselHUD = cfg.Bind("Hud", "EnableCarouselHUD", false, "Enable the custom Carousel HUD."); Instance.CarouselSpacing = cfg.Bind("Hud", "CarouselSpacing", 45f, "Vertical spacing for carousel items."); Instance.CarouselAnimationDuration = cfg.Bind("Hud", "CarouselAnimationDuration", 0.4f, "Duration of carousel animation."); Instance.CenterSlotX = cfg.Bind("Hud", "CenterSlotX", 25f, "X position offset for center slot."); Instance.CenterSlotY = cfg.Bind("Hud", "CenterSlotY", 50f, "Y position offset for center slot."); Instance.CenterSlotScale = cfg.Bind("Hud", "CenterSlotScale", 1f, "Scale for center slot."); Instance.CenterSlotOpacity = cfg.Bind("Hud", "CenterSlotOpacity", 1f, "Opacity for center slot."); Instance.CenterSlotShowIcon = cfg.Bind("Hud", "CenterSlotShowIcon", true, "Show icon in center slot."); Instance.CenterSlotShowWeightIcon = cfg.Bind("Hud", "CenterSlotShowWeightIcon", true, "Show weight icon in center slot."); Instance.CenterSlotShowName = cfg.Bind("Hud", "CenterSlotShowName", true, "Show name in center slot."); Instance.CenterSlotShowHealthBar = cfg.Bind("Hud", "CenterSlotShowHealthBar", true, "Show health bar in center slot."); Instance.CenterSlotShowSlotNumber = cfg.Bind("Hud", "CenterSlotShowSlotNumber", true, "Show slot number in center slot."); Instance.SideSlotX = cfg.Bind("Hud", "SideSlotX", 20f, "X position offset for side slots."); Instance.SideSlotY = cfg.Bind("Hud", "SideSlotY", 5f, "Y position offset for side slots."); Instance.SideSlotScale = cfg.Bind("Hud", "SideSlotScale", 0.8f, "Scale for side slots."); Instance.SideSlotOpacity = cfg.Bind("Hud", "SideSlotOpacity", 0.3f, "Opacity for side slots."); Instance.SideSlotShowIcon = cfg.Bind("Hud", "SideSlotShowIcon", true, "Show icon in side slots."); Instance.SideSlotShowWeightIcon = cfg.Bind("Hud", "SideSlotShowWeightIcon", true, "Show weight icon in side slots."); Instance.SideSlotShowName = cfg.Bind("Hud", "SideSlotShowName", true, "Show name in side slots."); Instance.SideSlotShowHealthBar = cfg.Bind("Hud", "SideSlotShowHealthBar", true, "Show health bar in side slots."); Instance.SideSlotShowSlotNumber = cfg.Bind("Hud", "SideSlotShowSlotNumber", true, "Show slot number in side slots."); Instance.SelectedHudElement = cfg.Bind("Hidden", "SelectedHudElement", HudElementType.All, "Select which HUD element group to configure."); Instance.SelectedHudElement.Value = HudElementType.All; Instance.EnableBaggedObjectInfo = cfg.Bind("Hud", "EnableBaggedObjectInfo", false, "Enable the Bagged Object Info stats panel."); Instance.BaggedObjectInfoX = cfg.Bind("Hud", "BaggedObjectInfoX", 450f, "X position offset for stats panel."); Instance.BaggedObjectInfoY = cfg.Bind("Hud", "BaggedObjectInfoY", 85f, "Y position offset for stats panel."); Instance.BaggedObjectInfoScale = cfg.Bind("Hud", "BaggedObjectInfoScale", 1f, "Scale for stats panel."); Instance.BaggedObjectInfoColor = cfg.Bind("Hud", "BaggedObjectInfoColor", new Color(1f, 1f, 1f, 0.9f), "Text color for stats panel."); Instance.UseNewWeightIcon = cfg.Bind("Hud", "UseNewWeightIcon", false, "Use the custom weight icon."); Instance.WeightDisplayMode = cfg.Bind("Hud", "WeightDisplayMode", DrifterBossGrabMod.WeightDisplayMode.Multiplier, "Mode for weight display."); Instance.ScaleWeightColor = cfg.Bind("Hud", "ScaleWeightColor", true, "Scale weight icon color by capacity."); Instance.ShowTotalMassOnWeightIcon = cfg.Bind("Hud", "ShowTotalMassOnWeightIcon", false, "Show total bag mass on center slot."); Instance.ShowOverencumberIcon = cfg.Bind("Hud", "ShowOverencumberIcon", false, "Show overencumbrance icon."); Instance.EnableDamagePreview = cfg.Bind("Hud", "EnableDamagePreview", false, "Show damage preview overlay."); Instance.DamagePreviewColor = cfg.Bind("Hud", "DamagePreviewColor", new Color(1f, 0.15f, 0.15f, 0.8f), "Color for damage preview."); Instance.EnableMassCapacityUI = cfg.Bind("Hud", "EnableMassCapacityUI", false, "Enable the Mass Capacity UI bar."); Instance.MassCapacityUIPositionX = cfg.Bind("Hud", "MassCapacityUIPositionX", -20f, "X offset for Mass Capacity UI."); Instance.MassCapacityUIPositionY = cfg.Bind("Hud", "MassCapacityUIPositionY", 0f, "Y offset for Mass Capacity UI."); Instance.MassCapacityUIScale = cfg.Bind("Hud", "MassCapacityUIScale", 0.8f, "Scale for Mass Capacity UI."); Instance.EnableSeparators = cfg.Bind("Hud", "EnableSeparators", true, "Show threshold pips on Mass Capacity UI."); Instance.GradientIntensity = cfg.Bind("Hud", "GradientIntensity", 1f, "Intensity of the gradient color."); Instance.CapacityGradientColorStart = cfg.Bind("Hud", "CapacityGradientColorStart", new Color(0f, 1f, 0f, 1f), "Start color for standard capacity gradient."); Instance.CapacityGradientColorMid = cfg.Bind("Hud", "CapacityGradientColorMid", new Color(1f, 1f, 0f, 1f), "Mid color for standard capacity gradient."); Instance.CapacityGradientColorEnd = cfg.Bind("Hud", "CapacityGradientColorEnd", new Color(1f, 0f, 0f, 1f), "End color for standard capacity gradient."); Instance.OverencumbranceGradientColorStart = cfg.Bind("Hud", "OverencumbranceGradientColorStart", new Color(0f, 1f, 1f, 1f), "Start color for overencumbrance gradient."); Instance.OverencumbranceGradientColorMid = cfg.Bind("Hud", "OverencumbranceGradientColorMid", new Color(0f, 0f, 0.5f, 1f), "Mid color for overencumbrance gradient."); Instance.OverencumbranceGradientColorEnd = cfg.Bind("Hud", "OverencumbranceGradientColorEnd", new Color(0f, 0f, 1f, 1f), "End color for overencumbrance gradient."); Instance.IsHudEditorEnabled = cfg.Bind("Hidden", "IsHudEditorEnabled", false, "Toggle to enable the in-game HUD Editor. You MUST be in game for it to work."); Instance.IsHudEditorEnabled.Value = false; WireHudEventHandlers(); } private static void WireHudEventHandlers() { Instance.EnableCarouselHUD.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowName.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.CenterSlotShowSlotNumber.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowName.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowHealthBar.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.SideSlotShowSlotNumber.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.UseNewWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.WeightDisplayMode.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ScaleWeightColor.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ShowTotalMassOnWeightIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.ShowOverencumberIcon.SettingChanged += delegate { UpdateBagUIToggles(); }; Instance.DamagePreviewColor.SettingChanged += delegate { UpdateDamagePreviewColors(); }; Instance.EnableMassCapacityUI.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.MassCapacityUIPositionX.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.MassCapacityUIPositionY.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.MassCapacityUIScale.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.EnableSeparators.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.GradientIntensity.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.CapacityGradientColorStart.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.CapacityGradientColorMid.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.CapacityGradientColorEnd.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.OverencumbranceGradientColorStart.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.OverencumbranceGradientColorMid.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; Instance.OverencumbranceGradientColorEnd.SettingChanged += delegate { UpdateMassCapacityUIToggles(); }; } private static void InitPersistenceConfig(ConfigFile cfg) { Instance.EnableObjectPersistence = cfg.Bind("Persistence", "EnableObjectPersistence", false, "Save and restore bagged objects across stages."); Instance.EnableAutoGrab = cfg.Bind("Persistence", "EnableAutoGrab", false, "Auto-grab persisted objects on stage start."); Instance.PersistBaggedBosses = cfg.Bind("Persistence", "PersistBaggedBosses", true, "Allow bosses to persist across stages."); Instance.PersistBaggedNPCs = cfg.Bind("Persistence", "PersistBaggedNPCs", true, "Allow NPCs to persist across stages."); Instance.PersistBaggedEnvironmentObjects = cfg.Bind("Persistence", "PersistBaggedEnvironmentObjects", true, "Allow environment objects to persist across stages."); Instance.PersistenceBlacklist = cfg.Bind("Persistence", "PersistenceBlacklist", "", "Objects to never persist. Comma-separated."); Instance.AutoGrabDelay = cfg.Bind("Persistence", "AutoGrabDelay", 1f, "Delay before auto-grabbing persisted objects (seconds)."); } 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 IsPersistenceBlacklisted(string? name) { if (string.IsNullOrEmpty(name)) { return false; } return Instance._persistenceBlacklistCacheWithClones.Value.Contains(name); } public static bool IsPersistenceBlacklisted(GameObject? obj) { if ((Object)(object)obj == (Object)null) { return false; } if (IsPersistenceBlacklisted(((Object)obj).name)) { return true; } if (Instance._persistenceBlacklistCache.Value.Contains("Teleporter") && (Object)(object)obj.GetComponent() != (Object)null) { return true; } return false; } 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 void RefreshCachedConfigStrings() { _isBagScaleCapInfinite = string.Equals(BagScaleCap.Value, "INF", StringComparison.OrdinalIgnoreCase) || string.Equals(BagScaleCap.Value, "INFINITY", StringComparison.OrdinalIgnoreCase); _parsedBagScaleCap = (_isBagScaleCapInfinite ? float.MaxValue : (float.TryParse(BagScaleCap.Value, out var result) ? result : 1f)); _isMassCapInfinite = string.Equals(MassCap.Value, "INF", StringComparison.OrdinalIgnoreCase) || string.Equals(MassCap.Value, "INFINITY", StringComparison.OrdinalIgnoreCase); _parsedMassCap = (_isMassCapInfinite ? float.MaxValue : (float.TryParse(MassCap.Value, out var result2) ? result2 : 700f)); _isAddedCapacityInfinite = string.Equals(SlotScalingFormula.Value, "INF", StringComparison.OrdinalIgnoreCase) || string.Equals(SlotScalingFormula.Value, "INFINITY", StringComparison.OrdinalIgnoreCase); _isMaxLaunchSpeedInfinite = string.Equals(MaxLaunchSpeed.Value, "INF", StringComparison.OrdinalIgnoreCase) || string.Equals(MaxLaunchSpeed.Value, "INFINITY", StringComparison.OrdinalIgnoreCase); _parsedMaxLaunchSpeed = (_isMaxLaunchSpeedInfinite ? float.MaxValue : (float.TryParse(MaxLaunchSpeed.Value, out var result3) ? result3 : 30f)); } public static void Init(ConfigFile cfg) { InitGeneralConfig(cfg); InitRecoveryConfig(cfg); InitPersistenceConfig(cfg); InitHudConfig(cfg); InitBottomlessBagConfig(cfg); InitBalanceConfig(cfg); InitCharacterFlagsConfig(cfg); InitBlacklistCaches(); Instance.RefreshCachedConfigStrings(); } private static void InitBlacklistCaches() { Instance._blacklistCache = new LazyCachedValue>(() => (!string.IsNullOrEmpty(Instance.BodyBlacklist.Value)) ? (from s in Instance.BodyBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(StringComparer.OrdinalIgnoreCase) : new HashSet()); Instance._blacklistCacheWithClones = new LazyCachedValue>(delegate { HashSet value3 = Instance._blacklistCache.Value; HashSet hashSet3 = new HashSet(value3, StringComparer.OrdinalIgnoreCase); foreach (string item in value3) { hashSet3.Add(item + "(Clone)"); } return hashSet3; }); Instance._recoveryBlacklistCache = new LazyCachedValue>(() => (!string.IsNullOrEmpty(Instance.RecoveryObjectBlacklist.Value)) ? (from s in Instance.RecoveryObjectBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(StringComparer.OrdinalIgnoreCase) : new HashSet()); Instance._recoveryBlacklistCacheWithClones = new LazyCachedValue>(delegate { HashSet value2 = Instance._recoveryBlacklistCache.Value; HashSet hashSet2 = new HashSet(value2, StringComparer.OrdinalIgnoreCase); foreach (string item2 in value2) { hashSet2.Add(item2 + "(Clone)"); } return hashSet2; }); Instance._grabbableComponentTypesCache = new LazyCachedValue>(() => (!string.IsNullOrEmpty(Instance.GrabbableComponentTypes.Value)) ? (from s in Instance.GrabbableComponentTypes.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(StringComparer.Ordinal) : new HashSet()); Instance._grabbableKeywordBlacklistCache = new LazyCachedValue>(() => (!string.IsNullOrEmpty(Instance.GrabbableKeywordBlacklist.Value)) ? (from s in Instance.GrabbableKeywordBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(StringComparer.OrdinalIgnoreCase) : new HashSet()); Instance._persistenceBlacklistCache = new LazyCachedValue>(() => (!string.IsNullOrEmpty(Instance.PersistenceBlacklist.Value)) ? (from s in Instance.PersistenceBlacklist.Value.Split(',') select s.Trim() into s where !string.IsNullOrEmpty(s) select s).ToHashSet(StringComparer.OrdinalIgnoreCase) : new HashSet()); Instance._persistenceBlacklistCacheWithClones = new LazyCachedValue>(delegate { HashSet value = Instance._persistenceBlacklistCache.Value; HashSet hashSet = new HashSet(value, StringComparer.OrdinalIgnoreCase); foreach (string item3 in value) { hashSet.Add(item3 + "(Clone)"); } return hashSet; }); Instance.BodyBlacklist.SettingChanged += delegate { Instance._blacklistCache.Invalidate(); Instance._blacklistCacheWithClones.Invalidate(); }; Instance.RecoveryObjectBlacklist.SettingChanged += delegate { Instance._recoveryBlacklistCache.Invalidate(); Instance._recoveryBlacklistCacheWithClones.Invalidate(); }; Instance.PersistenceBlacklist.SettingChanged += delegate { Instance._persistenceBlacklistCache.Invalidate(); Instance._persistenceBlacklistCacheWithClones.Invalidate(); }; Instance.GrabbableComponentTypes.SettingChanged += delegate { Instance._grabbableComponentTypesCache.Invalidate(); }; Instance.GrabbableKeywordBlacklist.SettingChanged += delegate { Instance._grabbableKeywordBlacklistCache.Invalidate(); }; } public static void RemoveEventHandlers(EventHandler debugLogsHandler, EventHandler blacklistHandler, EventHandler recoveryBlacklistHandler, EventHandler persistenceBlacklistHandler, EventHandler grabbableComponentTypesHandler, EventHandler grabbableKeywordBlacklistHandler, EventHandler bossGrabbingHandler, EventHandler npcGrabbingHandler, EventHandler environmentGrabbingHandler, EventHandler lockedObjectGrabbingHandler, EventHandler projectileGrabbingModeHandler) { Instance.EnableDebugLogs.SettingChanged -= debugLogsHandler; Instance.BodyBlacklist.SettingChanged -= blacklistHandler; Instance.RecoveryObjectBlacklist.SettingChanged -= recoveryBlacklistHandler; Instance.PersistenceBlacklist.SettingChanged -= persistenceBlacklistHandler; 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 ClearPersistenceBlacklistCache() { Instance._persistenceBlacklistCache.Invalidate(); Instance._persistenceBlacklistCacheWithClones.Invalidate(); } public static void ClearGrabbableComponentTypesCache() { Instance._grabbableComponentTypesCache.Invalidate(); } public static void ClearGrabbableKeywordBlacklistCache() { Instance._grabbableKeywordBlacklistCache.Invalidate(); } public static void InvalidateAllCaches() { Instance._blacklistCache.Invalidate(); Instance._blacklistCacheWithClones.Invalidate(); Instance._recoveryBlacklistCache.Invalidate(); Instance._recoveryBlacklistCacheWithClones.Invalidate(); Instance._persistenceBlacklistCache.Invalidate(); Instance._persistenceBlacklistCacheWithClones.Invalidate(); Instance._grabbableComponentTypesCache.Invalidate(); Instance._grabbableKeywordBlacklistCache.Invalidate(); } public static ConfigEntry GetFlagMultiplierConfig(CharacterFlagType flag) { return (ConfigEntry)(flag switch { CharacterFlagType.Elite => Instance.EliteFlagMultiplier, CharacterFlagType.Boss => Instance.BossFlagMultiplier, CharacterFlagType.Champion => Instance.ChampionFlagMultiplier, CharacterFlagType.Player => Instance.PlayerFlagMultiplier, CharacterFlagType.Minion => Instance.MinionFlagMultiplier, CharacterFlagType.Drone => Instance.DroneFlagMultiplier, CharacterFlagType.Mechanical => Instance.MechanicalFlagMultiplier, CharacterFlagType.Void => Instance.VoidFlagMultiplier, CharacterFlagType.All => Instance.AllFlagMultiplier, _ => Instance.AllFlagMultiplier, }); } public static string GetFlagDisplayName(CharacterFlagType flag) { return flag switch { CharacterFlagType.Elite => "Elite", CharacterFlagType.Boss => "Boss", CharacterFlagType.Champion => "Champion", CharacterFlagType.Player => "Player", CharacterFlagType.Minion => "Minion", CharacterFlagType.Drone => "Drone", CharacterFlagType.Mechanical => "Mechanical", CharacterFlagType.Void => "Void", CharacterFlagType.All => "All", _ => "All", }; } public static ConfigEntry GetSlotXConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotX; } return Instance.CenterSlotX; } public static ConfigEntry GetSlotYConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotY; } return Instance.CenterSlotY; } public static ConfigEntry GetSlotScaleConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotScale; } return Instance.CenterSlotScale; } public static ConfigEntry GetSlotOpacityConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotOpacity; } return Instance.CenterSlotOpacity; } public static ConfigEntry GetSlotShowIconConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotShowIcon; } return Instance.CenterSlotShowIcon; } public static ConfigEntry GetSlotShowWeightIconConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotShowWeightIcon; } return Instance.CenterSlotShowWeightIcon; } public static ConfigEntry GetSlotShowNameConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotShowName; } return Instance.CenterSlotShowName; } public static ConfigEntry GetSlotShowHealthBarConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotShowHealthBar; } return Instance.CenterSlotShowHealthBar; } public static ConfigEntry GetSlotShowSlotNumberConfig(HudElementType slot) { if (slot != HudElementType.MainSlot) { return Instance.SideSlotShowSlotNumber; } return Instance.CenterSlotShowSlotNumber; } private static void UpdateBagUIToggles() { BaggedObjectCarousel[] array = Object.FindObjectsByType((FindObjectsSortMode)0); BaggedObjectCarousel[] array2 = array; foreach (BaggedObjectCarousel baggedObjectCarousel in array2) { baggedObjectCarousel.UpdateToggles(); } } private static void UpdateMassCapacityUIToggles() { MassCapacityUIController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); MassCapacityUIController[] array2 = array; foreach (MassCapacityUIController massCapacityUIController in array2) { massCapacityUIController.UpdateConfig(); } } private static void UpdateDamagePreviewColors() { DamagePreviewOverlay[] array = Object.FindObjectsByType((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; } private static void InitRecoveryConfig(ConfigFile cfg) { Instance.EnableRecoveryFeature = cfg.Bind("Recovery", "EnableRecoveryFeature", true, "Return bagged items that fall off the map."); Instance.EnemyRecoveryMode = cfg.Bind("Recovery", "EnemyRecoveryMode", DrifterBossGrabMod.EnemyRecoveryMode.Recover, "Behavior for bagged enemies falling off the map."); Instance.RecoverBaggedBosses = cfg.Bind("Recovery", "RecoverBaggedBosses", true, "Recover bagged bosses from the abyss."); Instance.RecoverBaggedNPCs = cfg.Bind("Recovery", "RecoverBaggedNPCs", true, "Recover bagged NPCs from the abyss."); Instance.RecoverBaggedEnvironmentObjects = cfg.Bind("Recovery", "RecoverBaggedEnvironmentObjects", true, "Recover bagged environment objects from the abyss."); } } public static class ConfigChangeNotifier { private static readonly List observers = new List(); 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) { IConfigObserver[] array = observers.ToArray(); IConfigObserver[] array2 = array; foreach (IConfigObserver configObserver in array2) { configObserver.OnConfigChanged(key, value); } } public static void Init() { PluginConfig.Instance.BreakoutTimeMultiplier.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableBossGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableNPCGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableEnvironmentGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableLockedObjectGrabbing.SettingChanged += configChangedHandler; PluginConfig.Instance.ProjectileGrabbingMode.SettingChanged += configChangedHandler; PluginConfig.Instance.MaxSmacks.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableDebugLogs.SettingChanged += configChangedHandler; PluginConfig.Instance.BodyBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.RecoveryObjectBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.GrabbableComponentTypes.SettingChanged += configChangedHandler; PluginConfig.Instance.GrabbableKeywordBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableObjectPersistence.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableAutoGrab.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistBaggedBosses.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistBaggedNPCs.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistBaggedEnvironmentObjects.SettingChanged += configChangedHandler; PluginConfig.Instance.PersistenceBlacklist.SettingChanged += configChangedHandler; PluginConfig.Instance.BottomlessBagEnabled.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableMouseWheelScrolling.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableCarouselHUD.SettingChanged += configChangedHandler; PluginConfig.Instance.CarouselSpacing.SettingChanged += configChangedHandler; PluginConfig.Instance.CarouselAnimationDuration.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotX.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotY.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotScale.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotOpacity.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotShowIcon.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotShowWeightIcon.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotShowName.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotShowHealthBar.SettingChanged += configChangedHandler; PluginConfig.Instance.CenterSlotShowSlotNumber.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotX.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotY.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotScale.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotOpacity.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotShowIcon.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotShowWeightIcon.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotShowName.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotShowHealthBar.SettingChanged += configChangedHandler; PluginConfig.Instance.SideSlotShowSlotNumber.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableDamagePreview.SettingChanged += configChangedHandler; PluginConfig.Instance.DamagePreviewColor.SettingChanged += configChangedHandler; PluginConfig.Instance.UseNewWeightIcon.SettingChanged += configChangedHandler; PluginConfig.Instance.WeightDisplayMode.SettingChanged += configChangedHandler; PluginConfig.Instance.ScaleWeightColor.SettingChanged += configChangedHandler; PluginConfig.Instance.ShowTotalMassOnWeightIcon.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableMassCapacityUI.SettingChanged += configChangedHandler; PluginConfig.Instance.MassCapacityUIPositionX.SettingChanged += configChangedHandler; PluginConfig.Instance.MassCapacityUIPositionY.SettingChanged += configChangedHandler; PluginConfig.Instance.MassCapacityUIScale.SettingChanged += configChangedHandler; PluginConfig.Instance.EnableSeparators.SettingChanged += configChangedHandler; PluginConfig.Instance.GradientIntensity.SettingChanged += configChangedHandler; PluginConfig.Instance.CapacityGradientColorStart.SettingChanged += configChangedHandler; PluginConfig.Instance.CapacityGradientColorMid.SettingChanged += configChangedHandler; PluginConfig.Instance.CapacityGradientColorEnd.SettingChanged += configChangedHandler; PluginConfig.Instance.OverencumbranceGradientColorStart.SettingChanged += configChangedHandler; PluginConfig.Instance.OverencumbranceGradientColorMid.SettingChanged += configChangedHandler; PluginConfig.Instance.OverencumbranceGradientColorEnd.SettingChanged += configChangedHandler; } public static void Cleanup() { PluginConfig.Instance.BreakoutTimeMultiplier.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableBossGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableNPCGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableEnvironmentGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableLockedObjectGrabbing.SettingChanged -= configChangedHandler; PluginConfig.Instance.ProjectileGrabbingMode.SettingChanged -= configChangedHandler; PluginConfig.Instance.MaxSmacks.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableDebugLogs.SettingChanged -= configChangedHandler; PluginConfig.Instance.BodyBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.RecoveryObjectBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.GrabbableComponentTypes.SettingChanged -= configChangedHandler; PluginConfig.Instance.GrabbableKeywordBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableObjectPersistence.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableAutoGrab.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistBaggedBosses.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistBaggedNPCs.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistBaggedEnvironmentObjects.SettingChanged -= configChangedHandler; PluginConfig.Instance.PersistenceBlacklist.SettingChanged -= configChangedHandler; PluginConfig.Instance.BottomlessBagEnabled.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableMouseWheelScrolling.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableCarouselHUD.SettingChanged -= configChangedHandler; PluginConfig.Instance.CarouselSpacing.SettingChanged -= configChangedHandler; PluginConfig.Instance.CarouselAnimationDuration.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotX.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotY.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotScale.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotOpacity.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotShowIcon.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotShowWeightIcon.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotShowName.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotShowHealthBar.SettingChanged -= configChangedHandler; PluginConfig.Instance.CenterSlotShowSlotNumber.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotX.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotY.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotScale.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotOpacity.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotShowIcon.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotShowWeightIcon.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotShowName.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotShowHealthBar.SettingChanged -= configChangedHandler; PluginConfig.Instance.SideSlotShowSlotNumber.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableDamagePreview.SettingChanged -= configChangedHandler; PluginConfig.Instance.DamagePreviewColor.SettingChanged -= configChangedHandler; PluginConfig.Instance.UseNewWeightIcon.SettingChanged -= configChangedHandler; PluginConfig.Instance.WeightDisplayMode.SettingChanged -= configChangedHandler; PluginConfig.Instance.ScaleWeightColor.SettingChanged -= configChangedHandler; PluginConfig.Instance.ShowTotalMassOnWeightIcon.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableMassCapacityUI.SettingChanged -= configChangedHandler; PluginConfig.Instance.MassCapacityUIPositionX.SettingChanged -= configChangedHandler; PluginConfig.Instance.MassCapacityUIPositionY.SettingChanged -= configChangedHandler; PluginConfig.Instance.MassCapacityUIScale.SettingChanged -= configChangedHandler; PluginConfig.Instance.EnableSeparators.SettingChanged -= configChangedHandler; PluginConfig.Instance.GradientIntensity.SettingChanged -= configChangedHandler; PluginConfig.Instance.CapacityGradientColorStart.SettingChanged -= configChangedHandler; PluginConfig.Instance.CapacityGradientColorMid.SettingChanged -= configChangedHandler; PluginConfig.Instance.CapacityGradientColorEnd.SettingChanged -= configChangedHandler; PluginConfig.Instance.OverencumbranceGradientColorStart.SettingChanged -= configChangedHandler; PluginConfig.Instance.OverencumbranceGradientColorMid.SettingChanged -= configChangedHandler; PluginConfig.Instance.OverencumbranceGradientColorEnd.SettingChanged -= configChangedHandler; } } public enum EnemyRecoveryMode { Kill, Recover } public enum ProjectileGrabbingMode { None, SurvivorOnly, AllProjectiles } public enum WeightDisplayMode { None, Multiplier, Pounds, KiloGrams } public enum StateCalculationMode { Current, All } public enum AoEDamageMode { None, Full, Split } public enum CharacterFlagType { All, Elite, Boss, Champion, Player, Minion, Drone, Mechanical, Void } public enum HudElementType { All, MainSlot, SideSlots, WeightIcon, DamagePreview, CapacityUI, StatsPanel } public enum BalanceSubTabType { All, Formulas, Multipliers, Limits } public enum PresetType { Vanilla, Intended, Minimal, Default, Balance, Hardcore, Caveman, Custom } public interface ICachedValue { T Value { get; } void Invalidate(); } public class LazyCachedValue : ICachedValue { private readonly Func _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 factory) { _factory = factory ?? throw new ArgumentNullException("factory"); } } public enum ComponentChooserDummy { SelectToToggle } public enum ComponentChooserSortMode { ByFrequency, ByProximity, ByRaycast } public class BodyColliderCache : MonoBehaviour { private Collider[]? _colliders; private bool _isInitialized; public Dictionary OriginalStates { get; } = new Dictionary(); public Collider[] GetColliders() { if (!_isInitialized) { PopulateCache(); } return _colliders ?? Array.Empty(); } private void PopulateCache() { Log.Debug("[BodyColliderCache] Populating collider cache for " + ((Object)((Component)this).gameObject).name); ModelLocator component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null) { _colliders = ((Component)component.modelTransform).GetComponentsInChildren(true); } else { _colliders = ((Component)this).GetComponentsInChildren(true); } Collider[]? colliders = _colliders; Log.Debug($"[BodyColliderCache] Found {((colliders != null) ? colliders.Length : 0)} colliders for {((Object)((Component)this).gameObject).name}"); _isInitialized = true; } public void RefreshCache() { _isInitialized = false; } public static void DisableMovementColliders(GameObject obj, Dictionary originalStates) { BodyColliderCache bodyColliderCache = obj.GetComponent(); if ((Object)(object)bodyColliderCache == (Object)null) { bodyColliderCache = obj.AddComponent(); } IEnumerable colliders = bodyColliderCache.GetColliders(); if (bodyColliderCache.OriginalStates.Count > 0 && originalStates.Count == 0) { foreach (KeyValuePair originalState in bodyColliderCache.OriginalStates) { originalStates[originalState.Key] = originalState.Value; } } foreach (Collider item in colliders) { if ((Object)(object)item != (Object)null && item.enabled) { if (!originalStates.ContainsKey(item)) { originalStates[item] = item.enabled; } if (!bodyColliderCache.OriginalStates.ContainsKey(item)) { bodyColliderCache.OriginalStates[item] = item.enabled; } item.enabled = false; } } } public static void RestoreMovementColliders(Dictionary originalStates) { foreach (KeyValuePair originalState in originalStates) { if ((Object)(object)originalState.Key != (Object)null) { originalState.Key.enabled = originalState.Value; BodyColliderCache componentInParent = ((Component)originalState.Key).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { componentInParent.OriginalStates.Remove(originalState.Key); } } } originalStates.Clear(); } } 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 const int DefaultJunkQuantity = 4; public const int MinDurabilityThreshold = 1; public const float DefaultMassPerStock = 700f; } 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 const float SlamBaseDamageCoef = 2.8f; public const float SlamMassScaling = 5f; public const float DelicateWatchDamageBonus = 0.2f; public const float NearbyDamageBonus = 0.2f; } public static class Network { public const short BaggedObjectsPersistenceMessageType = 201; public const short CycleRequestMessageType = 205; public const short UpdateBagStateMessageType = 206; public const short ClientUpdateBagStateMessageType = 207; public const short GrabObjectMessageType = 208; public const short ClientPreferencesMessageType = 209; public const short SyncConfigMessageType = 210; public const short BagStateUpdatedMessageType = 211; } public const string CloneSuffix = "(Clone)"; public const string PluginGuid = "com.pwdcat.DrifterBossGrab"; public const string PluginName = "DrifterBossGrab"; public const string PluginVersion = "1.8.0"; } public abstract class FeatureToggleBase { private bool _isPatchesApplied; public abstract string FeatureName { get; } public abstract bool IsEnabled { get; } public Harmony Harmony { get; } protected abstract void ApplyPatches(Harmony harmony); protected FeatureToggleBase() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown Harmony = new Harmony("com.pwdcat.DrifterBossGrab." + FeatureName.ToLowerInvariant()); } public virtual void Initialize() { if (IsEnabled) { ApplyPatches(Harmony); _isPatchesApplied = true; } } public virtual void Cleanup() { Harmony.UnpatchSelf(); _isPatchesApplied = false; } public void Enable() { if (IsEnabled && !_isPatchesApplied) { ApplyPatches(Harmony); _isPatchesApplied = true; } } public void Disable() { Cleanup(); } public void Toggle(bool enable) { if (enable) { Enable(); } else { Disable(); } } } [BepInPlugin("com.pwdcat.DrifterBossGrab", "DrifterBossGrab", "1.8.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DrifterBossGrabPlugin : BaseUnityPlugin, IConfigObserver { public static class Timing { public const float BatchInitializationDelay = 0.2f; public const float GrabbableComponentTypesUpdateDelay = 0.5f; public const float HudSubTabVisibilityUpdateDelay = 0.5f; public const float BalanceSubTabVisibilityUpdateDelay = 0.5f; } public static class BatchProcessing { public const int BatchSize = 50; } public static class UI { public const int IconTextureSize = 256; public const float IconRectX = 0f; public const float IconRectY = 0f; public const float IconPivotX = 0.5f; public const float IconPivotY = 0.5f; } [CompilerGenerated] private sealed class d__42 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private GameObject[] 5__2; private int 5__3; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__42(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 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 (!IsDrifterPresent) { return false; } 5__2 = Object.FindObjectsByType((FindObjectsSortMode)0); 5__3 = 0; goto IL_00d9; case 2: { <>1__state = -1; goto IL_00ca; } IL_00ca: 5__3 += 50; goto IL_00d9; IL_00d9: if (5__3 < 5__2.Length) { int num = Mathf.Min(5__3 + 50, 5__2.Length); for (int i = 5__3; i < num; i++) { GameObject val = 5__2[i]; if ((Object)(object)val != (Object)null && PluginConfig.IsGrabbable(val)) { GrabbableObjectPatches.AddSpecialObjectAttributesToGrabbableObject(val); } } if (num < 5__2.Length) { <>2__current = null; <>1__state = 2; return true; } goto IL_00ca; } 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 d__41 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__41(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 d__44 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__44(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 d__46 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__46(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateBalanceSubTabVisibility(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__102 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__102(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateBottomlessBagVisibility(); } 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 d__43 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__43(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() != (Object)null; return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__45 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__45(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateHudSubTabVisibility(); } return false; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__101 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__101(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)Instance != (Object)null) { Instance.UpdateHudSubTabVisibility(); Instance.UpdateBalanceSubTabVisibility(); Instance.UpdateBottomlessBagVisibility(); Instance.UpdateBalanceVisibility(); Instance.UpdateHudVisibility(); Instance.UpdateRecoveryVisibility(); Instance.UpdatePersistenceVisibility(); } 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 volatile bool _isSwappingPassengers; public static float LastCycleClientTime; private DrifterGrabFeature? _drifterGrabFeature; private BottomlessBagFeature? _bottomlessBagFeature; private PersistenceFeature? _persistenceFeature; private TeleporterFeature? _teleporterFeature; private BalanceFeature? _balanceFeature; private RecoveryFeature? _recoveryFeature; private bool _wasBottomlessBagEnabled; private bool _wasPersistenceEnabled; private bool _wasTeleporterEnabled; private bool _wasBalanceEnabled; private bool _wasDrifterGrabEnabled; private bool _wasRecoveryEnabled; private EventHandler? debugLogsHandler; private EventHandler? blacklistHandler; private EventHandler? recoveryBlacklistHandler; private EventHandler? persistenceBlacklistHandler; 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? teleporterToggleHandler; private EventHandler? balanceToggleHandler; private EventHandler? recoveryToggleHandler; 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); Log.EnableDebugLogs = PluginConfig.Instance.EnableDebugLogs.Value; } private void InitializeFeatures() { _drifterGrabFeature = new DrifterGrabFeature(); _drifterGrabFeature.Initialize(); _bottomlessBagFeature = new BottomlessBagFeature(); _bottomlessBagFeature.Initialize(); _persistenceFeature = new PersistenceFeature(); _persistenceFeature.Initialize(); _teleporterFeature = new TeleporterFeature(); _teleporterFeature.Initialize(); _balanceFeature = new BalanceFeature(); _balanceFeature.Initialize(); _recoveryFeature = new RecoveryFeature(); _recoveryFeature.Initialize(); PersistenceManager.Initialize(); } public void Awake() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown InitializeInstance(); InitializeCoreSystems(); InitializeFeatures(); ConfigChangeNotifier.Init(); ConfigChangeNotifier.AddObserver(this); SetupConfigurationEventHandlers(); SetupFeatureToggleHandlers(); SetupClientPreferenceHandlers(); InitializeFormulaVariables(); ((BaseUnityPlugin)this).Config.SettingChanged += OnConfigSettingChangedEvent; PresetManager.CheckAndApplyPresetOnStartup(); SyncFeatureTrackingState(); RegisterGameEvents(); BagStateSync.Init(new Harmony("com.pwdcat.DrifterBossGrab.networking")); NetworkMessageRegistry.Initialize(); InputSetup.Init(); ((Component)this).gameObject.AddComponent(); ProperSaveIntegration.Initialize(); ObjectSpawner.Initialize(); } private void RegisterGameEvents() { Run.onPlayerFirstCreatedServer += OnPlayerFirstCreated; SceneManager.activeSceneChanged += OnSceneChanged; CharacterBody.onBodyStartGlobal += OnBodyStart; VehicleSeat.onPassengerExitGlobal += OnPassengerExitGlobal; } private static void OnPassengerExitGlobal(VehicleSeat seat, GameObject passenger) { if (!((Object)(object)seat == (Object)null) && !((Object)(object)passenger == (Object)null)) { BaggedObjectPatches.HandlePassengerExit(seat, passenger); } } 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")) { IsDrifterPresent = true; GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); UIPatches.InitializeMassCapacityUI(body); } } 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_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) IsDrifterPresent = false; ZoneDetectionPatches.ResetZoneInversionDetection(); SceneExitPatches.ResetCaptureFlag(); 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(d__41))] private static IEnumerator DelayedEnsureSpecialObjectAttributes() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__41(0); } [IteratorStateMachine(typeof(d__42))] private static IEnumerator DelayedBatchSpecialObjectAttributesInitialization() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__42(0); } [IteratorStateMachine(typeof(d__43))] private static IEnumerator DelayedUpdateDrifterPresence() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__43(0); } [IteratorStateMachine(typeof(d__44))] private static IEnumerator DelayedGrabbableComponentTypesUpdate() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__44(0); } [IteratorStateMachine(typeof(d__45))] private static IEnumerator DelayedUpdateHudSubTabVisibility() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__45(0); } [IteratorStateMachine(typeof(d__46))] private static IEnumerator DelayedUpdateBalanceSubTabVisibility() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__46(0); } public void OnDestroy() { Run.onPlayerFirstCreatedServer -= OnPlayerFirstCreated; SceneManager.activeSceneChanged -= OnSceneChanged; CharacterBody.onBodyStartGlobal -= OnBodyStart; VehicleSeat.onPassengerExitGlobal -= OnPassengerExitGlobal; ConfigChangeNotifier.RemoveObserver(this); ConfigChangeNotifier.Cleanup(); RemoveConfigurationEventHandlers(); RemovePersistenceEventHandlers(); RemoveFeatureToggleHandlers(); RemoveClientPreferenceHandlers(); CleanupFeatures(); StopCoroutines(); UIPatches.CleanupMassCapacityUI(); BagStateSync.Cleanup(); NetworkMessageRegistry.Cleanup(); ProperSaveIntegration.Cleanup(); } private void CleanupFeatures() { PersistenceManager.Cleanup(); _drifterGrabFeature?.Cleanup(); _bottomlessBagFeature?.Cleanup(); _persistenceFeature?.Cleanup(); _teleporterFeature?.Cleanup(); _balanceFeature?.Cleanup(); _recoveryFeature?.Cleanup(); } private void StopCoroutines() { if (_grabbableComponentTypesUpdateCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_grabbableComponentTypesUpdateCoroutine); _grabbableComponentTypesUpdateCoroutine = null; } } public void OnConfigChanged(string key, object value) { } public void Start() { if (RooInstalled) { SetupRiskOfOptions(); } } public void Update() { if (PluginConfig.Instance.BottomlessBagEnabled.Value) { BottomlessBagPatches.HandleInput(); } } private void SyncFeatureTrackingState() { _wasBottomlessBagEnabled = PluginConfig.Instance.BottomlessBagEnabled.Value; _wasPersistenceEnabled = PluginConfig.Instance.EnableObjectPersistence.Value; _wasTeleporterEnabled = PluginConfig.Instance.EnableObjectPersistence.Value && !PluginConfig.IsPersistenceBlacklisted("Teleporter"); _wasBalanceEnabled = PluginConfig.Instance.EnableBalance.Value; _wasRecoveryEnabled = PluginConfig.Instance.EnableRecoveryFeature.Value; _wasDrifterGrabEnabled = PluginConfig.Instance.SelectedPreset.Value != PresetType.Vanilla; } private void InitializeFormulaVariables() { FormulaRegistry.RegisterVariable("H", (CharacterBody? body) => (body == null) ? 0f : body.maxHealth, "Character's max health"); FormulaRegistry.RegisterVariable("L", (CharacterBody? body) => (body == null) ? 1f : body.level, "Character's level"); FormulaRegistry.RegisterVariable("C", (CharacterBody? body) => (!((Object)(object)body != (Object)null) || !((Object)(object)body.skillLocator != (Object)null) || !((Object)(object)body.skillLocator.utility != (Object)null)) ? 1f : ((float)body.skillLocator.utility.maxStock), "Utility stock count"); FormulaRegistry.RegisterVariable("S", (CharacterBody? body) => (!Object.op_Implicit((Object)(object)Run.instance)) ? 1 : (Run.instance.stageClearCount + 1), "Current stage number"); FormulaRegistry.RegisterVariable("MC", (CharacterBody? body) => PluginConfig.Instance.ParsedMassCap, "Mass capacity limit (from config)"); FormulaRegistry.RegisterVariable("BH", (CharacterBody? body) => body?.baseMaxHealth ?? 0f, "Character's base max health"); FormulaRegistry.RegisterVariable("B", (CharacterBody? body) => 0f, "Base mass (for flag multipliers)"); Log.Debug("[FormulaInit] Default variables initialized"); } private void SetupConfigurationEventHandlers() { SetupDebugLogsHandler(); SetupBlacklistHandlers(); SetupGrabbableHandlers(); SetupGrabbingHandlers(); SetupPersistenceHandlers(); SetupCharacterFlagMultiplierHandlers(); SetupHudSubTabHandlers(); SetupBalanceSubTabHandlers(); SetupPresetHandlers(); SetupAutoSwitchToCustomHandlers(); PersistenceManager.UpdateCachedConfig(); } private void SetupDebugLogsHandler() { debugLogsHandler = delegate { Log.EnableDebugLogs = 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; persistenceBlacklistHandler = delegate { PluginConfig.ClearPersistenceBlacklistCache(); }; PluginConfig.Instance.PersistenceBlacklist.SettingChanged += persistenceBlacklistHandler; } 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 SetupCharacterFlagMultiplierHandlers() { PluginConfig.Instance.SelectedFlag.SettingChanged += delegate { CharacterFlagType value3 = PluginConfig.Instance.SelectedFlag.Value; ConfigEntry flagMultiplierConfig2 = PluginConfig.GetFlagMultiplierConfig(value3); PluginConfig.Instance.SelectedFlagMultiplier.Value = flagMultiplierConfig2.Value.ToString(); RefreshStringInputFieldUI(PluginConfig.Instance.SelectedFlagMultiplier); }; PluginConfig.Instance.SelectedFlagMultiplier.SettingChanged += delegate { CharacterFlagType value = PluginConfig.Instance.SelectedFlag.Value; string value2 = PluginConfig.Instance.SelectedFlagMultiplier.Value; string text = FormulaParser.Validate(value2); if (text != null) { Log.Warning($"[ConfigValidation] Invalid FlagMultiplier formula for {value}: {text}"); } else { ConfigEntry flagMultiplierConfig = PluginConfig.GetFlagMultiplierConfig(value); if (flagMultiplierConfig != null && flagMultiplierConfig.Value != value2) { flagMultiplierConfig.Value = value2; } RecalculateAllBaggedMasses(); } }; PluginConfig.Instance.AllFlagMultiplier.SettingChanged += delegate { RecalculateAllBaggedMasses(); }; } private void SetupHudSubTabHandlers() { PluginConfig.Instance.SelectedHudElement.SettingChanged += delegate { UpdateHudSubTabVisibility(); }; } private void SetupBalanceSubTabHandlers() { PluginConfig.Instance.SelectedBalanceSubTab.SettingChanged += delegate { UpdateBalanceSubTabVisibility(); }; } private void SetupPresetHandlers() { PluginConfig.Instance.SelectedPreset.SettingChanged += delegate { PresetType value = PluginConfig.Instance.SelectedPreset.Value; PluginConfig.Instance.LastSelectedPreset.Value = value; PresetManager.ApplyPreset(value); bool flag = value != PresetType.Vanilla; if (flag != _wasDrifterGrabEnabled) { _drifterGrabFeature?.Toggle(flag); _wasDrifterGrabEnabled = flag; } }; } private void SetupAutoSwitchToCustomHandlers() { RegisterAutoSwitchHandlers(PluginConfig.Instance.EnableBossGrabbing, PluginConfig.Instance.EnableNPCGrabbing, PluginConfig.Instance.EnableEnvironmentGrabbing, PluginConfig.Instance.EnableLockedObjectGrabbing, PluginConfig.Instance.ProjectileGrabbingMode, PluginConfig.Instance.EnableDebugLogs, PluginConfig.Instance.EnableConfigSync); RegisterPresetOnlyHandlers(PluginConfig.Instance.BreakoutTimeMultiplier, PluginConfig.Instance.MaxSmacks, PluginConfig.Instance.EnableObjectPersistence, PluginConfig.Instance.EnableAutoGrab, PluginConfig.Instance.PersistBaggedBosses, PluginConfig.Instance.PersistBaggedNPCs, PluginConfig.Instance.PersistBaggedEnvironmentObjects, PluginConfig.Instance.AutoGrabDelay, PluginConfig.Instance.BottomlessBagEnabled, PluginConfig.Instance.EnableStockRefreshClamping, PluginConfig.Instance.EnableSuccessiveGrabStockRefresh, PluginConfig.Instance.CycleCooldown, PluginConfig.Instance.PlayAnimationOnCycle, PluginConfig.Instance.EnableMouseWheelScrolling, PluginConfig.Instance.InverseMouseWheelScrolling, PluginConfig.Instance.AutoPromoteMainSeat, PluginConfig.Instance.PrioritizeMainSeat, PluginConfig.Instance.EnableCarouselHUD, PluginConfig.Instance.CarouselSpacing, PluginConfig.Instance.CarouselAnimationDuration, PluginConfig.Instance.CenterSlotX, PluginConfig.Instance.CenterSlotY, PluginConfig.Instance.CenterSlotScale, PluginConfig.Instance.CenterSlotOpacity, PluginConfig.Instance.CenterSlotShowIcon, PluginConfig.Instance.CenterSlotShowWeightIcon, PluginConfig.Instance.CenterSlotShowName, PluginConfig.Instance.CenterSlotShowHealthBar, PluginConfig.Instance.CenterSlotShowSlotNumber, PluginConfig.Instance.SideSlotX, PluginConfig.Instance.SideSlotY, PluginConfig.Instance.SideSlotScale, PluginConfig.Instance.SideSlotOpacity, PluginConfig.Instance.SideSlotShowIcon, PluginConfig.Instance.SideSlotShowWeightIcon, PluginConfig.Instance.SideSlotShowName, PluginConfig.Instance.SideSlotShowHealthBar, PluginConfig.Instance.SideSlotShowSlotNumber, PluginConfig.Instance.EnableDamagePreview, PluginConfig.Instance.DamagePreviewColor, PluginConfig.Instance.UseNewWeightIcon, PluginConfig.Instance.WeightDisplayMode, PluginConfig.Instance.ScaleWeightColor, PluginConfig.Instance.ShowTotalMassOnWeightIcon, PluginConfig.Instance.EnableMassCapacityUI, PluginConfig.Instance.MassCapacityUIPositionX, PluginConfig.Instance.MassCapacityUIPositionY, PluginConfig.Instance.MassCapacityUIScale, PluginConfig.Instance.EnableSeparators, PluginConfig.Instance.GradientIntensity, PluginConfig.Instance.CapacityGradientColorStart, PluginConfig.Instance.CapacityGradientColorMid, PluginConfig.Instance.CapacityGradientColorEnd, PluginConfig.Instance.OverencumbranceGradientColorStart, PluginConfig.Instance.OverencumbranceGradientColorMid, PluginConfig.Instance.OverencumbranceGradientColorEnd, PluginConfig.Instance.EnableBaggedObjectInfo, PluginConfig.Instance.BaggedObjectInfoX, PluginConfig.Instance.BaggedObjectInfoY, PluginConfig.Instance.BaggedObjectInfoScale, PluginConfig.Instance.BaggedObjectInfoColor, PluginConfig.Instance.EnableRecoveryFeature, PluginConfig.Instance.EnemyRecoveryMode, PluginConfig.Instance.RecoverBaggedBosses, PluginConfig.Instance.RecoverBaggedNPCs, PluginConfig.Instance.RecoverBaggedEnvironmentObjects, PluginConfig.Instance.EnableBalance, PluginConfig.Instance.AoEDamageDistribution, PluginConfig.Instance.SlotScalingFormula, PluginConfig.Instance.MassCapacityFormula, PluginConfig.Instance.SlamDamageFormula, PluginConfig.Instance.EliteFlagMultiplier, PluginConfig.Instance.BossFlagMultiplier, PluginConfig.Instance.ChampionFlagMultiplier, PluginConfig.Instance.PlayerFlagMultiplier, PluginConfig.Instance.MinionFlagMultiplier, PluginConfig.Instance.DroneFlagMultiplier, PluginConfig.Instance.MechanicalFlagMultiplier, PluginConfig.Instance.VoidFlagMultiplier, PluginConfig.Instance.OverencumbranceMax, PluginConfig.Instance.StateCalculationMode, PluginConfig.Instance.MovespeedPenaltyFormula, PluginConfig.Instance.BagScaleCap, PluginConfig.Instance.SearchRadiusMultiplier, PluginConfig.Instance.MaxLaunchSpeed, PluginConfig.Instance.MassCap); } private void RecalculateAllBaggedMasses() { DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (DrifterBagController controller in array) { BagPassengerManager.ForceRecalculateMass(controller); } } private void OnConfigSettingChangedEvent(object sender, SettingChangedEventArgs args) { if (NetworkServer.active) { ConfigSyncHandler.BroadcastConfigToClients(); } } private void OnClientPreferenceSettingChanged(object sender, EventArgs args) { if (!NetworkClient.active) { return; } foreach (PlayerCharacterMasterController instance in PlayerCharacterMasterController.instances) { if (!((NetworkBehaviour)instance).hasAuthority || !Object.op_Implicit((Object)(object)instance.master) || !Object.op_Implicit((Object)(object)instance.master.GetBody())) { continue; } DrifterBagController component = ((Component)instance.master.GetBody()).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { continue; } BottomlessBagNetworkController component2 = ((Component)component).GetComponent(); if (Object.op_Implicit((Object)(object)component2) && ((NetworkBehaviour)component2).hasAuthority) { NetworkIdentity component3 = ((Component)component2).GetComponent(); if ((Object)(object)component3 != (Object)null) { CycleNetworkHandler.SendClientPreferences(component3, PluginConfig.Instance.AutoPromoteMainSeat.Value, PluginConfig.Instance.PrioritizeMainSeat.Value); } } } } private void SetupFeatureToggleHandlers() { bottomlessBagToggleHandler = delegate { bool value4 = PluginConfig.Instance.BottomlessBagEnabled.Value; if (value4 != _wasBottomlessBagEnabled) { _bottomlessBagFeature?.Toggle(value4); _wasBottomlessBagEnabled = value4; UpdateBottomlessBagVisibility(); } }; PluginConfig.Instance.BottomlessBagEnabled.SettingChanged += bottomlessBagToggleHandler; persistenceToggleHandler = delegate { bool value3 = PluginConfig.Instance.EnableObjectPersistence.Value; if (value3 != _wasPersistenceEnabled) { _persistenceFeature?.Toggle(value3); _wasPersistenceEnabled = value3; UpdatePersistenceVisibility(); } }; PluginConfig.Instance.EnableObjectPersistence.SettingChanged += persistenceToggleHandler; teleporterToggleHandler = delegate { bool flag = PluginConfig.Instance.EnableObjectPersistence.Value && !PluginConfig.IsPersistenceBlacklisted("Teleporter"); if (flag != _wasTeleporterEnabled) { _teleporterFeature?.Toggle(flag); _wasTeleporterEnabled = flag; } }; PluginConfig.Instance.EnableObjectPersistence.SettingChanged += teleporterToggleHandler; PluginConfig.Instance.PersistenceBlacklist.SettingChanged += teleporterToggleHandler; balanceToggleHandler = delegate { bool value2 = PluginConfig.Instance.EnableBalance.Value; if (value2 != _wasBalanceEnabled) { _balanceFeature?.Toggle(value2); _wasBalanceEnabled = value2; UpdateBalanceVisibility(); } }; PluginConfig.Instance.EnableBalance.SettingChanged += balanceToggleHandler; recoveryToggleHandler = delegate { bool value = PluginConfig.Instance.EnableRecoveryFeature.Value; if (value != _wasRecoveryEnabled) { _recoveryFeature?.Toggle(value); _wasRecoveryEnabled = value; UpdateRecoveryVisibility(); } }; PluginConfig.Instance.EnableRecoveryFeature.SettingChanged += recoveryToggleHandler; PluginConfig.Instance.EnableCarouselHUD.SettingChanged += delegate { UpdateHudVisibility(); }; PluginConfig.Instance.EnableDamagePreview.SettingChanged += delegate { UpdateHudVisibility(); }; PluginConfig.Instance.EnableMassCapacityUI.SettingChanged += delegate { UpdateHudVisibility(); }; PluginConfig.Instance.EnableBaggedObjectInfo.SettingChanged += delegate { UpdateHudVisibility(); }; } private void SetupClientPreferenceHandlers() { PluginConfig.Instance.AutoPromoteMainSeat.SettingChanged += OnClientPreferenceSettingChanged; PluginConfig.Instance.PrioritizeMainSeat.SettingChanged += OnClientPreferenceSettingChanged; } private void RemoveConfigurationEventHandlers() { ((BaseUnityPlugin)this).Config.SettingChanged -= OnConfigSettingChangedEvent; PluginConfig.RemoveEventHandlers(debugLogsHandler ?? ((EventHandler)delegate { }), blacklistHandler ?? ((EventHandler)delegate { }), recoveryBlacklistHandler ?? ((EventHandler)delegate { }), persistenceBlacklistHandler ?? ((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.EnableObjectPersistence.SettingChanged -= teleporterToggleHandler; PluginConfig.Instance.PersistenceBlacklist.SettingChanged -= teleporterToggleHandler; PluginConfig.Instance.EnableBalance.SettingChanged -= balanceToggleHandler; PluginConfig.Instance.EnableRecoveryFeature.SettingChanged -= recoveryToggleHandler; } private void RemoveClientPreferenceHandlers() { PluginConfig.Instance.AutoPromoteMainSeat.SettingChanged -= OnClientPreferenceSettingChanged; PluginConfig.Instance.PrioritizeMainSeat.SettingChanged -= OnClientPreferenceSettingChanged; } private void OnAutoSwitchSettingChanged(object sender, EventArgs args) { PresetManager.OnSettingModified(); PresetManager.RefreshPresetDropdownUI(); } private void OnPresetOnlySettingChanged(object sender, EventArgs args) { PresetManager.OnSettingModified(); } private void RegisterAutoSwitchHandlers(params object[] configEntries) { foreach (object obj in configEntries) { EventInfo @event = obj.GetType().GetEvent("SettingChanged"); if (@event != null) { MethodInfo method = typeof(DrifterBossGrabPlugin).GetMethod("OnAutoSwitchSettingChanged", BindingFlags.Instance | BindingFlags.NonPublic); Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, this, method); @event.AddEventHandler(obj, handler); } } } private void RegisterPresetOnlyHandlers(params object[] configEntries) { foreach (object obj in configEntries) { EventInfo @event = obj.GetType().GetEvent("SettingChanged"); if (@event != null) { MethodInfo method = typeof(DrifterBossGrabPlugin).GetMethod("OnPresetOnlySettingChanged", BindingFlags.Instance | BindingFlags.NonPublic); Delegate handler = Delegate.CreateDelegate(@event.EventHandlerType, this, method); @event.AddEventHandler(obj, handler); } } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void SetupRiskOfOptions() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) if (!RooInstalled) { return; } ModSettingsManager.SetModDescription("Allows Drifter to grab bosses, NPCs, and environment objects.", "com.pwdcat.DrifterBossGrab", "DrifterBossGrab"); try { Assembly executingAssembly = Assembly.GetExecutingAssembly(); string directoryName = Path.GetDirectoryName(executingAssembly.Location); string text = Path.Combine(directoryName, "icon.png"); if (File.Exists(text)) { byte[] array = File.ReadAllBytes(text); 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))); } else { Log.Warning("[UI] Mod icon not found at: " + text); } } catch (Exception ex) { Log.Warning("[UI] Failed to load mod icon: " + ex.Message); } AddConfigurationOptions(); ((MonoBehaviour)this).StartCoroutine(DelayedUpdateHudSubTabVisibility()); ((MonoBehaviour)this).StartCoroutine(DelayedUpdateBalanceSubTabVisibility()); ((MonoBehaviour)this).StartCoroutine(DelayedUpdateBottomlessBagVisibility()); SetupRiskOfOptionsEvents(); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void AddConfigurationOptions() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Expected O, but got Unknown //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Expected O, but got Unknown //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Expected O, but got Unknown //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Expected O, but got Unknown //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Expected O, but got Unknown //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Expected O, but got Unknown //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Expected O, but got Unknown //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Expected O, but got Unknown //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Expected O, but got Unknown //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Expected O, but got Unknown //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0208: Expected O, but got Unknown //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Expected O, but got Unknown //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Expected O, but got Unknown //IL_0236: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0256: Expected O, but got Unknown //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Expected O, but got Unknown //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Expected O, but got Unknown //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Expected O, but got Unknown //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Expected O, but got Unknown //IL_02d2: Unknown result type (might be due to invalid IL or missing references) //IL_02dc: Expected O, but got Unknown //IL_02e6: Unknown result type (might be due to invalid IL or missing references) //IL_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Expected O, but got Unknown //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_030b: Expected O, but got Unknown //IL_0315: Unknown result type (might be due to invalid IL or missing references) //IL_031a: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Expected O, but got Unknown //IL_0330: Unknown result type (might be due to invalid IL or missing references) //IL_033a: Expected O, but got Unknown //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0354: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Expected O, but got Unknown //IL_035f: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Expected O, but got Unknown //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_0378: Unknown result type (might be due to invalid IL or missing references) //IL_0383: Unknown result type (might be due to invalid IL or missing references) //IL_0393: Expected O, but got Unknown //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Expected O, but got Unknown //IL_03a2: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Expected O, but got Unknown //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03c7: Expected O, but got Unknown //IL_03d1: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03e6: Expected O, but got Unknown //IL_03e1: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Expected O, but got Unknown //IL_03f5: Unknown result type (might be due to invalid IL or missing references) //IL_03fa: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Expected O, but got Unknown //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Expected O, but got Unknown //IL_0419: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_042e: Expected O, but got Unknown //IL_0429: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Expected O, but got Unknown //IL_043d: Unknown result type (might be due to invalid IL or missing references) //IL_0442: Unknown result type (might be due to invalid IL or missing references) //IL_044d: Unknown result type (might be due to invalid IL or missing references) //IL_045d: Expected O, but got Unknown //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_0462: Expected O, but got Unknown //IL_046c: Unknown result type (might be due to invalid IL or missing references) //IL_0471: Unknown result type (might be due to invalid IL or missing references) //IL_047c: Unknown result type (might be due to invalid IL or missing references) //IL_048c: Expected O, but got Unknown //IL_0487: Unknown result type (might be due to invalid IL or missing references) //IL_0491: Expected O, but got Unknown //IL_049b: Unknown result type (might be due to invalid IL or missing references) //IL_04a0: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Expected O, but got Unknown //IL_04b6: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Expected O, but got Unknown //IL_04ca: Unknown result type (might be due to invalid IL or missing references) //IL_04cf: Unknown result type (might be due to invalid IL or missing references) //IL_04da: Unknown result type (might be due to invalid IL or missing references) //IL_04ea: Expected O, but got Unknown //IL_04e5: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Expected O, but got Unknown //IL_04f9: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0509: Unknown result type (might be due to invalid IL or missing references) //IL_0514: Unknown result type (might be due to invalid IL or missing references) //IL_051f: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_053a: Expected O, but got Unknown //IL_0535: Unknown result type (might be due to invalid IL or missing references) //IL_053f: Expected O, but got Unknown //IL_0549: Unknown result type (might be due to invalid IL or missing references) //IL_054e: Unknown result type (might be due to invalid IL or missing references) //IL_0559: Unknown result type (might be due to invalid IL or missing references) //IL_0569: Expected O, but got Unknown //IL_0564: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Expected O, but got Unknown //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_057d: Unknown result type (might be due to invalid IL or missing references) //IL_0588: Unknown result type (might be due to invalid IL or missing references) //IL_0598: Expected O, but got Unknown //IL_0593: Unknown result type (might be due to invalid IL or missing references) //IL_059d: Expected O, but got Unknown //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_05ac: Unknown result type (might be due to invalid IL or missing references) //IL_05b7: Unknown result type (might be due to invalid IL or missing references) //IL_05c7: 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_05db: Unknown result type (might be due to invalid IL or missing references) //IL_05e6: Unknown result type (might be due to invalid IL or missing references) //IL_05f6: Expected O, but got Unknown //IL_05f1: Unknown result type (might be due to invalid IL or missing references) //IL_05fb: Expected O, but got Unknown //IL_0605: Unknown result type (might be due to invalid IL or missing references) //IL_060a: Unknown result type (might be due to invalid IL or missing references) //IL_0615: Unknown result type (might be due to invalid IL or missing references) //IL_0625: Expected O, but got Unknown //IL_0620: Unknown result type (might be due to invalid IL or missing references) //IL_062a: Expected O, but got Unknown //IL_0634: Unknown result type (might be due to invalid IL or missing references) //IL_0639: Unknown result type (might be due to invalid IL or missing references) //IL_0644: Unknown result type (might be due to invalid IL or missing references) //IL_0654: Expected O, but got Unknown //IL_064f: Unknown result type (might be due to invalid IL or missing references) //IL_0659: Expected O, but got Unknown //IL_0663: Unknown result type (might be due to invalid IL or missing references) //IL_0668: Unknown result type (might be due to invalid IL or missing references) //IL_0673: Unknown result type (might be due to invalid IL or missing references) //IL_0683: Expected O, but got Unknown //IL_067e: Unknown result type (might be due to invalid IL or missing references) //IL_0688: Expected O, but got Unknown //IL_0692: Unknown result type (might be due to invalid IL or missing references) //IL_0697: Unknown result type (might be due to invalid IL or missing references) //IL_06a2: Unknown result type (might be due to invalid IL or missing references) //IL_06b2: Expected O, but got Unknown //IL_06ad: Unknown result type (might be due to invalid IL or missing references) //IL_06b7: Expected O, but got Unknown //IL_06c1: Unknown result type (might be due to invalid IL or missing references) //IL_06c6: Unknown result type (might be due to invalid IL or missing references) //IL_06d1: Unknown result type (might be due to invalid IL or missing references) //IL_06e1: Expected O, but got Unknown //IL_06dc: Unknown result type (might be due to invalid IL or missing references) //IL_06e6: Expected O, but got Unknown //IL_06f0: Unknown result type (might be due to invalid IL or missing references) //IL_06f5: Unknown result type (might be due to invalid IL or missing references) //IL_0700: Unknown result type (might be due to invalid IL or missing references) //IL_0710: Expected O, but got Unknown //IL_070b: Unknown result type (might be due to invalid IL or missing references) //IL_0715: Expected O, but got Unknown //IL_071f: Unknown result type (might be due to invalid IL or missing references) //IL_0724: Unknown result type (might be due to invalid IL or missing references) //IL_072f: Unknown result type (might be due to invalid IL or missing references) //IL_073f: Expected O, but got Unknown //IL_073a: Unknown result type (might be due to invalid IL or missing references) //IL_0744: Expected O, but got Unknown //IL_074e: Unknown result type (might be due to invalid IL or missing references) //IL_0753: Unknown result type (might be due to invalid IL or missing references) //IL_075e: Unknown result type (might be due to invalid IL or missing references) //IL_076e: Expected O, but got Unknown //IL_0769: Unknown result type (might be due to invalid IL or missing references) //IL_0773: Expected O, but got Unknown //IL_077d: Unknown result type (might be due to invalid IL or missing references) //IL_0782: Unknown result type (might be due to invalid IL or missing references) //IL_078d: Unknown result type (might be due to invalid IL or missing references) //IL_079d: Expected O, but got Unknown //IL_0798: Unknown result type (might be due to invalid IL or missing references) //IL_07a2: Expected O, but got Unknown //IL_07ac: Unknown result type (might be due to invalid IL or missing references) //IL_07b1: Unknown result type (might be due to invalid IL or missing references) //IL_07bc: Unknown result type (might be due to invalid IL or missing references) //IL_07cc: Expected O, but got Unknown //IL_07c7: Unknown result type (might be due to invalid IL or missing references) //IL_07d1: Expected O, but got Unknown //IL_07db: Unknown result type (might be due to invalid IL or missing references) //IL_07e0: Unknown result type (might be due to invalid IL or missing references) //IL_07eb: Unknown result type (might be due to invalid IL or missing references) //IL_07fb: Expected O, but got Unknown //IL_07f6: Unknown result type (might be due to invalid IL or missing references) //IL_0800: Expected O, but got Unknown //IL_080a: Unknown result type (might be due to invalid IL or missing references) //IL_080f: Unknown result type (might be due to invalid IL or missing references) //IL_081a: Unknown result type (might be due to invalid IL or missing references) //IL_0825: Unknown result type (might be due to invalid IL or missing references) //IL_0830: Unknown result type (might be due to invalid IL or missing references) //IL_083b: Unknown result type (might be due to invalid IL or missing references) //IL_084b: Expected O, but got Unknown //IL_0846: Unknown result type (might be due to invalid IL or missing references) //IL_0850: Expected O, but got Unknown //IL_085a: Unknown result type (might be due to invalid IL or missing references) //IL_085f: Unknown result type (might be due to invalid IL or missing references) //IL_086a: Unknown result type (might be due to invalid IL or missing references) //IL_087a: Expected O, but got Unknown //IL_0875: Unknown result type (might be due to invalid IL or missing references) //IL_087f: Expected O, but got Unknown //IL_0889: Unknown result type (might be due to invalid IL or missing references) //IL_088e: Unknown result type (might be due to invalid IL or missing references) //IL_0899: Unknown result type (might be due to invalid IL or missing references) //IL_08a9: Expected O, but got Unknown //IL_08a4: Unknown result type (might be due to invalid IL or missing references) //IL_08ae: Expected O, but got Unknown //IL_08b8: Unknown result type (might be due to invalid IL or missing references) //IL_08bd: Unknown result type (might be due to invalid IL or missing references) //IL_08c8: Unknown result type (might be due to invalid IL or missing references) //IL_08d8: Expected O, but got Unknown //IL_08d3: Unknown result type (might be due to invalid IL or missing references) //IL_08dd: Expected O, but got Unknown //IL_08e7: Unknown result type (might be due to invalid IL or missing references) //IL_08ec: Unknown result type (might be due to invalid IL or missing references) //IL_08f7: Unknown result type (might be due to invalid IL or missing references) //IL_0907: Expected O, but got Unknown //IL_0902: Unknown result type (might be due to invalid IL or missing references) //IL_090c: Expected O, but got Unknown //IL_0916: Unknown result type (might be due to invalid IL or missing references) //IL_091b: Unknown result type (might be due to invalid IL or missing references) //IL_0926: Unknown result type (might be due to invalid IL or missing references) //IL_0936: Expected O, but got Unknown //IL_0931: Unknown result type (might be due to invalid IL or missing references) //IL_093b: Expected O, but got Unknown //IL_0945: Unknown result type (might be due to invalid IL or missing references) //IL_094a: Unknown result type (might be due to invalid IL or missing references) //IL_0955: Unknown result type (might be due to invalid IL or missing references) //IL_0965: Expected O, but got Unknown //IL_0960: Unknown result type (might be due to invalid IL or missing references) //IL_096a: Expected O, but got Unknown //IL_0974: Unknown result type (might be due to invalid IL or missing references) //IL_0979: Unknown result type (might be due to invalid IL or missing references) //IL_0984: Unknown result type (might be due to invalid IL or missing references) //IL_0994: Expected O, but got Unknown //IL_098f: Unknown result type (might be due to invalid IL or missing references) //IL_0999: Expected O, but got Unknown //IL_09a3: Unknown result type (might be due to invalid IL or missing references) //IL_09a8: Unknown result type (might be due to invalid IL or missing references) //IL_09b8: Expected O, but got Unknown //IL_09b3: Unknown result type (might be due to invalid IL or missing references) //IL_09bd: Expected O, but got Unknown //IL_09c7: Unknown result type (might be due to invalid IL or missing references) //IL_09cc: Unknown result type (might be due to invalid IL or missing references) //IL_09dc: Expected O, but got Unknown //IL_09d7: Unknown result type (might be due to invalid IL or missing references) //IL_09e1: Expected O, but got Unknown //IL_09eb: Unknown result type (might be due to invalid IL or missing references) //IL_09f0: Unknown result type (might be due to invalid IL or missing references) //IL_0a00: Expected O, but got Unknown //IL_09fb: Unknown result type (might be due to invalid IL or missing references) //IL_0a05: Expected O, but got Unknown //IL_0a0f: Unknown result type (might be due to invalid IL or missing references) //IL_0a14: Unknown result type (might be due to invalid IL or missing references) //IL_0a24: Expected O, but got Unknown //IL_0a1f: Unknown result type (might be due to invalid IL or missing references) //IL_0a29: Expected O, but got Unknown //IL_0a33: Unknown result type (might be due to invalid IL or missing references) //IL_0a38: Unknown result type (might be due to invalid IL or missing references) //IL_0a48: Expected O, but got Unknown //IL_0a43: Unknown result type (might be due to invalid IL or missing references) //IL_0a4d: Expected O, but got Unknown //IL_0a57: Unknown result type (might be due to invalid IL or missing references) //IL_0a5c: Unknown result type (might be due to invalid IL or missing references) //IL_0a6c: Expected O, but got Unknown //IL_0a67: Unknown result type (might be due to invalid IL or missing references) //IL_0a71: Expected O, but got Unknown //IL_0a7b: Unknown result type (might be due to invalid IL or missing references) //IL_0a80: Unknown result type (might be due to invalid IL or missing references) //IL_0a90: Expected O, but got Unknown //IL_0a8b: Unknown result type (might be due to invalid IL or missing references) //IL_0a95: Expected O, but got Unknown //IL_0a9f: Unknown result type (might be due to invalid IL or missing references) //IL_0aa4: Unknown result type (might be due to invalid IL or missing references) //IL_0ab4: Expected O, but got Unknown //IL_0aaf: Unknown result type (might be due to invalid IL or missing references) //IL_0ab9: Expected O, but got Unknown //IL_0ac3: Unknown result type (might be due to invalid IL or missing references) //IL_0ac8: Unknown result type (might be due to invalid IL or missing references) //IL_0ad8: Expected O, but got Unknown //IL_0ad3: Unknown result type (might be due to invalid IL or missing references) //IL_0add: Expected O, but got Unknown //IL_0ae7: Unknown result type (might be due to invalid IL or missing references) //IL_0aec: Unknown result type (might be due to invalid IL or missing references) //IL_0afc: Expected O, but got Unknown //IL_0af7: Unknown result type (might be due to invalid IL or missing references) //IL_0b01: Expected O, but got Unknown //IL_0b0b: Unknown result type (might be due to invalid IL or missing references) //IL_0b10: Unknown result type (might be due to invalid IL or missing references) //IL_0b20: Expected O, but got Unknown //IL_0b1b: Unknown result type (might be due to invalid IL or missing references) //IL_0b25: Expected O, but got Unknown //IL_0b2f: Unknown result type (might be due to invalid IL or missing references) //IL_0b34: Unknown result type (might be due to invalid IL or missing references) //IL_0b44: Expected O, but got Unknown //IL_0b3f: Unknown result type (might be due to invalid IL or missing references) //IL_0b49: Expected O, but got Unknown //IL_0b53: Unknown result type (might be due to invalid IL or missing references) //IL_0b58: Unknown result type (might be due to invalid IL or missing references) //IL_0b68: Expected O, but got Unknown //IL_0b63: Unknown result type (might be due to invalid IL or missing references) //IL_0b6d: Expected O, but got Unknown //IL_0b77: Unknown result type (might be due to invalid IL or missing references) //IL_0b7c: Unknown result type (might be due to invalid IL or missing references) //IL_0b8c: Expected O, but got Unknown //IL_0b87: Unknown result type (might be due to invalid IL or missing references) //IL_0b91: Expected O, but got Unknown //IL_0b9b: Unknown result type (might be due to invalid IL or missing references) //IL_0ba0: Unknown result type (might be due to invalid IL or missing references) //IL_0bb0: Expected O, but got Unknown //IL_0bab: Unknown result type (might be due to invalid IL or missing references) //IL_0bb5: Expected O, but got Unknown //IL_0bbf: Unknown result type (might be due to invalid IL or missing references) //IL_0bc4: Unknown result type (might be due to invalid IL or missing references) //IL_0bd4: Expected O, but got Unknown //IL_0bcf: Unknown result type (might be due to invalid IL or missing references) //IL_0bd9: Expected O, but got Unknown //IL_0be3: Unknown result type (might be due to invalid IL or missing references) //IL_0be8: Unknown result type (might be due to invalid IL or missing references) //IL_0bf8: Expected O, but got Unknown //IL_0bf3: Unknown result type (might be due to invalid IL or missing references) //IL_0bfd: Expected O, but got Unknown //IL_0c07: Unknown result type (might be due to invalid IL or missing references) //IL_0c0c: Unknown result type (might be due to invalid IL or missing references) //IL_0c1c: Expected O, but got Unknown //IL_0c17: Unknown result type (might be due to invalid IL or missing references) //IL_0c21: Expected O, but got Unknown //IL_0c2b: Unknown result type (might be due to invalid IL or missing references) //IL_0c30: Unknown result type (might be due to invalid IL or missing references) //IL_0c40: Expected O, but got Unknown //IL_0c3b: Unknown result type (might be due to invalid IL or missing references) //IL_0c45: Expected O, but got Unknown //IL_0c4f: Unknown result type (might be due to invalid IL or missing references) //IL_0c54: Unknown result type (might be due to invalid IL or missing references) //IL_0c64: Expected O, but got Unknown //IL_0c5f: Unknown result type (might be due to invalid IL or missing references) //IL_0c69: Expected O, but got Unknown //IL_0c73: Unknown result type (might be due to invalid IL or missing references) //IL_0c78: Unknown result type (might be due to invalid IL or missing references) //IL_0c88: Expected O, but got Unknown //IL_0c83: Unknown result type (might be due to invalid IL or missing references) //IL_0c8d: Expected O, but got Unknown //IL_0c97: Unknown result type (might be due to invalid IL or missing references) //IL_0c9c: Unknown result type (might be due to invalid IL or missing references) //IL_0cac: Expected O, but got Unknown //IL_0ca7: Unknown result type (might be due to invalid IL or missing references) //IL_0cb1: Expected O, but got Unknown //IL_0cbb: Unknown result type (might be due to invalid IL or missing references) //IL_0cc0: Unknown result type (might be due to invalid IL or missing references) //IL_0cd0: Expected O, but got Unknown //IL_0ccb: Unknown result type (might be due to invalid IL or missing references) //IL_0cd5: Expected O, but got Unknown //IL_0cdf: Unknown result type (might be due to invalid IL or missing references) //IL_0ce4: Unknown result type (might be due to invalid IL or missing references) //IL_0cf4: Expected O, but got Unknown //IL_0cef: Unknown result type (might be due to invalid IL or missing references) //IL_0cf9: Expected O, but got Unknown //IL_0d03: Unknown result type (might be due to invalid IL or missing references) //IL_0d08: Unknown result type (might be due to invalid IL or missing references) //IL_0d18: Expected O, but got Unknown //IL_0d13: Unknown result type (might be due to invalid IL or missing references) //IL_0d1d: Expected O, but got Unknown //IL_0d27: Unknown result type (might be due to invalid IL or missing references) //IL_0d2c: Unknown result type (might be due to invalid IL or missing references) //IL_0d3c: Expected O, but got Unknown //IL_0d37: Unknown result type (might be due to invalid IL or missing references) //IL_0d41: Expected O, but got Unknown //IL_0d4b: Unknown result type (might be due to invalid IL or missing references) //IL_0d50: Unknown result type (might be due to invalid IL or missing references) //IL_0d60: Expected O, but got Unknown //IL_0d5b: Unknown result type (might be due to invalid IL or missing references) //IL_0d65: Expected O, but got Unknown //IL_0d6f: Unknown result type (might be due to invalid IL or missing references) //IL_0d74: Unknown result type (might be due to invalid IL or missing references) //IL_0d84: Expected O, but got Unknown //IL_0d7f: Unknown result type (might be due to invalid IL or missing references) //IL_0d89: Expected O, but got Unknown //IL_0d93: Unknown result type (might be due to invalid IL or missing references) //IL_0d98: Unknown result type (might be due to invalid IL or missing references) //IL_0da8: Expected O, but got Unknown //IL_0da3: Unknown result type (might be due to invalid IL or missing references) //IL_0dad: Expected O, but got Unknown //IL_0db7: Unknown result type (might be due to invalid IL or missing references) //IL_0dbc: Unknown result type (might be due to invalid IL or missing references) //IL_0dcc: Expected O, but got Unknown //IL_0dc7: Unknown result type (might be due to invalid IL or missing references) //IL_0dd1: Expected O, but got Unknown //IL_0ddb: Unknown result type (might be due to invalid IL or missing references) //IL_0de0: Unknown result type (might be due to invalid IL or missing references) //IL_0df0: Expected O, but got Unknown //IL_0deb: Unknown result type (might be due to invalid IL or missing references) //IL_0df5: Expected O, but got Unknown //IL_0dff: Unknown result type (might be due to invalid IL or missing references) //IL_0e04: Unknown result type (might be due to invalid IL or missing references) //IL_0e14: Expected O, but got Unknown //IL_0e0f: Unknown result type (might be due to invalid IL or missing references) //IL_0e19: Expected O, but got Unknown //IL_0e23: Unknown result type (might be due to invalid IL or missing references) //IL_0e28: Unknown result type (might be due to invalid IL or missing references) //IL_0e38: Expected O, but got Unknown //IL_0e33: Unknown result type (might be due to invalid IL or missing references) //IL_0e3d: Expected O, but got Unknown //IL_0e47: Unknown result type (might be due to invalid IL or missing references) //IL_0e4c: Unknown result type (might be due to invalid IL or missing references) //IL_0e57: Unknown result type (might be due to invalid IL or missing references) //IL_0e62: Unknown result type (might be due to invalid IL or missing references) //IL_0e6d: Unknown result type (might be due to invalid IL or missing references) //IL_0e7d: Expected O, but got Unknown //IL_0e78: Unknown result type (might be due to invalid IL or missing references) //IL_0e82: Expected O, but got Unknown //IL_0e8c: Unknown result type (might be due to invalid IL or missing references) //IL_0e91: Unknown result type (might be due to invalid IL or missing references) //IL_0ea1: Expected O, but got Unknown //IL_0e9c: Unknown result type (might be due to invalid IL or missing references) //IL_0ea6: Expected O, but got Unknown //IL_0eb0: Unknown result type (might be due to invalid IL or missing references) //IL_0eb5: Unknown result type (might be due to invalid IL or missing references) //IL_0ec5: Expected O, but got Unknown //IL_0ec0: Unknown result type (might be due to invalid IL or missing references) //IL_0eca: Expected O, but got Unknown //IL_0ed4: Unknown result type (might be due to invalid IL or missing references) //IL_0ed9: Unknown result type (might be due to invalid IL or missing references) //IL_0ee9: Expected O, but got Unknown //IL_0ee4: Unknown result type (might be due to invalid IL or missing references) //IL_0eee: Expected O, but got Unknown //IL_0ef8: Unknown result type (might be due to invalid IL or missing references) //IL_0efd: Unknown result type (might be due to invalid IL or missing references) //IL_0f0d: Expected O, but got Unknown //IL_0f08: Unknown result type (might be due to invalid IL or missing references) //IL_0f12: Expected O, but got Unknown //IL_0f1c: Unknown result type (might be due to invalid IL or missing references) //IL_0f21: Unknown result type (might be due to invalid IL or missing references) //IL_0f31: Expected O, but got Unknown //IL_0f2c: Unknown result type (might be due to invalid IL or missing references) //IL_0f36: Expected O, but got Unknown //IL_0f40: Unknown result type (might be due to invalid IL or missing references) //IL_0f45: Unknown result type (might be due to invalid IL or missing references) //IL_0f55: Expected O, but got Unknown //IL_0f50: Unknown result type (might be due to invalid IL or missing references) //IL_0f5a: Expected O, but got Unknown //IL_0f64: Unknown result type (might be due to invalid IL or missing references) //IL_0f69: Unknown result type (might be due to invalid IL or missing references) //IL_0f79: Expected O, but got Unknown //IL_0f74: Unknown result type (might be due to invalid IL or missing references) //IL_0f7e: Expected O, but got Unknown //IL_0f88: Unknown result type (might be due to invalid IL or missing references) //IL_0f8d: Unknown result type (might be due to invalid IL or missing references) //IL_0f9d: Expected O, but got Unknown //IL_0f98: Unknown result type (might be due to invalid IL or missing references) //IL_0fa2: Expected O, but got Unknown //IL_0fac: Unknown result type (might be due to invalid IL or missing references) //IL_0fb1: Unknown result type (might be due to invalid IL or missing references) //IL_0fc1: Expected O, but got Unknown //IL_0fbc: Unknown result type (might be due to invalid IL or missing references) //IL_0fc6: Expected O, but got Unknown //IL_0fd0: Unknown result type (might be due to invalid IL or missing references) //IL_0fd5: Unknown result type (might be due to invalid IL or missing references) //IL_0fe5: Expected O, but got Unknown //IL_0fe0: Unknown result type (might be due to invalid IL or missing references) //IL_0fea: Expected O, but got Unknown //IL_0ff4: Unknown result type (might be due to invalid IL or missing references) //IL_0ff9: Unknown result type (might be due to invalid IL or missing references) //IL_1009: Expected O, but got Unknown //IL_1004: Unknown result type (might be due to invalid IL or missing references) //IL_100e: Expected O, but got Unknown if (RooInstalled) { ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.SelectedPreset, new ChoiceConfig { name = "Selected Preset", category = "General" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableBossGrabbing, new CheckBoxConfig { name = "Enable Boss Grabbing" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableNPCGrabbing, new CheckBoxConfig { name = "Enable NPC Grabbing" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableEnvironmentGrabbing, new CheckBoxConfig { name = "Enable Environment Grabbing" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableLockedObjectGrabbing, new CheckBoxConfig { name = "Enable Locked Object Grabbing" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.ProjectileGrabbingMode, new ChoiceConfig { name = "Projectile Grabbing" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableObjectPersistence, new CheckBoxConfig { name = "Enable Persistence" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableAutoGrab, new CheckBoxConfig { name = "Enable Auto-Grab" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PersistBaggedBosses, new CheckBoxConfig { name = "Persist Bosses" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PersistBaggedNPCs, new CheckBoxConfig { name = "Persist NPCs" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PersistBaggedEnvironmentObjects, new CheckBoxConfig { name = "Persist Environment" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.PersistenceBlacklist, new InputFieldConfig { name = "Persistence Blacklist" })); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.AutoGrabDelay, new StepSliderConfig { name = "Auto-Grab Delay", min = 0f, max = 10f, increment = 0.1f })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.BodyBlacklist, new InputFieldConfig { name = "Grab Blacklist" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.GrabbableComponentTypes, new InputFieldConfig { name = "Grabbable Components", category = "General" })); ModSettingsManager.AddOption((BaseOption)(object)new ComponentChooserOption((ConfigEntryBase)(object)PluginConfig.Instance.ComponentChooserDummyEntry, "Component Chooser", "Click to load and toggle components in the GrabbableComponentTypes list.")); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.ComponentChooserSortModeEntry, new ChoiceConfig { name = "Chooser Sort Mode", category = "General" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableRecoveryFeature, new CheckBoxConfig { name = "Enable Recovery Feature", category = "Recovery" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.EnemyRecoveryMode, new ChoiceConfig { name = "Enemy Recovery Mode", category = "Recovery" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.RecoverBaggedBosses, new CheckBoxConfig { name = "Recover Bosses", category = "Recovery" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.RecoverBaggedNPCs, new CheckBoxConfig { name = "Recover NPCs", category = "Recovery" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.RecoverBaggedEnvironmentObjects, new CheckBoxConfig { name = "Recover Environment Objects", category = "Recovery" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.RecoveryObjectBlacklist, new InputFieldConfig { name = "Recovery Blacklist", category = "Recovery" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.GrabbableKeywordBlacklist, new InputFieldConfig { name = "Keyword Blacklist" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableDebugLogs, new CheckBoxConfig { name = "Enable Debug Logs" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableConfigSync, new CheckBoxConfig { name = "Enable Config Sync" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.BottomlessBagEnabled, new CheckBoxConfig { name = "Enable Bottomless Bag", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.SlotScalingFormula, new InputFieldConfig { name = "Slot Scaling Formula", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableStockRefreshClamping, new CheckBoxConfig { name = "Refresh Clamping", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableSuccessiveGrabStockRefresh, new CheckBoxConfig { name = "Successive Grab Refresh", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.CycleCooldown, new StepSliderConfig { name = "Cycle Cooldown", category = "Bottomless Bag", min = 0f, max = 1f, increment = 0.01f })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PlayAnimationOnCycle, new CheckBoxConfig { name = "Play Cycle Animation", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableMouseWheelScrolling, new CheckBoxConfig { name = "Mouse Wheel Scrolling", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.InverseMouseWheelScrolling, new CheckBoxConfig { name = "Invert Scrolling", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.AutoPromoteMainSeat, new CheckBoxConfig { name = "Auto-Promote Main Seat", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.PrioritizeMainSeat, new CheckBoxConfig { name = "Prioritize Main Seat", category = "Bottomless Bag" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableBalance, new CheckBoxConfig { name = "Enable Balance", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.SelectedBalanceSubTab, new ChoiceConfig { name = "Balance Filter", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.MassCapacityFormula, new InputFieldConfig { name = "Mass Capacity Formula", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.SlamDamageFormula, new InputFieldConfig { name = "Slam Damage Formula", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.MovespeedPenaltyFormula, new InputFieldConfig { name = "Speed Penalty Formula", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.StateCalculationMode, new ChoiceConfig { name = "State Calculation", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.AoEDamageDistribution, new ChoiceConfig { name = "AoE Damage", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.OverencumbranceMax, new FloatFieldConfig { name = "Max Overencumbrance (%)", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.SelectedFlag, new ChoiceConfig { name = "Flag", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.SelectedFlagMultiplier, new InputFieldConfig { name = "Multiplier", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.SearchRadiusMultiplier, new StepSliderConfig { name = "Grab Range Multiplier", category = "Balance", min = 1f, max = 100f, increment = 0.1f })); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.BreakoutTimeMultiplier, new StepSliderConfig { name = "Breakout Time Multiplier", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new IntSliderOption(PluginConfig.Instance.MaxSmacks, new IntSliderConfig { name = "Max Hits Before Breakout", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.MaxLaunchSpeed, new InputFieldConfig { name = "Max Launch Speed", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.BagScaleCap, new InputFieldConfig { name = "Bag Visual Size Cap", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(PluginConfig.Instance.MassCap, new InputFieldConfig { name = "Bagged Entity Mass Cap", category = "Balance" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.SelectedHudElement, new ChoiceConfig { name = "HUD Filter", category = "Hud" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.IsHudEditorEnabled, new CheckBoxConfig { name = "Enable HUD Editor", category = "Hud" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableCarouselHUD, new CheckBoxConfig { name = "Enable Carousel HUD" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselSpacing, new FloatFieldConfig { name = "Vertical Spacing" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CarouselAnimationDuration, new FloatFieldConfig { name = "Animation Duration" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CenterSlotX, new FloatFieldConfig { name = "Main Slot X Offset" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CenterSlotY, new FloatFieldConfig { name = "Main Slot Y Offset" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CenterSlotScale, new FloatFieldConfig { name = "Main Slot Scale" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.CenterSlotOpacity, new FloatFieldConfig { name = "Main Slot Opacity" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.CenterSlotShowIcon, new CheckBoxConfig { name = "Show Icon (Main)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.CenterSlotShowWeightIcon, new CheckBoxConfig { name = "Show Weight Icon (Main)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.CenterSlotShowName, new CheckBoxConfig { name = "Show Name (Main)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.CenterSlotShowHealthBar, new CheckBoxConfig { name = "Show Health (Main)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.CenterSlotShowSlotNumber, new CheckBoxConfig { name = "Show Slot # (Main)" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.SideSlotX, new FloatFieldConfig { name = "Side Slot X Offset" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.SideSlotY, new FloatFieldConfig { name = "Side Slot Y Offset" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.SideSlotScale, new FloatFieldConfig { name = "Side Slot Scale" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.SideSlotOpacity, new FloatFieldConfig { name = "Side Slot Opacity" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.SideSlotShowIcon, new CheckBoxConfig { name = "Show Icon (Side)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.SideSlotShowWeightIcon, new CheckBoxConfig { name = "Show Weight Icon (Side)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.SideSlotShowName, new CheckBoxConfig { name = "Show Name (Side)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.SideSlotShowHealthBar, new CheckBoxConfig { name = "Show Health (Side)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.SideSlotShowSlotNumber, new CheckBoxConfig { name = "Show Slot # (Side)" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.UseNewWeightIcon, new CheckBoxConfig { name = "Use New Weight Icon" })); ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)PluginConfig.Instance.WeightDisplayMode, new ChoiceConfig { name = "Weight Display Mode" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.ScaleWeightColor, new CheckBoxConfig { name = "Scale Weight Color" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.ShowTotalMassOnWeightIcon, new CheckBoxConfig { name = "Show Total Mass" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.ShowOverencumberIcon, new CheckBoxConfig { name = "Show Overencumbered Icon" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableDamagePreview, new CheckBoxConfig { name = "Enable Damage Preview" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.DamagePreviewColor, new ColorOptionConfig { name = "Damage Preview Color" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableMassCapacityUI, new CheckBoxConfig { name = "Enable Capacity UI" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MassCapacityUIPositionX, new FloatFieldConfig { name = "Capacity UI X Pos" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MassCapacityUIPositionY, new FloatFieldConfig { name = "Capacity UI Y Pos" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.MassCapacityUIScale, new FloatFieldConfig { name = "Capacity UI Scale" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableSeparators, new CheckBoxConfig { name = "Enable Separators" })); ModSettingsManager.AddOption((BaseOption)new StepSliderOption(PluginConfig.Instance.GradientIntensity, new StepSliderConfig { name = "Gradient Intensity", min = 0f, max = 1f, increment = 0.05f })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.CapacityGradientColorStart, new ColorOptionConfig { name = "Gradient Color Start" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.CapacityGradientColorMid, new ColorOptionConfig { name = "Gradient Color Mid" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.CapacityGradientColorEnd, new ColorOptionConfig { name = "Gradient Color End" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.OverencumbranceGradientColorStart, new ColorOptionConfig { name = "Overencumbrance Start" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.OverencumbranceGradientColorMid, new ColorOptionConfig { name = "Overencumbrance Mid" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.OverencumbranceGradientColorEnd, new ColorOptionConfig { name = "Overencumbrance End" })); ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(PluginConfig.Instance.EnableBaggedObjectInfo, new CheckBoxConfig { name = "Enable Stats Panel" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.BaggedObjectInfoX, new FloatFieldConfig { name = "Stats Panel X Pos" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.BaggedObjectInfoY, new FloatFieldConfig { name = "Stats Panel Y Pos" })); ModSettingsManager.AddOption((BaseOption)new FloatFieldOption(PluginConfig.Instance.BaggedObjectInfoScale, new FloatFieldConfig { name = "Stats Panel Scale" })); ModSettingsManager.AddOption((BaseOption)new ColorOption(PluginConfig.Instance.BaggedObjectInfoColor, new ColorOptionConfig { name = "Stats Panel Color" })); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void SetupRiskOfOptionsEvents() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown if (!RooInstalled) { return; } try { Harmony val = new Harmony("com.pwdcat.DrifterBossGrab.roo_ui"); MethodInfo methodInfo = AccessTools.Method(typeof(ModOptionPanelController), "LoadOptionListFromCategory", (Type[])null, (Type[])null); if (methodInfo != null) { MethodInfo methodInfo2 = AccessTools.Method(typeof(DrifterBossGrabPlugin), "OnRooCategoryLoaded", (Type[])null, (Type[])null); val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { Log.Warning("[RiskOfOptions] Failed to find LoadOptionListFromCategory method in RiskOfOptions."); } val.CreateClassProcessor(typeof(RiskOfOptionsDummyPatches)).Patch(); } catch (Exception arg) { Log.Warning($"[RiskOfOptions] Exception while patching RiskOfOptions: {arg}"); } } private static void OnRooCategoryLoaded(string modGuid) { if (modGuid == "com.pwdcat.DrifterBossGrab" && (Object)(object)Instance != (Object)null) { ((MonoBehaviour)Instance).StartCoroutine(DelayedUpdateRooVisibility()); } } [IteratorStateMachine(typeof(d__101))] private static IEnumerator DelayedUpdateRooVisibility() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__101(0); } [IteratorStateMachine(typeof(d__102))] private static IEnumerator DelayedUpdateBottomlessBagVisibility() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__102(0); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private void RefreshStringInputFieldUI(ConfigEntry configEntry) { if (!RooInstalled) { return; } string text = ("com.pwdcat.DrifterBossGrab." + ((ConfigEntryBase)configEntry).Definition.Section + "." + ((ConfigEntryBase)configEntry).Definition.Key + ".STRING_INPUT_FIELD").Replace(" ", "_").ToUpper(); if (configEntry == PluginConfig.Instance.SelectedFlagMultiplier) { text = "com.pwdcat.DrifterBossGrab.BALANCE.MULTIPLIER.STRING_INPUT_FIELD".Replace(" ", "_").ToUpper(); } ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); ModSetting[] array2 = array; foreach (ModSetting val in array2) { if (val.settingToken == text) { GameObject gameObject = ((Component)val).gameObject; if ((Object)(object)gameObject != (Object)null && gameObject.activeSelf) { gameObject.SetActive(false); gameObject.SetActive(true); } break; } } } private bool ShouldHudSettingBeVisible(string token) { if (PluginConfig.HudSettingToSubTab.TryGetValue(token, out HudElementType[] value)) { HudElementType value2 = PluginConfig.Instance.SelectedHudElement.Value; if (value2 != 0) { return Array.IndexOf(value, value2) >= 0; } return true; } return true; } private bool ShouldBalanceSettingBeVisible(string token) { if (PluginConfig.BalanceSettingToSubTab.TryGetValue(token, out BalanceSubTabType[] value)) { BalanceSubTabType value2 = PluginConfig.Instance.SelectedBalanceSubTab.Value; if (value2 != 0) { return Array.IndexOf(value, value2) >= 0; } return true; } return true; } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdateHudSubTabVisibility() { if (!RooInstalled) { return; } HudElementType selectedSubTab = PluginConfig.Instance.SelectedHudElement.Value; UpdateSubTabVisibility(selectedSubTab, PluginConfig.HudSettingToSubTab, (string settingToken, HudElementType[] subTabs) => selectedSubTab == HudElementType.All || Array.IndexOf(subTabs, selectedSubTab) >= 0); UpdateHudVisibility(); string text = "com.pwdcat.DrifterBossGrab.HUD.HUD_FILTER.CHOICE".ToUpper(); ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); ModSetting[] array2 = array; foreach (ModSetting val in array2) { if (!(val.settingToken == text)) { continue; } OnEnableCallback component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { break; } component = ((Component)val).gameObject.AddComponent(); component.Action = delegate { if (PluginConfig.Instance.SelectedHudElement.Value != 0) { PluginConfig.Instance.SelectedHudElement.Value = HudElementType.All; } else { UpdateHudSubTabVisibility(); } }; break; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdateBalanceSubTabVisibility() { if (!RooInstalled) { return; } CharacterFlagType value = PluginConfig.Instance.SelectedFlag.Value; ConfigEntry flagMultiplierConfig = PluginConfig.GetFlagMultiplierConfig(value); if (flagMultiplierConfig != null) { PluginConfig.Instance.SelectedFlagMultiplier.Value = flagMultiplierConfig.Value; } BalanceSubTabType selectedSubTab = PluginConfig.Instance.SelectedBalanceSubTab.Value; UpdateSubTabVisibility(selectedSubTab, PluginConfig.BalanceSettingToSubTab, (string settingToken, BalanceSubTabType[] subTabs) => selectedSubTab == BalanceSubTabType.All || Array.IndexOf(subTabs, selectedSubTab) >= 0); UpdateBalanceVisibility(); string text = "com.pwdcat.DrifterBossGrab.BALANCE.BALANCE_FILTER.CHOICE".ToUpper(); ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); ModSetting[] array2 = array; foreach (ModSetting val in array2) { if (!(val.settingToken == text)) { continue; } OnEnableCallback component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { break; } component = ((Component)val).gameObject.AddComponent(); component.Action = delegate { if (PluginConfig.Instance.SelectedBalanceSubTab.Value != 0) { PluginConfig.Instance.SelectedBalanceSubTab.Value = BalanceSubTabType.All; } else { UpdateBalanceSubTabVisibility(); } CharacterFlagType value2 = PluginConfig.Instance.SelectedFlag.Value; ConfigEntry flagMultiplierConfig2 = PluginConfig.GetFlagMultiplierConfig(value2); if (flagMultiplierConfig2 != null) { PluginConfig.Instance.SelectedFlagMultiplier.Value = flagMultiplierConfig2.Value; } RefreshStringInputFieldUI(PluginConfig.Instance.SelectedFlagMultiplier); }; break; } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdateBottomlessBagVisibility() { if (RooInstalled) { UpdateCategoryToggledVisibility("Bottomless Bag", PluginConfig.Instance.BottomlessBagEnabled.Value, "Enable Bottomless Bag"); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdateBalanceVisibility() { if (RooInstalled) { UpdateCategoryToggledVisibility("Balance", PluginConfig.Instance.EnableBalance.Value, "Enable Balance"); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdateHudVisibility() { if (RooInstalled) { UpdateCategoryToggledVisibility("Hud", PluginConfig.Instance.EnableCarouselHUD.Value, "Enable Carousel HUD", (string token) => token.Contains("_SLOT_") || token.Contains("SPACING") || token.Contains("DURATION") || token.Contains("SHOW_ICON") || token.Contains("SHOW_WEIGHT") || token.Contains("SHOW_NAME") || token.Contains("SHOW_HEALTH") || token.Contains("SHOW_SLOT") || token.Contains("WEIGHT_DISPLAY") || token.Contains("NEW_WEIGHT_ICON") || token.Contains("SCALE_WEIGHT") || token.Contains("TOTAL_MASS") || token.Contains("OVERENCUMBERED_ICON")); UpdateCategoryToggledVisibility("Hud", PluginConfig.Instance.EnableDamagePreview.Value, "Enable Damage Preview", (string token) => token.Contains("DAMAGE_PREVIEW_COLOR")); UpdateCategoryToggledVisibility("Hud", PluginConfig.Instance.EnableMassCapacityUI.Value, "Enable Capacity UI", (string token) => token.Contains("CAPACITY_UI_") || token.Contains("ENABLE_SEPARATORS") || token.Contains("GRADIENT_INTENSITY") || token.Contains("GRADIENT_COLOR") || token.Contains("OVERENCUMBRANCE")); UpdateCategoryToggledVisibility("Hud", PluginConfig.Instance.EnableBaggedObjectInfo.Value, "Enable Stats Panel", (string token) => token.Contains("STATS_PANEL_")); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdateRecoveryVisibility() { if (RooInstalled) { UpdateCategoryToggledVisibility("Recovery", PluginConfig.Instance.EnableRecoveryFeature.Value, "Enable Recovery Feature"); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] public void UpdatePersistenceVisibility() { if (RooInstalled) { UpdateCategoryToggledVisibility("Persistence", PluginConfig.Instance.EnableObjectPersistence.Value, "Enable Persistence"); } } private void UpdateCategoryToggledVisibility(string categoryName, bool isEnabled, string masterToggleName, Func? filterPredicate = null) { ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); string text = categoryName.Replace(" ", "_").ToUpper(); string text2 = masterToggleName.Replace(" ", "_").ToUpper(); ModSetting[] array2 = array; foreach (ModSetting val in array2) { if (!string.IsNullOrEmpty(val.settingToken) && val.settingToken.Contains("." + text + ".") && !val.settingToken.Contains("." + text2 + ".") && !val.settingToken.EndsWith("." + text2, StringComparison.OrdinalIgnoreCase) && (filterPredicate == null || filterPredicate(val.settingToken))) { CanvasGroup val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } LayoutElement val3 = ((Component)val).GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val).gameObject.AddComponent(); } bool flag = true; if (categoryName.Equals("Hud", StringComparison.OrdinalIgnoreCase)) { flag = ShouldHudSettingBeVisible(val.settingToken); } else if (categoryName.Equals("Balance", StringComparison.OrdinalIgnoreCase)) { flag = ShouldBalanceSettingBeVisible(val.settingToken); } if (!flag) { val2.alpha = 0f; val2.blocksRaycasts = false; val3.ignoreLayout = true; } else { val2.alpha = (isEnabled ? 1f : 0.3f); val2.blocksRaycasts = isEnabled; val3.ignoreLayout = false; } } } } private void UpdateSubTabVisibility(T selectedSubTab, Dictionary settingToSubTabMap, Func shouldShowPredicate) { ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int num5 = 0; ModSetting[] array2 = array; foreach (ModSetting val in array2) { if (string.IsNullOrEmpty(val.settingToken)) { continue; } T[] value; bool flag = settingToSubTabMap.TryGetValue(val.settingToken, out value); if (val.settingToken.Contains(".HUD.")) { num4++; } else if (val.settingToken.Contains(".BALANCE.")) { num5++; } if (flag) { num++; bool flag2 = shouldShowPredicate(val.settingToken, value); CanvasGroup val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } LayoutElement val3 = ((Component)val).GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = ((Component)val).gameObject.AddComponent(); } if (flag2) { val2.alpha = 1f; val2.blocksRaycasts = true; val3.ignoreLayout = false; num2++; } else { val2.alpha = 0f; val2.blocksRaycasts = false; val3.ignoreLayout = true; num3++; } } } } } internal static class Log { private static ManualLogSource? _logger; private static bool _enableDebugLogs; internal static bool EnableDebugLogs { get { return _enableDebugLogs; } set { _enableDebugLogs = value; } } internal static void Init(ManualLogSource logSource) { _logger = logSource; } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Error(object data) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogError((object)data.ToString()); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Warning(object data) { ManualLogSource? logger = _logger; if (logger != null) { logger.LogWarning((object)data.ToString()); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Debug(object data) { if (_enableDebugLogs && _logger != null) { _logger.LogDebug((object)data.ToString()); } } } public class OnEnableCallback : MonoBehaviour { public Action? Action; public void OnEnable() { Action?.Invoke(); } } public static class ReflectionCache { public static class ThrownObjectProjectileController { public static readonly FieldInfo ProjectileController = AccessTools.Field(typeof(ThrownObjectProjectileController), "projectileController"); public static readonly MethodInfo CalculatePassengerFinalPosition = AccessTools.Method(typeof(ThrownObjectProjectileController), "CalculatePassengerFinalPosition", (Type[])null, (Type[])null); } public static class BaggedObject { private static readonly Type BaggedObjectType = Type.GetType("EntityStates.Drifter.Bag.BaggedObject, RoR2") ?? typeof(BaggedObject); public static readonly FieldInfo TargetObject = AccessTools.Field(BaggedObjectType, "targetObject"); public static readonly FieldInfo TargetBody = AccessTools.Field(BaggedObjectType, "targetBody"); public static readonly FieldInfo IsBody = AccessTools.Field(BaggedObjectType, "isBody"); public static readonly MethodInfo HoldsDeadBody = AccessTools.Method(BaggedObjectType, "HoldsDeadBody", (Type[])null, (Type[])null); public static readonly FieldInfo VehiclePassengerAttributes = AccessTools.Field(BaggedObjectType, "vehiclePassengerAttributes"); public static readonly FieldInfo BaggedMass = AccessTools.Field(BaggedObjectType, "baggedMass"); public static readonly FieldInfo UIOverlayController = AccessTools.Field(BaggedObjectType, "uiOverlayController"); public static readonly FieldInfo OverriddenUtility = AccessTools.Field(BaggedObjectType, "overriddenUtility"); public static readonly FieldInfo OverriddenPrimary = AccessTools.Field(BaggedObjectType, "overriddenPrimary"); public static readonly FieldInfo UtilityOverride = AccessTools.Field(BaggedObjectType, "utilityOverride"); public static readonly FieldInfo PrimaryOverride = AccessTools.Field(BaggedObjectType, "primaryOverride"); public static readonly FieldInfo BreakoutTime = AccessTools.Field(BaggedObjectType, "breakoutTime"); public static readonly FieldInfo BreakoutAttempts = AccessTools.Field(BaggedObjectType, "breakoutAttempts"); public static readonly MethodInfo TryOverrideUtility = AccessTools.Method(BaggedObjectType, "TryOverrideUtility", (Type[])null, (Type[])null); public static readonly MethodInfo TryOverridePrimary = AccessTools.Method(BaggedObjectType, "TryOverridePrimary", (Type[])null, (Type[])null); public static readonly FieldInfo BagScale01 = AccessTools.Field(BaggedObjectType, "bagScale01"); public static readonly MethodInfo SetScale = AccessTools.Method(BaggedObjectType, "SetScale", new Type[1] { typeof(float) }, (Type[])null); public static readonly FieldInfo DrifterBagController = AccessTools.Field(BaggedObjectType, "drifterBagController"); public static readonly FieldInfo WalkSpeedModifier = AccessTools.Field(BaggedObjectType, "walkSpeedModifier"); } public static class DrifterBagController { public static readonly FieldInfo BaggedMass = AccessTools.Field(typeof(DrifterBagController), "baggedMass"); public static readonly MethodInfo OnSyncBaggedObject = AccessTools.Method(typeof(DrifterBagController), "OnSyncBaggedObject", new Type[1] { typeof(GameObject) }, (Type[])null); public static readonly FieldInfo JunkController = AccessTools.Field(typeof(DrifterBagController), "junkController"); public static readonly FieldInfo Smacks = AccessTools.Field(typeof(DrifterBagController), "smacks"); } public static class SpecialObjectAttributes { public static readonly FieldInfo CollidersToDisable = typeof(SpecialObjectAttributes).GetField("collidersList", BindingFlags.Instance | BindingFlags.NonPublic); } public static class HackingMainState { public static readonly FieldInfo SphereSearch = typeof(HackingMainState).GetField("sphereSearch", BindingFlags.Instance | BindingFlags.NonPublic); } public static class EntityState { public static readonly PropertyInfo FixedAge = AccessTools.Property(typeof(EntityState), "fixedAge"); } public static class GenericSkill { public static readonly FieldInfo SkillOverrides = AccessTools.Field(typeof(GenericSkill), "skillOverrides"); } public static class Misc { public static readonly MethodInfo OnUIOverlayInstanceRemove = AccessTools.Method(typeof(BaggedObject), "OnUIOverlayInstanceRemove", (Type[])null, (Type[])null); } public static class EmptyBag { public static readonly FieldInfo ProjectileBaseSpeed = AccessTools.Field(typeof(AimThrowableBase), "projectileBaseSpeed"); } public static class BaggedObjectAdditional { private static readonly Type BaggedObjectType = Type.GetType("EntityStates.Drifter.Bag.BaggedObject, RoR2") ?? typeof(BaggedObject); public static readonly FieldInfo MovespeedPenalty = AccessTools.Field(BaggedObjectType, "movespeedPenalty"); public static readonly FieldInfo? AttackSpeedStat = null; public static readonly FieldInfo? DamageStat = null; public static readonly FieldInfo? CritStat = null; public static readonly FieldInfo? MoveSpeedStat = null; } public static class RepossessExit { public static readonly FieldInfo ChosenTarget = AccessTools.Field(typeof(RepossessExit), "chosenTarget"); public static readonly FieldInfo ActivatedHitpause = AccessTools.Field(typeof(RepossessExit), "activatedHitpause"); } public static class JunkCubeController { private static FieldInfo? _maxActivationCount; public static FieldInfo? MaxActivationCount { get { if (_maxActivationCount == null) { Type type = Type.GetType("RoR2.JunkCubeController, RoR2"); if (type != null) { _maxActivationCount = AccessTools.Field(type, "_maxActivationCount"); } } return _maxActivationCount; } } } public static class NetworkIdentity { public static readonly FieldInfo AssetId = AccessTools.Field(typeof(NetworkIdentity), "m_AssetId"); } public static class Rewired { public static class ActionElementMap { private static MethodInfo? _applyToControllerMapMethod; public static MethodInfo? GetApplyToControllerMapMethod() { if (_applyToControllerMapMethod == null) { Type type = Type.GetType("Rewired.Data.Mapping.ActionElementMap, Rewired_Core"); if (type != null) { MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.ReturnType == typeof(void))) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1) { Type type2 = Type.GetType("Rewired.ControllerMap, Rewired_Core"); if (type2 != null && type2.IsAssignableFrom(parameters[0].ParameterType)) { _applyToControllerMapMethod = methodInfo; break; } } } } } return _applyToControllerMapMethod; } } } public static class TeleporterInteraction { public static readonly FieldInfo BossGroup = AccessTools.Field(typeof(TeleporterInteraction), "bossGroup"); public static readonly FieldInfo MainStateMachine = AccessTools.Field(typeof(TeleporterInteraction), "mainStateMachine"); public static readonly FieldInfo BossDirector = AccessTools.Field(typeof(TeleporterInteraction), "bossDirector"); public static readonly FieldInfo MonstersCleared = AccessTools.Field(typeof(TeleporterInteraction), "monstersCleared"); public static readonly FieldInfo PositionIndicator = AccessTools.Field(typeof(TeleporterInteraction), "teleporterPositionIndicator"); public static readonly FieldInfo BossShrineCounter = AccessTools.Field(typeof(TeleporterInteraction), "_bossShrineCounter"); public static readonly FieldInfo CachedLocalUser = AccessTools.Field(typeof(TeleporterInteraction), "cachedLocalUser"); } public static class CombatDirector { public static readonly FieldInfo CombatSquad = AccessTools.Field(typeof(CombatDirector), "combatSquad"); public static readonly FieldInfo MonsterCredit = AccessTools.Field(typeof(CombatDirector), "monsterCredit"); public static readonly FieldInfo MinSpawnRange = AccessTools.Field(typeof(CombatDirector), "minSpawnRange"); public static readonly FieldInfo MaxSpawnDistance = AccessTools.Field(typeof(CombatDirector), "maxSpawnDistance"); public static readonly FieldInfo BossOverrideSpawnSingleBoss = AccessTools.Field(typeof(CombatDirector), "_bossOverrideSpawnSingleBoss"); } public static class OutsideInteractableLocker { public static readonly FieldInfo LockObjectMap = AccessTools.Field(typeof(OutsideInteractableLocker), "lockObjectMap"); public static readonly FieldInfo LockInteractableMap = AccessTools.Field(typeof(OutsideInteractableLocker), "lockInteractableMap"); } public static class CombatSquad { public static readonly FieldInfo MembersList = AccessTools.Field(typeof(CombatSquad), "membersList"); } public static class HoldoutZoneController { public static readonly PropertyInfo CurrentRadius = AccessTools.Property(typeof(HoldoutZoneController), "currentRadius"); public static readonly FieldInfo RadiusVelocity = AccessTools.Field(typeof(HoldoutZoneController), "radiusVelocity"); } public static class BossGroup { public static readonly FieldInfo BossMemoryCount = AccessTools.Field(typeof(BossGroup), "bossMemoryCount"); public static readonly MethodInfo ResetBossBar = AccessTools.Method(typeof(BossGroup), "ResetBossBar", (Type[])null, (Type[])null); public static readonly FieldInfo BossDropTables = AccessTools.Field(typeof(BossGroup), "bossDropTables"); public static readonly FieldInfo BossDrops = AccessTools.Field(typeof(BossGroup), "bossDrops"); public static readonly FieldInfo BossDropTablesLocked = AccessTools.Field(typeof(BossGroup), "bossDropTablesLocked"); public static readonly FieldInfo rng = AccessTools.Field(typeof(BossGroup), "rng"); } } public class BalanceFeature : FeatureToggleBase { public override string FeatureName => "Balance"; public override bool IsEnabled => PluginConfig.Instance.EnableBalance.Value; protected override void ApplyPatches(Harmony harmony) { Log.Debug("[" + FeatureName + "] Applying balance patches..."); harmony.CreateClassProcessor(typeof(BalancePatches.CharacterBody_RecalculateStats_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.CharacterBody_OnDestroy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.EmptyBag_ModifyProjectile_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.EmptyBag_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.EmptyBag_FireProjectile_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BalancePatches.ProjectileManager_FireProjectile_Patch)).Patch(); harmony.CreateClassProcessor(typeof(StateCalculationPatches.SuffocateSlam_AuthorityModifyOverlapAttack_ApplyCustomDamage)).Patch(); harmony.CreateClassProcessor(typeof(CmdDamageBaggedObject_AoE)).Patch(); harmony.CreateClassProcessor(typeof(StateCalculationPatches.SuffocateSlam_OnEnter_UseDynamicCapacity)).Patch(); harmony.CreateClassProcessor(typeof(StateCalculationPatches.BluntForceHit3_OnEnter_UseFormula)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.BaggedObject_UpdateBaggedObjectMass)).Patch(); Log.Debug("[" + FeatureName + "] Balance patches applied successfully."); } } public class BottomlessBagFeature : FeatureToggleBase { public override string FeatureName => "BottomlessBag"; public override bool IsEnabled => PluginConfig.Instance.BottomlessBagEnabled.Value; protected override void ApplyPatches(Harmony harmony) { Log.Debug("[" + FeatureName + "] Applying patches..."); harmony.CreateClassProcessor(typeof(BaggedObjectPatches.BaggedObject_TryOverrideUtility)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectPatches.BaggedObject_TryOverridePrimary)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.BaggedObject_OnEnter)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.BaggedObject_OnExit)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.BaggedObject_HoldsDeadBody_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.BaggedObject_FixedUpdate_Patch)).Patch(); harmony.CreateClassProcessor(typeof(AnimationPatches)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.EntityStateMachine_SetNextStateToMain)).Patch(); harmony.CreateClassProcessor(typeof(VehicleSeat_AssignPassenger_Postfix)).Patch(); harmony.CreateClassProcessor(typeof(VehicleSeat_OnPassengerExit_Patch)).Patch(); harmony.CreateClassProcessor(typeof(GlobalEventManager_OnCharacterDeath)).Patch(); harmony.CreateClassProcessor(typeof(SkillPatches.GenericSkill_RunRecharge)).Patch(); harmony.CreateClassProcessor(typeof(RepossessExitPatches.RepossessExit_OnExit_Patch)).Patch(); Log.Debug("[" + FeatureName + "] Patches applied successfully."); } } public class DrifterGrabFeature : FeatureToggleBase { public override string FeatureName => "DrifterGrab"; public override bool IsEnabled => PluginConfig.Instance.SelectedPreset.Value != PresetType.Vanilla; protected override void ApplyPatches(Harmony harmony) { harmony.CreateClassProcessor(typeof(BagPatches.Run_Start_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BagPatches.DrifterBagController_AssignPassenger)).Patch(); harmony.CreateClassProcessor(typeof(MiscPatches.HackingMainState_ScanForTarget_Patch)).Patch(); harmony.CreateClassProcessor(typeof(MiscPatches.ThrownObjectProjectileController_EjectPassengerToFinalPosition_Patch)).Patch(); harmony.CreateClassProcessor(typeof(MiscPatches.ThrownObjectProjectileController_CheckForDeadPassenger_Patch)).Patch(); harmony.CreateClassProcessor(typeof(ProjectileRecoveryPatches.ThrownObjectProjectileController_OnSyncPassenger_Patch)).Patch(); harmony.CreateClassProcessor(typeof(ProjectileRecoveryPatches.ThrownObjectProjectileController_ImpactBehavior_Patch)).Patch(); harmony.CreateClassProcessor(typeof(ProjectileRecoveryPatches.ThrownObjectProjectileController_OnDestroy_Patch)).Patch(); harmony.CreateClassProcessor(typeof(SpecialObjectAttributesPatches.SpecialObjectAttributes_OnEnable_Patch)).Patch(); harmony.CreateClassProcessor(typeof(SpecialObjectAttributesPatches.SpecialObjectAttributes_OnDisable_Patch)).Patch(); harmony.CreateClassProcessor(typeof(SpecialObjectAttributesPatches.SpecialObjectAttributes_Start_Patch)).Patch(); harmony.CreateClassProcessor(typeof(SpecialObjectAttributesPatches.BaggedObject_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessExitPatches.RepossessExit_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessExitPatches.RepossessExit_OnSerialize_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessExitPatches.RepossessExit_OnDeserialize_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessExitPatches.BaggedObject_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessExitPatches.BaggedObject_OnExit_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.DrifterBagController_CalculateBaggedObjectMass_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.DrifterBagController_RecalculateBaggedObjectMass_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.DrifterBagController_OnSyncBaggedObject_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.DrifterBagController_Awake_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.BaggedObject_OnEnter_ExtendBreakoutTime)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.SpecialObjectAttributes_get_isTargetable)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.RepossessBullseyeSearch_HurtBoxPassesRequirements)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.SpecialObjectAttributes_AvoidCapture)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.AimRepossess_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(RepossessPatches.Repossess_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(CharacterSpawnPatches.CharacterMaster_OnBodyStart)).Patch(); harmony.CreateClassProcessor(typeof(GrabbableObjectPatches.DirectorCore_TrySpawnObject_Patch)).Patch(); harmony.CreateClassProcessor(typeof(GrabbableObjectPatches.SpecialObjectAttributes_Start_Patch)).Patch(); harmony.CreateClassProcessor(typeof(GrabbableObjectPatches.BaseCaptainSupplyDropState_OnEnter_Patch)).Patch(); harmony.CreateClassProcessor(typeof(BaggedObjectStatePatches.EntityStateMachine_SetState)).Patch(); harmony.CreateClassProcessor(typeof(MiscPatches.ThrownObjectProjectileController_CheckForDeadPassenger_Patch)).Patch(); harmony.CreateClassProcessor(typeof(ProjectilePatches.ProjectileController_Start_Patch)).Patch(); } } public class BossGrabbingStrategy : IGrabbingStrategy { public bool CanGrab(GameObject obj) { CharacterBody component = obj.GetComponent(); if ((Object)(object)component != (Object)null && (component.isBoss || component.isChampion)) { return PluginConfig.Instance.EnableBossGrabbing.Value; } return false; } } public class EnvironmentGrabbingStrategy : IGrabbingStrategy { public bool CanGrab(GameObject obj) { CharacterBody component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return PluginConfig.Instance.EnableEnvironmentGrabbing.Value; } return false; } } public class NPCGrabbingStrategy : IGrabbingStrategy { public bool CanGrab(GameObject obj) { CharacterBody component = obj.GetComponent(); if ((Object)(object)component != (Object)null && !component.isBoss && !component.isChampion) { return PluginConfig.Instance.EnableNPCGrabbing.Value; } return false; } } public class PersistenceFeature : FeatureToggleBase { public override string FeatureName => "Persistence"; public override bool IsEnabled => PluginConfig.Instance.EnableObjectPersistence.Value; protected override void ApplyPatches(Harmony harmony) { harmony.CreateClassProcessor(typeof(SceneExitPatches.SceneExitController_OnEnable)).Patch(); harmony.CreateClassProcessor(typeof(SceneExitPatches.SceneExitController_OnDisable)).Patch(); RunLifecyclePatches.Initialize(); } public override void Cleanup() { base.Cleanup(); RunLifecyclePatches.Cleanup(); } } public interface IPersistenceCommand { void Execute(); } public class AddPersistedObjectCommand : IPersistenceCommand { private readonly GameObject _obj; private readonly string? _ownerPlayerId; public AddPersistedObjectCommand(GameObject obj, string? ownerPlayerId = null) { _obj = obj; _ownerPlayerId = ownerPlayerId; } public void Execute() { PersistenceObjectManager.AddPersistedObjectInternal(_obj, _ownerPlayerId); } } public class RemovePersistedObjectCommand : IPersistenceCommand { private readonly GameObject _obj; private readonly bool _isDestroying; public RemovePersistedObjectCommand(GameObject obj, bool isDestroying = false) { _obj = obj; _isDestroying = isDestroying; } public void Execute() { PersistenceObjectManager.RemovePersistedObjectInternal(_obj, _isDestroying); } } public class ClearPersistedObjectsCommand : IPersistenceCommand { private GameObject[] _clearedObjects; public void Execute() { _clearedObjects = PersistenceObjectManager.GetPersistedObjects(); PersistenceObjectManager.ClearPersistedObjectsInternal(); } } public class PersistenceCommandInvoker { public void ExecuteCommand(IPersistenceCommand command) { command.Execute(); } } public static class PersistenceManager { private static readonly HashSet _teleportersCurrentlyBagged = new HashSet(); private static readonly object _teleporterLock = new object(); public static void Initialize() { PersistenceObjectManager.Initialize(); } public static void Cleanup() { PersistenceObjectManager.Cleanup(); } public static void UpdateCachedConfig() { PersistenceObjectManager.UpdateCachedConfig(); } public static void RemovePersistedObject(GameObject obj, bool isDestroying = false) { PersistenceObjectManager.RemovePersistedObject(obj, isDestroying); } public static void ClearPersistedObjects() { PersistenceObjectManager.ClearPersistedObjects(); } public static void CaptureCurrentlyBaggedObjects() { PersistenceObjectManager.CaptureCurrentlyBaggedObjects(); } public static List GetCurrentlyBaggedObjects() { return PersistenceObjectManager.GetCurrentlyBaggedObjects(); } public static void MoveObjectsToPersistenceContainer() { PersistenceObjectManager.MoveObjectsToPersistenceContainer(); } public static void OnSceneChanged(Scene oldScene, Scene newScene) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) PersistenceSceneHandler.Instance.OnSceneChanged(oldScene, newScene); } public static void ScheduleAutoGrab(CharacterMaster master) { PersistenceSceneHandler.Instance.ScheduleAutoGrab(master); } public static bool IsTeleporterCurrentlyBagged(GameObject obj) { lock (_teleporterLock) { return _teleportersCurrentlyBagged.Contains(obj); } } public static void MarkTeleporterAsBagged(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_teleporterLock) { _teleportersCurrentlyBagged.Add(obj); Log.Debug($" Marked {((Object)obj).name} as bagged, total bagged: {_teleportersCurrentlyBagged.Count}"); } } public static void UnmarkTeleporterAsBagged(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_teleporterLock) { if (_teleportersCurrentlyBagged.Remove(obj)) { Log.Debug($" Unmarked {((Object)obj).name} as bagged, total remaining: {_teleportersCurrentlyBagged.Count}"); } } } } public static class PersistenceNetworkHandler { [CompilerGenerated] private sealed class d__5 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public UpdateBagStateMessage msg; private int 5__2; private int 5__3; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; 5__3++; goto IL_0050; } <>1__state = -1; 5__2 = 0; goto IL_0092; IL_0050: if (5__3 < 10) { <>2__current = null; <>1__state = 1; return true; } GameObject val = ClientScene.FindLocalObject(msg.controllerNetId); if ((Object)(object)val != (Object)null) { ApplyBagStateUpdate(val, msg); return false; } 5__2++; goto IL_0092; IL_0092: if (5__2 < 10) { 5__3 = 0; goto IL_0050; } Log.Error($"[BagStateSync] Failed to find controller object with netId {((NetworkInstanceId)(ref msg.controllerNetId)).Value} after 10 retries"); 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(); } } public static void SendBaggedObjectsPersistenceMessage(List baggedObjects, DrifterBagController? owner = null) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) if (baggedObjects == null || baggedObjects.Count == 0) { return; } BaggedObjectsPersistenceMessage baggedObjectsPersistenceMessage = new BaggedObjectsPersistenceMessage(); foreach (GameObject baggedObject in baggedObjects) { if (!((Object)(object)baggedObject != (Object)null)) { continue; } NetworkIdentity component = baggedObject.GetComponent(); if (!((Object)(object)component != (Object)null)) { continue; } baggedObjectsPersistenceMessage.baggedObjectNetIds.Add(component.netId); if ((Object)(object)owner != (Object)null) { CharacterBody component2 = ((Component)owner).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.master != (Object)null && (Object)(object)component2.master.playerCharacterMasterController != (Object)null) { NetworkUserId id = component2.master.playerCharacterMasterController.networkUser.id; string item = ((id.strValue != null) ? id.strValue : $"{id.value}_{id.subId}"); baggedObjectsPersistenceMessage.ownerPlayerIds.Add(item); } else { baggedObjectsPersistenceMessage.ownerPlayerIds.Add(string.Empty); } } else { baggedObjectsPersistenceMessage.ownerPlayerIds.Add(string.Empty); } bool item2 = false; if ((Object)(object)owner != (Object)null) { BagState state = BagPatches.GetState(owner); if (state != null && state.DisabledCollidersByObject != null && state.DisabledCollidersByObject.ContainsKey(baggedObject)) { item2 = state.DisabledCollidersByObject[baggedObject].Count > 0; } } baggedObjectsPersistenceMessage.collidersDisabled.Add(item2); } if (baggedObjectsPersistenceMessage.baggedObjectNetIds.Count > 0) { NetworkServer.SendToAll((short)201, (MessageBase)(object)baggedObjectsPersistenceMessage); } } [NetworkMessageHandler(msgType = 201, client = true, server = false)] public static void HandleBaggedObjectsPersistenceMessage(NetworkMessage netMsg) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) BaggedObjectsPersistenceMessage baggedObjectsPersistenceMessage = new BaggedObjectsPersistenceMessage(); ((MessageBase)baggedObjectsPersistenceMessage).Deserialize(netMsg.reader); for (int i = 0; i < baggedObjectsPersistenceMessage.baggedObjectNetIds.Count; i++) { NetworkInstanceId netId = baggedObjectsPersistenceMessage.baggedObjectNetIds[i]; string ownerPlayerId = null; bool flag = false; if (i < baggedObjectsPersistenceMessage.ownerPlayerIds.Count) { ownerPlayerId = baggedObjectsPersistenceMessage.ownerPlayerIds[i]; } if (i < baggedObjectsPersistenceMessage.collidersDisabled.Count) { flag = baggedObjectsPersistenceMessage.collidersDisabled[i]; } GameObject val = FindObjectByNetIdWithRetry(netId, 3, 0.1f); if ((Object)(object)val != (Object)null) { ThrownObjectProjectileController component = val.GetComponent(); bool flag2 = PluginConfig.IsBlacklisted(((Object)val).name); if ((Object)(object)component != (Object)null && !flag2) { break; } } if ((Object)(object)val == (Object)null) { break; } if (PersistenceSceneHandler.IsRestoringFromSceneChange()) { PersistenceSceneHandler.HandleSpecialObjectRestoration(val, duringSceneRestoration: true); } else { TeleporterInteraction component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null) { Log.Debug(" Found TeleporterInteraction on " + ((Object)((Component)component2).gameObject).name + " during cycling. Registering as secondary only."); MultiTeleporterTracker.RegisterSecondary(component2); } } if (PersistenceSceneHandler.IsRestoringFromSceneChange()) { VisualRefreshUtility.Refresh(val); if (PersistenceObjectsTracker.IsObjectCurrentlyBagged(val)) { PersistenceObjectsTracker.SetBaggedObjectVisibility(val, isVisible: false); } } PersistenceObjectManager.AddPersistedObject(val, ownerPlayerId); if (!flag || NetworkServer.active) { continue; } DrifterBagController val2 = null; foreach (DrifterBagController allController in BagPatches.GetAllControllers()) { List baggedObjects = BagPatches.GetState(allController).BaggedObjects; if (baggedObjects != null && baggedObjects.Contains(val)) { val2 = allController; break; } } if (!((Object)(object)val2 != (Object)null)) { continue; } BagState state = BagPatches.GetState(val2); if (state != null) { if (!state.DisabledCollidersByObject.ContainsKey(val)) { state.DisabledCollidersByObject[val] = new Dictionary(); } Dictionary originalStates = state.DisabledCollidersByObject[val]; BodyColliderCache.DisableMovementColliders(val, originalStates); } } } [NetworkMessageHandler(msgType = 206, client = true, server = false)] public static void HandleUpdateBagStateMessage(NetworkMessage netMsg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) UpdateBagStateMessage updateBagStateMessage = netMsg.ReadMessage(); GameObject val = ClientScene.FindLocalObject(updateBagStateMessage.controllerNetId); if ((Object)(object)val == (Object)null) { if ((Object)(object)DrifterBossGrabPlugin.Instance != (Object)null) { ((MonoBehaviour)DrifterBossGrabPlugin.Instance).StartCoroutine(RetryFindController(updateBagStateMessage)); } } else { ApplyBagStateUpdate(val, updateBagStateMessage); } } public static void RegisterServerHooks() { if (NetworkServer.active) { Stage.onServerStageComplete += OnServerStageComplete; } } private static void ApplyBagStateUpdate(GameObject controllerObj, UpdateBagStateMessage msg) { //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) BottomlessBagNetworkController component = controllerObj.GetComponent(); if ((Object)(object)component == (Object)null) { return; } DrifterBagController component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null) { return; } BagState state = BagPatches.GetState(component2); if (state == null) { return; } if (!NetworkServer.active) { List baggedObjects = state.BaggedObjects; if (baggedObjects != null) { List list = new List(); if (msg.baggedIds != null) { uint[] baggedIds = msg.baggedIds; foreach (uint num in baggedIds) { GameObject val = FindObjectByNetId(new NetworkInstanceId(num)); if ((Object)(object)val != (Object)null) { list.Add(val); } } } foreach (GameObject item in baggedObjects.ToList()) { if (((Object)(object)item == (Object)null || !Object.op_Implicit((Object)(object)item) || !list.Contains(item)) && (Object)(object)item != (Object)null) { baggedObjects.Remove(item); state.RemoveInstanceId(((Object)item).GetInstanceID()); } } } } if (msg.baggedIds != null) { uint[] baggedIds2 = msg.baggedIds; foreach (uint num2 in baggedIds2) { GameObject val2 = FindObjectByNetId(new NetworkInstanceId(num2)); if (!((Object)(object)val2 != (Object)null)) { continue; } int num3 = Array.IndexOf(msg.baggedIds, num2); if (num3 < 0 || num3 >= msg.collidersDisabled.Length || !msg.collidersDisabled[num3] || NetworkServer.active) { continue; } BagState state2 = BagPatches.GetState(((Component)component).GetComponent()); if (state2 != null) { if (!state2.DisabledCollidersByObject.ContainsKey(val2)) { state2.DisabledCollidersByObject[val2] = new Dictionary(); } Dictionary originalStates = state2.DisabledCollidersByObject[val2]; BodyColliderCache.DisableMovementColliders(val2, originalStates); } } } component.ApplyStateFromMessage(msg.selectedIndex, msg.baggedIds ?? Array.Empty(), msg.seatIds ?? Array.Empty(), msg.scrollDirection, msg.elapsedBreakoutTimes, msg.breakoutAttempts, msg.breakoutTimes); } [IteratorStateMachine(typeof(d__5))] private static IEnumerator RetryFindController(UpdateBagStateMessage msg) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0) { msg = msg }; } private static GameObject? FindObjectByNetId(NetworkInstanceId netId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return FindObjectByNetIdWithRetry(netId, 1, 0f); } private static GameObject? FindObjectByNetIdWithRetry(NetworkInstanceId netId, int maxRetries, float retryDelay) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) if (netId == NetworkInstanceId.Invalid) { return null; } GameObject val = null; int num = 0; GameObject[] persistedObjects = PersistenceObjectManager.GetPersistedObjects(); while (num < maxRetries && (Object)(object)val == (Object)null) { num++; if (!NetworkServer.active) { Scene sceneByName = SceneManager.GetSceneByName("DontDestroyOnLoad"); if (((Scene)(ref sceneByName)).IsValid() && ((Scene)(ref sceneByName)).isLoaded) { GameObject[] rootGameObjects = ((Scene)(ref sceneByName)).GetRootGameObjects(); foreach (GameObject val2 in rootGameObjects) { if ((Object)(object)val2 != (Object)null) { NetworkIdentity component = val2.GetComponent(); if ((Object)(object)component != (Object)null && component.netId == netId) { val = val2; break; } } } } } if ((Object)(object)val == (Object)null) { GameObject[] array = persistedObjects; foreach (GameObject val3 in array) { if ((Object)(object)val3 != (Object)null) { NetworkIdentity component2 = val3.GetComponent(); if ((Object)(object)component2 != (Object)null && component2.netId == netId) { val = val3; break; } } } } if ((Object)(object)val == (Object)null) { foreach (DrifterBagController allController in BagPatches.GetAllControllers()) { List baggedObjects = BagPatches.GetState(allController).BaggedObjects; if (baggedObjects != null) { foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null) { NetworkIdentity component3 = item.GetComponent(); if ((Object)(object)component3 != (Object)null && component3.netId == netId) { val = item; break; } } } } if ((Object)(object)val != (Object)null) { break; } } } if ((Object)(object)val == (Object)null) { val = ClientScene.FindLocalObject(netId); } if ((Object)(object)val == (Object)null && NetworkServer.active) { try { val = NetworkServer.FindLocalObject(netId); } catch { val = null; } } } return val; } private static void OnServerStageComplete(Stage stage) { if (!NetworkServer.active) { return; } DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { BagCarouselUpdater.UpdateNetworkBagState(val); List baggedObjects = BagPatches.GetState(val).BaggedObjects; if (baggedObjects != null) { SendBaggedObjectsPersistenceMessage(baggedObjects, val); } } } } public static class PersistenceObjectManager { private static GameObject? _persistenceContainer; private static readonly HashSet _persistedObjects = new HashSet(); private static readonly Dictionary _persistedObjectOwnerPlayerIds = new Dictionary(); private static readonly Dictionary _bodyToMasterMap = new Dictionary(); private static readonly object _lock = new object(); private static readonly PersistenceCommandInvoker _commandInvoker = new PersistenceCommandInvoker(); private static bool _cachedEnablePersistence; private static bool _cachedEnableAutoGrab; private const string PERSISTENCE_CONTAINER_NAME = "DBG_PersistenceContainer"; public static void Initialize() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)_persistenceContainer != (Object)null)) { _persistenceContainer = new GameObject("DBG_PersistenceContainer"); Object.DontDestroyOnLoad((Object)(object)_persistenceContainer); } } public static void Cleanup() { ClearPersistedObjects(); _bodyToMasterMap.Clear(); if ((Object)(object)_persistenceContainer != (Object)null) { Object.Destroy((Object)(object)_persistenceContainer); _persistenceContainer = null; } } public static void UpdateCachedConfig() { _cachedEnablePersistence = PluginConfig.Instance.EnableObjectPersistence.Value; _cachedEnableAutoGrab = PluginConfig.Instance.EnableAutoGrab.Value; } public static void AddPersistedObject(GameObject obj, string? ownerPlayerId = null) { if (!((Object)(object)obj == (Object)null)) { if (IsPlayerOrSurvivor(obj)) { Log.Debug("[AddPersistedObject] Refusing to add " + ((Object)obj).name + ": Object represents a player or survivor."); return; } if (PluginConfig.IsPersistenceBlacklisted(obj)) { Log.Debug("[AddPersistedObject] Refusing to add " + ((Object)obj).name + ": Object is blacklisted."); return; } AddPersistedObjectCommand command = new AddPersistedObjectCommand(obj, ownerPlayerId); _commandInvoker.ExecuteCommand(command); } } internal static void AddPersistedObjectInternal(GameObject obj, string? ownerPlayerId = null) { if ((Object)(object)obj == (Object)null || !_cachedEnablePersistence) { return; } lock (_lock) { if (!_persistedObjects.Add(obj)) { return; } if (!string.IsNullOrEmpty(ownerPlayerId)) { _persistedObjectOwnerPlayerIds[obj] = ownerPlayerId; } obj.transform.SetParent(_persistenceContainer.transform, true); ModelLocator component = obj.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null) { component.dontDetatchFromParent = true; if ((Object)(object)component.modelTransform.parent != (Object)(object)obj.transform) { component.modelTransform.SetParent(obj.transform, true); } } CharacterBody component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.master != (Object)null && IsValidForPersistence(((Component)component2.master).gameObject)) { AddPersistedObjectInternal(((Component)component2.master).gameObject, ownerPlayerId); } } } public static void RemovePersistedObject(GameObject obj, bool isDestroying = false) { RemovePersistedObjectCommand command = new RemovePersistedObjectCommand(obj, isDestroying); _commandInvoker.ExecuteCommand(command); } internal static void RemovePersistedObjectInternal(GameObject obj, bool isDestroying = false) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (obj == null) { return; } lock (_lock) { if (!_persistedObjects.Remove(obj)) { return; } _persistedObjectOwnerPlayerIds.Remove(obj); if (!isDestroying) { obj.transform.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(obj, SceneManager.GetActiveScene()); } CharacterMaster masterForBody = GetMasterForBody(obj); if ((Object)(object)masterForBody != (Object)null && (Object)(object)((Component)masterForBody).gameObject != (Object)null) { _persistedObjects.Remove(((Component)masterForBody).gameObject); _persistedObjectOwnerPlayerIds.Remove(((Component)masterForBody).gameObject); if ((Object)(object)((Component)masterForBody).gameObject.transform.parent == (Object)(object)_persistenceContainer.transform) { ((Component)masterForBody).gameObject.transform.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(((Component)masterForBody).gameObject, SceneManager.GetActiveScene()); } } _bodyToMasterMap.Remove(obj); } } public static void ClearPersistedObjects() { ClearPersistedObjectsCommand command = new ClearPersistedObjectsCommand(); _commandInvoker.ExecuteCommand(command); } internal static void ClearPersistedObjectsInternal() { lock (_lock) { GameObject[] array = _persistedObjects.ToArray(); foreach (GameObject val in array) { if ((Object)(object)val != (Object)null) { Object.Destroy((Object)(object)val); } } _persistedObjects.Clear(); _persistedObjectOwnerPlayerIds.Clear(); } } public static bool IsPlayerOrSurvivor(GameObject obj) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Invalid comparison between Unknown and I4 if ((Object)(object)obj == (Object)null) { return false; } CharacterBody component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { if (component.isPlayerControlled) { return true; } if ((int)SurvivorCatalog.GetSurvivorIndexFromBodyIndex(component.bodyIndex) != -1) { return true; } } CharacterMaster val = (((Object)(object)component != (Object)null) ? component.master : obj.GetComponent()); if ((Object)(object)val != (Object)null) { if ((Object)(object)val.playerCharacterMasterController != (Object)null) { return true; } if ((Object)(object)val.bodyPrefab != (Object)null) { CharacterBody component2 = val.bodyPrefab.GetComponent(); if ((Object)(object)component2 != (Object)null && (int)SurvivorCatalog.GetSurvivorIndexFromBodyIndex(component2.bodyIndex) != -1) { return true; } } } return false; } public static bool IsValidForPersistence(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } if (_persistedObjects.Contains(obj)) { return false; } if (IsPlayerOrSurvivor(obj)) { Log.Debug("[IsValidForPersistence] Rejected " + ((Object)obj).name + ": Represents a player or survivor."); return false; } ThrownObjectProjectileController component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Log.Debug("[IsValidForPersistence] Rejected " + ((Object)obj).name + ": Is a transient projectile."); return false; } if (PluginConfig.IsPersistenceBlacklisted(obj)) { Log.Debug("[IsValidForPersistence] Rejected " + ((Object)obj).name + ": Matched persistence blacklist."); return false; } return true; } public static void CaptureCurrentlyBaggedObjects() { if (!_cachedEnablePersistence) { return; } lock (_lock) { List list = _persistedObjects.Where((GameObject obj) => (Object)(object)obj != (Object)null && PluginConfig.IsPersistenceBlacklisted(obj)).ToList(); foreach (GameObject item in list) { Log.Debug("[CaptureCurrentlyBaggedObjects] Pruning now-blacklisted object: " + ((Object)item).name); RemovePersistedObjectInternal(item); } } List currentlyBaggedObjects = PersistenceObjectsTracker.GetCurrentlyBaggedObjects(); foreach (GameObject item2 in currentlyBaggedObjects) { if (IsValidForPersistence(item2)) { string baggedObjectOwnerPlayerId = GetBaggedObjectOwnerPlayerId(item2); AddPersistedObject(item2, baggedObjectOwnerPlayerId); } } } internal static string? GetBaggedObjectOwnerPlayerId(GameObject obj) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return null; } DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); if (array == null) { return null; } DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { if ((Object)(object)val.vehicleSeat != (Object)null && (Object)(object)val.vehicleSeat.NetworkpassengerBodyObject == (Object)(object)obj) { CharacterMaster val2 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent(); object obj2; if (val2 == null) { obj2 = null; } else { PlayerCharacterMasterController playerCharacterMasterController = val2.playerCharacterMasterController; obj2 = ((playerCharacterMasterController != null) ? playerCharacterMasterController.networkUser : null); } if ((Object)obj2 != (Object)null) { return NetworkUtils.GetPlayerIdString(val2.playerCharacterMasterController.networkUser.id); } } ConcurrentDictionary additionalSeats = BagPatches.GetState(val).AdditionalSeats; if (additionalSeats == null) { continue; } foreach (KeyValuePair item in additionalSeats) { if ((Object)(object)item.Value.NetworkpassengerBodyObject == (Object)(object)obj) { CharacterMaster val3 = ((Component)val).GetComponent() ?? ((Component)val).GetComponentInParent(); object obj3; if (val3 == null) { obj3 = null; } else { PlayerCharacterMasterController playerCharacterMasterController2 = val3.playerCharacterMasterController; obj3 = ((playerCharacterMasterController2 != null) ? playerCharacterMasterController2.networkUser : null); } if ((Object)obj3 != (Object)null) { return NetworkUtils.GetPlayerIdString(val3.playerCharacterMasterController.networkUser.id); } } } } return null; } internal static CharacterMaster? GetMasterForBody(GameObject bodyObj) { if ((Object)(object)bodyObj == (Object)null) { return null; } lock (_lock) { if (_bodyToMasterMap.TryGetValue(bodyObj, out CharacterMaster value)) { return value; } CharacterBody component = bodyObj.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.master != (Object)null) { _bodyToMasterMap[bodyObj] = component.master; return component.master; } return null; } } public static void MoveObjectsToPersistenceContainer() { lock (_lock) { foreach (GameObject persistedObject in _persistedObjects) { if ((Object)(object)persistedObject != (Object)null && (Object)(object)persistedObject.transform.parent != (Object)(object)_persistenceContainer.transform) { persistedObject.transform.SetParent(_persistenceContainer.transform, true); } } } } public static bool IsObjectPersisted(GameObject obj) { lock (_lock) { return _persistedObjects.Contains(obj); } } public static List GetCurrentlyBaggedObjects() { return PersistenceObjectsTracker.GetCurrentlyBaggedObjects(); } public static int GetPersistedObjectsCount() { lock (_lock) { return _persistedObjects.Count; } } public static GameObject[] GetPersistedObjects() { lock (_lock) { return _persistedObjects.ToArray(); } } internal static HashSet GetPersistedObjectsSet() { return _persistedObjects; } internal static object GetLock() { return _lock; } internal static string? GetPersistedObjectOwnerPlayerId(GameObject obj) { lock (_lock) { string value; return _persistedObjectOwnerPlayerIds.TryGetValue(obj, out value) ? value : null; } } internal static bool GetCachedEnablePersistence() { return _cachedEnablePersistence; } internal static bool GetCachedEnableAutoGrab() { return _cachedEnableAutoGrab; } } public static class PersistenceObjectsTracker { private static readonly HashSet _currentlyBaggedObjects = new HashSet(); private static readonly object _lock = new object(); public static void SetBaggedObjectVisibility(GameObject obj, bool isVisible) { if ((Object)(object)obj == (Object)null) { return; } try { ModelLocator component = obj.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null) { CharacterModel component2 = ((Component)component.modelTransform).GetComponent(); if ((Object)(object)component2 != (Object)null) { if (!isVisible) { if (component2.invisibilityCount <= 0) { int invisibilityCount = component2.invisibilityCount; component2.invisibilityCount = invisibilityCount + 1; } } else if (component2.invisibilityCount > 0) { int invisibilityCount = component2.invisibilityCount; component2.invisibilityCount = invisibilityCount - 1; } } } SpecialObjectAttributes component3 = obj.GetComponent(); if (!((Object)(object)component3 != (Object)null)) { return; } if (component3.renderersToDisable != null) { foreach (Renderer item in component3.renderersToDisable) { if ((Object)(object)item != (Object)null) { item.forceRenderingOff = !isVisible; } } } if (component3.lightsToDisable != null) { foreach (Light item2 in component3.lightsToDisable) { if ((Object)(object)item2 != (Object)null) { ((Behaviour)item2).enabled = isVisible; } } } if (component3.pickupDisplaysToDisable != null) { foreach (PickupDisplay item3 in component3.pickupDisplaysToDisable) { if ((Object)(object)item3 != (Object)null) { item3.SetRenderersEnabled(isVisible); } } } if (component3.childObjectsToDisable == null) { return; } foreach (GameObject item4 in component3.childObjectsToDisable) { if ((Object)(object)item4 != (Object)null) { item4.SetActive(isVisible); } } } catch (Exception arg) { Log.Error($"[SetBaggedObjectVisibility] Exception during visibility update for {((Object)obj).name}: {arg}"); } } public static void TrackBaggedObject(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_lock) { _currentlyBaggedObjects.Add(obj); SetBaggedObjectVisibility(obj, isVisible: false); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($" Tracking bagged object: {((Object)obj).name} (total tracked: {_currentlyBaggedObjects.Count})"); } if (PluginConfig.Instance.EnableDebugLogs.Value) { HealthComponent component = obj.GetComponent(); Log.Debug($"[DEBUG] [TrackBaggedObject] {((Object)obj).name}: alive={((component != null) ? new bool?(component.alive) : null)}"); } } } public static void UntrackBaggedObject(GameObject obj, bool isDestroying = false) { if (obj == null) { return; } lock (_lock) { if (_currentlyBaggedObjects.Remove(obj)) { if (PluginConfig.Instance.EnableDebugLogs.Value) { HealthComponent component = obj.GetComponent(); Log.Debug($"[DEBUG] [UntrackBaggedObject] {((Object)obj).name}: alive={((component != null) ? new bool?(component.alive) : null)}, isDestroying={isDestroying}"); } PersistenceManager.RemovePersistedObject(obj, isDestroying); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($" Untracked bagged object: {((Object)obj).name} (total tracked: {_currentlyBaggedObjects.Count})"); } if (!isDestroying) { SetBaggedObjectVisibility(obj, isVisible: true); } } } } public static List GetCurrentlyBaggedObjects() { lock (_lock) { _currentlyBaggedObjects.RemoveWhere((GameObject obj) => (Object)(object)obj == (Object)null); return _currentlyBaggedObjects.ToList(); } } public static bool IsObjectCurrentlyBagged(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } lock (_lock) { return _currentlyBaggedObjects.Contains(obj); } } public static void ClearTrackedObjects() { lock (_lock) { _currentlyBaggedObjects.Clear(); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug(" Cleared all tracked bagged objects"); } } } } public class PersistenceSceneHandler { private class PersistenceCoroutineRunner : MonoBehaviour { private void OnDestroy() { Log.Debug(" PersistenceCoroutineRunner destroyed - cleanup completed"); } } private class BossGroupCleanupRunner : MonoBehaviour { [CompilerGenerated] private sealed class d__3 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BossGroupCleanupRunner <>4__this; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__3(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { int num = <>1__state; BossGroupCleanupRunner bossGroupCleanupRunner = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -1; try { CharacterBody body = bossGroupCleanupRunner._characterMaster.GetBody(); if ((Object)(object)body != (Object)null) { BossGroup val = BossGroup.FindBossGroup(body); if ((Object)(object)val != (Object)null) { val.ForgetBoss(bossGroupCleanupRunner._characterMaster); Log.Debug(" Removed persisted boss " + bossGroupCleanupRunner._objectName + " from BossGroup to prevent teleporter interference"); } } } catch (Exception ex) { Log.Error("[DelayedBossGroupCleanup] Error: " + ex.Message); } Object.Destroy((Object)(object)((Component)bossGroupCleanupRunner).gameObject); 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 CharacterMaster? _characterMaster; private string? _objectName; public void Initialize(CharacterMaster characterMaster, string objectName) { _characterMaster = characterMaster; _objectName = objectName; ((MonoBehaviour)this).StartCoroutine(DelayedBossGroupCleanup()); } [IteratorStateMachine(typeof(d__3))] private IEnumerator DelayedBossGroupCleanup() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__3(0) { <>4__this = this }; } } private class PersistedObjectSeeker : MonoBehaviour { [CompilerGenerated] private sealed class d__2 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public PersistedObjectSeeker <>4__this; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__2(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; PersistedObjectSeeker persistedObjectSeeker = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = 0f; break; case 1: { <>1__state = -1; 5__2 += 0.5f; NetworkUser val = FindNetworkUserById(persistedObjectSeeker._ownerPlayerId); if (!((Object)(object)val != (Object)null)) { break; } CharacterMaster master = val.master; CharacterBody val2 = ((master != null) ? master.GetBody() : null); if ((Object)(object)val2 != (Object)null) { Vector3 position = val2.transform.position; Vector3 forward = val2.transform.forward; Vector3 val3 = position + forward * 0.5f + Vector3.up * 0.5f; Log.Debug($"[PersistedObjectSeeker] Found owner {((Object)val2).name} after {5__2:F2}s. Teleporting {((Object)persistedObjectSeeker).name} to {val3}"); ((Component)persistedObjectSeeker).transform.position = val3; ((Component)persistedObjectSeeker).transform.rotation = Quaternion.identity; Rigidbody val4 = default(Rigidbody); if (((Component)persistedObjectSeeker).TryGetComponent(ref val4)) { val4.velocity = Vector3.zero; val4.angularVelocity = Vector3.zero; } Object.Destroy((Object)(object)persistedObjectSeeker); return false; } break; } } if (5__2 < 60f) { if (!NetworkServer.active) { Object.Destroy((Object)(object)persistedObjectSeeker); return false; } <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 1; return true; } Log.Debug("[PersistedObjectSeeker] Timeout seeking owner for " + ((Object)persistedObjectSeeker).name + ". Staying at current position."); Object.Destroy((Object)(object)persistedObjectSeeker); 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 string _ownerPlayerId = string.Empty; public void Initialize(string ownerId) { _ownerPlayerId = ownerId; ((MonoBehaviour)this).StartCoroutine(SeekOwnerCoroutine()); } [IteratorStateMachine(typeof(d__2))] private IEnumerator SeekOwnerCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__2(0) { <>4__this = this }; } } [CompilerGenerated] private sealed class d__16 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject obj; public PersistenceCoroutineRunner runner; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__16(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 //IL_00c7: Unknown result type (might be due to invalid IL or missing references) switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(1.5f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)obj != (Object)null) { Rigidbody component = obj.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.FindStateForObject(obj); if (baggedObjectStateData != null && baggedObjectStateData.hasCapturedRigidbodyState) { component.isKinematic = baggedObjectStateData.originalIsKinematic; component.useGravity = baggedObjectStateData.originalUseGravity; component.mass = baggedObjectStateData.originalMass; component.drag = baggedObjectStateData.originalDrag; component.angularDrag = baggedObjectStateData.originalAngularDrag; component.detectCollisions = true; } else { component.isKinematic = false; component.detectCollisions = true; } component.velocity = Vector3.zero; } } if ((Object)(object)runner != (Object)null && (Object)(object)((Component)runner).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)runner).gameObject); } 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 d__20 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public GameObject obj; public string ownerPlayerId; public PersistenceCoroutineRunner runner; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__20(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)obj != (Object)null) { TryAutoGrabObject(obj, ownerPlayerId); } if ((Object)(object)runner != (Object)null && (Object)(object)((Component)runner).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)runner).gameObject); } 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 d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private PersistenceCoroutineRunner 5__2; private int 5__3; private int 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 1u) { try { } finally { <>m__Finally1(); } } 5__2 = null; <>1__state = -2; } private bool MoveNext() { try { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = null; <>1__state = -3; 5__2 = Object.FindFirstObjectByType(); <>2__current = null; <>1__state = 1; return true; case 1: <>1__state = -3; 5__3 = 120; 5__4 = 0; break; case 2: <>1__state = -3; break; } if (5__4 < 5__3) { if (!AnyPlayerHasBody()) { 5__4++; <>2__current = null; <>1__state = 2; return true; } Log.Debug($" Any player body found after {5__4} frames, proceeding with restoration"); } RestorePersistedObjects(); <>m__Finally1(); return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; if ((Object)(object)5__2 != (Object)null) { Object.Destroy((Object)(object)((Component)5__2).gameObject); } } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } private static bool isRestoringFromSceneChange; private static readonly FieldInfo _clientSceneObjectsField; private static IDictionary? _clientSceneObjects; public static PersistenceSceneHandler Instance { get; } public static bool IsRestoringFromSceneChange() { return isRestoringFromSceneChange; } static PersistenceSceneHandler() { isRestoringFromSceneChange = false; Instance = new PersistenceSceneHandler(); _clientSceneObjectsField = AccessTools.Field(typeof(ClientScene), "objects") ?? AccessTools.Field(typeof(ClientScene), "s_LocalObjects"); if (_clientSceneObjectsField != null) { try { _clientSceneObjects = _clientSceneObjectsField.GetValue(null) as IDictionary; } catch { _clientSceneObjects = null; } } } private static NetworkUser? FindNetworkUserById(string playerId) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(playerId)) { return null; } ReadOnlyCollection readOnlyInstancesList = NetworkUser.readOnlyInstancesList; foreach (NetworkUser item in readOnlyInstancesList) { if (NetworkUtils.GetPlayerIdString(item.id) == playerId) { return item; } } if (readOnlyInstancesList.Count == 1) { NetworkUser val = readOnlyInstancesList[0]; Log.Debug("[FindNetworkUserById] ID mismatch '" + playerId + "' != '" + NetworkUtils.GetPlayerIdString(val.id) + "', but only one player found. Using fallback."); return val; } if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning($"[FindNetworkUserById] Failed to find owner {playerId} among {readOnlyInstancesList.Count} players."); } return null; } public void OnSceneChanged(Scene oldScene, Scene newScene) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Expected O, but got Unknown if (!PersistenceObjectManager.GetCachedEnablePersistence()) { Log.Debug(" Persistence disabled, skipping scene change handling for " + ((Scene)(ref newScene)).name); return; } Log.Debug($" Scene changed from {((Scene)(ref oldScene)).name} to {((Scene)(ref newScene)).name}, restoring {PersistenceObjectManager.GetPersistedObjectsCount()} persisted objects"); GameObject val = new GameObject("PersistenceCoroutineRunner"); PersistenceCoroutineRunner persistenceCoroutineRunner = val.AddComponent(); isRestoringFromSceneChange = true; ((MonoBehaviour)persistenceCoroutineRunner).StartCoroutine(DelayedRestorePersistedObjects()); } [IteratorStateMachine(typeof(d__10))] private static IEnumerator DelayedRestorePersistedObjects() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0); } private static bool AnyPlayerHasBody() { foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { CharacterMaster master = readOnlyInstances.master; if ((Object)(object)((master != null) ? master.GetBody() : null) != (Object)null) { return true; } } return false; } public static void RestorePersistedObjects() { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_03ee: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_04a4: Unknown result type (might be due to invalid IL or missing references) //IL_04ab: Expected O, but got Unknown //IL_0438: Unknown result type (might be due to invalid IL or missing references) //IL_043f: Expected O, but got Unknown HashSet persistedObjectsSet = PersistenceObjectManager.GetPersistedObjectsSet(); object @lock = PersistenceObjectManager.GetLock(); lock (@lock) { Log.Debug($" Starting restoration of {persistedObjectsSet.Count} persisted objects"); List list = new List(); List list2 = new List(); GameObject[] array = persistedObjectsSet.ToArray(); GameObject[] array2 = array; Rigidbody val3 = default(Rigidbody); foreach (GameObject val in array2) { if ((Object)(object)val == (Object)null) { list.Add(null); continue; } if (PluginConfig.IsPersistenceBlacklisted(val)) { Log.Debug("[RestorePersistedObjects] Skipping restoration of " + ((Object)val).name + ": Object is blacklisted."); Object.Destroy((Object)(object)val); list.Add(val); continue; } HealthComponent component = val.GetComponent(); Log.Debug($"[DEBUG] [RestorePersistedObjects LOOP] {((Object)val).name}: alive={((component != null) ? new bool?(component.alive) : null)}, activeInHierarchy={val.activeInHierarchy}"); bool flag = val.scene == SceneManager.GetActiveScene(); NetworkIdentity component2 = val.GetComponent(); if (flag) { Log.Debug($"[RestorePersistedObjects] Skipping object {((Object)val).name} (NetID: {((component2 != null) ? new NetworkInstanceId?(component2.netId) : null)}) - already in active scene."); if (PluginConfig.Instance.EnableDebugLogs.Value && (Object)(object)component != (Object)null && !component.alive) { Log.Warning($"[DEBUG] [RestorePersistedObjects] SKIPPED object {((Object)val).name} is already in scene but is DEAD! alive={component.alive}"); } continue; } string[] obj = new string[6] { " Restoring object ", ((Object)val).name, " to scene (currently parented to: ", null, null, null }; Transform parent = val.transform.parent; obj[3] = ((parent != null) ? ((Object)parent).name : null) ?? "null"; obj[4] = ") from "; Scene scene = val.scene; obj[5] = ((Scene)(ref scene)).name; Log.Debug(string.Concat(obj)); val.transform.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(val, SceneManager.GetActiveScene()); BodyColliderCache component3 = val.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.RefreshCache(); Log.Debug("[RestorePersistedObjects] Refreshed BodyColliderCache for " + ((Object)val).name); } ModelLocator component4 = val.GetComponent(); if ((Object)(object)component4 != (Object)null && (Object)(object)component4.modelTransform != (Object)null) { GameObject gameObject = ((Component)component4.modelTransform).gameObject; if ((Object)(object)gameObject.transform.parent != (Object)(object)val.transform) { Log.Debug("[RestorePersistedObjects] Re-parenting model " + ((Object)gameObject).name + " to body " + ((Object)val).name); gameObject.transform.SetParent(val.transform, true); gameObject.transform.localPosition = Vector3.zero; gameObject.transform.localRotation = Quaternion.identity; } VisualRefreshUtility.Refresh(val); } if (NetworkServer.active) { bool flag2 = PositionNearPlayer(val); string persistedObjectOwnerPlayerId = PersistenceObjectManager.GetPersistedObjectOwnerPlayerId(val); if (!flag2 && !string.IsNullOrEmpty(persistedObjectOwnerPlayerId)) { Log.Debug("[RestorePersistedObjects] Specific owner for " + ((Object)val).name + " not found. Attaching PersistedObjectSeeker."); PersistedObjectSeeker persistedObjectSeeker = val.AddComponent(); persistedObjectSeeker.Initialize(persistedObjectOwnerPlayerId); } try { if ((Object)(object)component2 != (Object)null) { TeleporterInteraction component5 = val.GetComponent(); if ((Object)(object)component5 != (Object)null) { object? obj2 = ReflectionCache.TeleporterInteraction.BossDirector?.GetValue(component5); CombatDirector val2 = (CombatDirector)((obj2 is CombatDirector) ? obj2 : null); if ((Object)(object)val2 != (Object)null) { CombatDirectorPatches.MarkTeleporterDirectorAsRestoring(val2); } } NetworkServer.UnSpawn(val); NetworkServer.Spawn(val); } } catch (Exception ex) { Log.Error("[RestorePersistedObjects] Error refreshing network identity: " + ex.Message); } } else if ((Object)(object)component2 != (Object)null) { Log.Debug($"[RestorePersistedObjects] Client: preserving object {((Object)val).name} (NetID: {component2.netId}). Re-registering with ClientScene."); PositionNearPlayer(val); RegisterLocalObjectReflectively(component2); if (val.TryGetComponent(ref val3)) { val3.isKinematic = true; GameObject val4 = new GameObject("ClientSafetyFloatRunner_" + ((Object)val).name); PersistenceCoroutineRunner persistenceCoroutineRunner = val4.AddComponent(); ((MonoBehaviour)persistenceCoroutineRunner).StartCoroutine(ClientSafetyFloat(val, persistenceCoroutineRunner)); } } else { PositionNearPlayer(val); Rigidbody component6 = val.GetComponent(); if (Object.op_Implicit((Object)(object)component6)) { component6.isKinematic = true; Log.Debug("[RestorePersistedObjects] Enabled Kinematic Safety for local object " + ((Object)val).name); } GameObject val5 = new GameObject("ClientSafetyFloatRunner_" + ((Object)val).name); PersistenceCoroutineRunner persistenceCoroutineRunner2 = val5.AddComponent(); ((MonoBehaviour)persistenceCoroutineRunner2).StartCoroutine(ClientSafetyFloat(val, persistenceCoroutineRunner2)); } val.SetActive(true); RestoreRenderers(val); HandleSpecialObjectRestoration(val, duringSceneRestoration: true); if (PersistenceObjectManager.GetCachedEnableAutoGrab() && NetworkServer.active) { ScheduleAutoGrabForObject(val); } list2.Add(val); } foreach (GameObject item in list) { persistedObjectsSet.Remove(item); } foreach (GameObject item2 in list2) { persistedObjectsSet.Remove(item2); } if (NetworkServer.active) { foreach (GameObject item3 in list2) { if ((Object)(object)item3 == (Object)null) { continue; } CharacterMaster masterForBody = PersistenceObjectManager.GetMasterForBody(item3); if ((Object)(object)masterForBody != (Object)null) { CharacterBody component7 = item3.GetComponent(); if ((Object)(object)component7 != (Object)null) { Log.Debug("[RestorePersistedObjects] Re-linked master " + ((Object)masterForBody).name + " to body " + ((Object)item3).name); } } } } Log.Debug($"[RestorePersistedObjects] Restoration complete. {list2.Count} objects restored."); isRestoringFromSceneChange = false; } } private static void RestoreRenderers(GameObject obj) { Renderer[] componentsInChildren = obj.GetComponentsInChildren(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { val.enabled = true; } ModelLocator component = obj.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null) { ((Component)component.modelTransform).gameObject.SetActive(true); Renderer[] componentsInChildren2 = ((Component)component.modelTransform).GetComponentsInChildren(true); Renderer[] array2 = componentsInChildren2; foreach (Renderer val2 in array2) { val2.enabled = true; } } } [IteratorStateMachine(typeof(d__16))] private static IEnumerator ClientSafetyFloat(GameObject obj, PersistenceCoroutineRunner runner) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__16(0) { obj = obj, runner = runner }; } private static bool PositionNearPlayer(GameObject obj) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) string persistedObjectOwnerPlayerId = PersistenceObjectManager.GetPersistedObjectOwnerPlayerId(obj); CharacterBody val = null; bool flag = false; if (!string.IsNullOrEmpty(persistedObjectOwnerPlayerId)) { NetworkUser val2 = FindNetworkUserById(persistedObjectOwnerPlayerId); if ((Object)(object)val2 != (Object)null) { CharacterMaster master = val2.master; val = ((master != null) ? master.GetBody() : null); if ((Object)(object)val != (Object)null) { flag = true; } } } if ((Object)(object)val == (Object)null) { NetworkUser val3 = ((IEnumerable)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func)((NetworkUser nu) => ((NetworkBehaviour)nu).isServer)); if ((Object)(object)val3 != (Object)null && (Object)(object)val3.master != (Object)null) { val = val3.master.GetBody(); } } if ((Object)(object)val == (Object)null) { object obj2; if (NetworkUser.readOnlyLocalPlayersList.Count <= 0) { obj2 = null; } else { NetworkUser obj3 = NetworkUser.readOnlyLocalPlayersList[0]; if (obj3 == null) { obj2 = null; } else { CharacterMaster master2 = obj3.master; obj2 = ((master2 != null) ? master2.GetBody() : null); } } val = (CharacterBody)obj2; } if ((Object)(object)val != (Object)null) { Vector3 position = val.transform.position; Vector3 forward = val.transform.forward; Vector3 val4 = position + forward * 0.5f + Vector3.up * 0.5f; obj.transform.position = val4; obj.transform.rotation = Quaternion.identity; Log.Debug(string.Format(" Positioned {0} at {1} near {2} body {3} (Pos: {4})", ((Object)obj).name, val4, flag ? "owner" : "fallback", ((Object)val).name, position)); return flag; } Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 position2 = ((Component)main).transform.position; Vector3 forward2 = ((Component)main).transform.forward; Vector3 val5 = position2 + forward2 * 2f; obj.transform.position = val5; obj.transform.rotation = Quaternion.identity; Log.Debug($" Used camera fallback positioning for {((Object)obj).name} at {val5}"); } else { obj.transform.position = new Vector3(0f, 1f, 0f); obj.transform.rotation = Quaternion.identity; Log.Debug(" Used origin fallback positioning for " + ((Object)obj).name); } return false; } public static void ScheduleAutoGrabForObject(GameObject obj, string? ownerPlayerId = null) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown if (NetworkServer.active && !((Object)(object)obj == (Object)null)) { GameObject val = new GameObject("ServerAutoGrabRunner_" + ((Object)obj).name); PersistenceCoroutineRunner persistenceCoroutineRunner = val.AddComponent(); ((MonoBehaviour)persistenceCoroutineRunner).StartCoroutine(DelayedAutoGrab(obj, ownerPlayerId, persistenceCoroutineRunner, PluginConfig.Instance.AutoGrabDelay.Value)); } } [IteratorStateMachine(typeof(d__20))] private static IEnumerator DelayedAutoGrab(GameObject obj, string? ownerPlayerId, PersistenceCoroutineRunner runner, float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__20(0) { obj = obj, ownerPlayerId = ownerPlayerId, runner = runner, delay = delay }; } public static void TryAutoGrabObject(GameObject obj, string? ownerPlayerId = null) { //IL_0540: Unknown result type (might be due to invalid IL or missing references) //IL_0547: Expected O, but got Unknown if (!NetworkServer.active || (Object)(object)obj == (Object)null) { return; } if (PluginConfig.IsPersistenceBlacklisted(obj)) { Log.Debug("[TryAutoGrabObject] Aborting auto-grab for " + ((Object)obj).name + ": Object is blacklisted."); return; } if ((Object)(object)obj.GetComponent() != (Object)null) { Log.Debug(" Skipping auto-grab for " + ((Object)obj).name + " - is CharacterMaster"); return; } HealthComponent component = obj.GetComponent(); if ((Object)(object)component != (Object)null && !component.alive) { Log.Debug($" Skipping auto-grab for {((Object)obj).name} - object is dead (alive={component.alive})"); return; } Log.Debug($"[DEBUG] [TryAutoGrabObject ENTRY] {((Object)obj).name}: alive={((component != null) ? new bool?(component.alive) : null)}, activeInHierarchy={obj.activeInHierarchy}"); Log.Debug(" Attempting auto-grab for restored object " + ((Object)obj).name); CharacterBody val = null; if (string.IsNullOrEmpty(ownerPlayerId)) { ownerPlayerId = PersistenceObjectManager.GetPersistedObjectOwnerPlayerId(obj); } if (!string.IsNullOrEmpty(ownerPlayerId)) { NetworkUser val2 = FindNetworkUserById(ownerPlayerId); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.master != (Object)null) { val = val2.master.GetBody(); if ((Object)(object)val != (Object)null) { Log.Debug(" Found owner body " + ((Object)val).name + " for object " + ((Object)obj).name + " via player ID " + ownerPlayerId); } } } else { ReadOnlyCollection readOnlyInstancesList = NetworkUser.readOnlyInstancesList; if (readOnlyInstancesList.Count == 1) { NetworkUser val3 = readOnlyInstancesList[0]; CharacterMaster master = val3.master; val = ((master != null) ? master.GetBody() : null); } } if ((Object)(object)val == (Object)null) { if (!PluginConfig.Instance.EnableDebugLogs.Value) { return; } if (!string.IsNullOrEmpty(ownerPlayerId)) { NetworkUser val4 = FindNetworkUserById(ownerPlayerId); Log.Debug("[TryAutoGrabObject DEBUG] ownerPlayerId: " + ownerPlayerId); Log.Debug($"[TryAutoGrabObject DEBUG] user found: {(Object)(object)val4 != (Object)null}"); if ((Object)(object)val4 != (Object)null) { Log.Debug($"[TryAutoGrabObject DEBUG] user.master found: {(Object)(object)val4.master != (Object)null}"); if ((Object)(object)val4.master != (Object)null) { Log.Debug($"[TryAutoGrabObject DEBUG] user.master.GetBody() found: {(Object)(object)val4.master.GetBody() != (Object)null}"); } } Log.Debug(" Owner Drifter (player ID: " + ownerPlayerId + ") not found in scene yet for " + ((Object)obj).name + ". Object will remain ungrabbed until owner spawns."); } else { Log.Debug(" No owner assigned to " + ((Object)obj).name + ". Object will remain ungrabbed (backward compatibility for unowned objects)."); } return; } if ((Object)(object)val == (Object)null) { Log.Debug(" No Drifter body found in scene to auto-grab " + ((Object)obj).name); return; } DrifterBagController component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 == (Object)null) { Log.Debug(" No DrifterBagController found on target body " + ((Object)val).name); return; } if (BagCapacityCalculator.HasRoomForGrab(component2)) { try { Log.Debug(" Server assigning " + ((Object)obj).name + " to " + ((Object)val).name + "'s bag (Suppression Enabled)"); SpecialObjectAttributes component3 = obj.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.childSpecialObjectAttributes?.RemoveAll((SpecialObjectAttributes s) => (Object)(object)s == (Object)null); component3.renderersToDisable?.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); component3.behavioursToDisable?.RemoveAll((MonoBehaviour b) => (Object)(object)b == (Object)null); component3.childObjectsToDisable?.RemoveAll((GameObject c) => (Object)(object)c == (Object)null); component3.pickupDisplaysToDisable?.RemoveAll((PickupDisplay p) => (Object)(object)p == (Object)null); component3.lightsToDisable?.RemoveAll((Light l) => (Object)(object)l == (Object)null); component3.objectsToDetach?.RemoveAll((GameObject o) => (Object)(object)o == (Object)null); component3.skillHighlightRenderers?.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); } component2.AssignPassenger(obj); if ((Object)(object)BagPatches.GetMainSeatObject(component2) == (Object)(object)obj) { EntityStateMachine val5 = EntityStateMachine.FindByCustomName(((Component)val).gameObject, "Bag"); if ((Object)(object)val5 != (Object)null) { Log.Debug(" Setting BaggedObject state on " + ((Object)val).name + " for " + ((Object)obj).name); BaggedObject val6 = new BaggedObject(); val6.targetObject = obj; val5.SetNextState((EntityState)(object)val6); } } return; } catch (Exception arg) { Log.Error($"[TryAutoGrabObject] Error assigning passenger: {arg}"); return; } } Log.Debug(" Drifter bag for " + ((Object)val).name + " is full, cannot auto-grab " + ((Object)obj).name); } public void ScheduleAutoGrab(CharacterMaster master) { //IL_0417: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Expected O, but got Unknown //IL_0437: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_0517: Unknown result type (might be due to invalid IL or missing references) //IL_051c: Unknown result type (might be due to invalid IL or missing references) //IL_05dd: Unknown result type (might be due to invalid IL or missing references) //IL_05e2: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Expected O, but got Unknown //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || !PersistenceObjectManager.GetCachedEnableAutoGrab()) { return; } Log.Debug(" Executing immediate auto-grab for Drifter"); CharacterBody body = master.GetBody(); if ((Object)(object)body == (Object)null) { Log.Debug(" No body found for Drifter during auto-grab"); return; } DrifterBagController component = ((Component)master).GetComponent(); if ((Object)(object)component == (Object)null) { component = ((Component)body).GetComponent(); Log.Debug(" Found bag controller on body during auto-grab"); } else { Log.Debug(" Found bag controller on master during auto-grab"); } if ((Object)(object)component == (Object)null) { Log.Debug(" No DrifterBagController found on Drifter master or body"); return; } string text = null; CharacterBody component2 = ((Component)body).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.master != (Object)null && (Object)(object)component2.master.playerCharacterMasterController != (Object)null) { NetworkUserId id = component2.master.playerCharacterMasterController.networkUser.id; text = ((id.strValue != null) ? id.strValue : $"{id.value}_{id.subId}"); Log.Debug(" Drifter player ID: " + text); } List list = new List(); object @lock = PersistenceObjectManager.GetLock(); lock (@lock) { foreach (GameObject item in PersistenceObjectManager.GetPersistedObjectsSet()) { if ((Object)(object)item != (Object)null && item.scene == SceneManager.GetActiveScene()) { list.Add(item); } } } Log.Debug($" Found {list.Count} persisted objects in scene for auto-grab"); List list2 = new List(); List currentlyBaggedObjects = PersistenceObjectManager.GetCurrentlyBaggedObjects(); foreach (GameObject item2 in currentlyBaggedObjects) { if ((Object)(object)item2 != (Object)null && item2.scene == SceneManager.GetActiveScene()) { list2.Add(item2); } } Log.Debug($" Found {list2.Count} currently bagged objects in scene for auto-grab"); List list3 = new List(); list3.AddRange(list); list3.AddRange(list2); List list4 = new List(); foreach (GameObject item3 in list3) { string persistedObjectOwnerPlayerId = PersistenceObjectManager.GetPersistedObjectOwnerPlayerId(item3); if (string.IsNullOrEmpty(persistedObjectOwnerPlayerId) || persistedObjectOwnerPlayerId == text) { list4.Add(item3); } } Log.Debug($" Total objects to attempt auto-grab for Drifter {text}: {list4.Count} (filtered from {list3.Count} total)"); foreach (GameObject item4 in list4) { if ((Object)(object)item4.GetComponent() != (Object)null) { Log.Debug(" Skipping auto-grab for " + ((Object)item4).name + " - is CharacterMaster"); continue; } if (!BagCapacityCalculator.HasRoomForGrab(component)) { Log.Debug(" Drifter bag is full, stopping auto-grab"); break; } if ((Object)(object)item4.GetComponent() != (Object)null) { if (BagCapacityCalculator.GetCurrentBaggedCount(component) == 0) { EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)body).gameObject, "Bag"); if ((Object)(object)val != (Object)null) { try { Log.Debug(" Found Bag state machine, setting BaggedObject state for " + ((Object)item4).name); BaggedObject val2 = new BaggedObject(); val2.targetObject = item4; val.SetNextState((EntityState)(object)val2); Log.Debug(" Successfully initiated auto-grab for " + ((Object)item4).name + " using EntityStateMachine"); } catch (Exception ex) { Log.Error("[ScheduleAutoGrab] Error setting EntityStateMachine: " + ex.Message); } } else { Log.Debug(" Could not find Bag state machine for CharacterBody " + ((Object)item4).name); } continue; } try { Log.Debug(" Manually assigning CharacterBody " + ((Object)item4).name + " to additional seat"); GameObject val3 = new GameObject($"AdditionalSeat_AutoGrab_{DateTime.Now.Ticks}"); val3.transform.SetParent(((Component)component).transform); val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.identity; VehicleSeat val4 = val3.AddComponent(); val4.seatPosition = component.vehicleSeat.seatPosition; val4.exitPosition = component.vehicleSeat.exitPosition; val4.ejectOnCollision = component.vehicleSeat.ejectOnCollision; val4.hidePassenger = component.vehicleSeat.hidePassenger; val4.exitVelocityFraction = component.vehicleSeat.exitVelocityFraction; val4.disablePassengerMotor = component.vehicleSeat.disablePassengerMotor; val4.isEquipmentActivationAllowed = component.vehicleSeat.isEquipmentActivationAllowed; val4.shouldProximityHighlight = component.vehicleSeat.shouldProximityHighlight; val4.disableInteraction = component.vehicleSeat.disableInteraction; val4.shouldSetIdle = component.vehicleSeat.shouldSetIdle; val4.additionalExitVelocity = component.vehicleSeat.additionalExitVelocity; val4.disableAllCollidersAndHurtboxes = component.vehicleSeat.disableAllCollidersAndHurtboxes; val4.disableColliders = component.vehicleSeat.disableColliders; val4.disableCharacterNetworkTransform = component.vehicleSeat.disableCharacterNetworkTransform; val4.ejectFromSeatOnMapEvent = component.vehicleSeat.ejectFromSeatOnMapEvent; val4.inheritRotation = component.vehicleSeat.inheritRotation; val4.holdPassengerAfterDeath = component.vehicleSeat.holdPassengerAfterDeath; val4.ejectPassengerToGround = component.vehicleSeat.ejectPassengerToGround; val4.ejectRayDistance = component.vehicleSeat.ejectRayDistance; val4.handleExitTeleport = component.vehicleSeat.handleExitTeleport; val4.setCharacterMotorPositionToCurrentPosition = component.vehicleSeat.setCharacterMotorPositionToCurrentPosition; val4.passengerState = component.vehicleSeat.passengerState; val4.AssignPassenger(item4); List list5 = BagPatches.GetState(component).BaggedObjects; if (list5 == null) { list5 = new List(); BagPatches.GetState(component).BaggedObjects = list5; } if (!list5.Contains(item4)) { list5.Add(item4); } ConcurrentDictionary additionalSeats = BagPatches.GetState(component).AdditionalSeats; additionalSeats[item4] = val4; Log.Debug(" Successfully auto-grabbed CharacterBody " + ((Object)item4).name + " to additional seat"); } catch (Exception ex2) { Log.Error("[ScheduleAutoGrab] Error assigning to additional seat: " + ex2.Message); } continue; } try { Log.Debug(" Directly assigning " + ((Object)item4).name + " to bag for auto-grab (Suppression Enabled)"); component.AssignPassenger(item4); if ((Object)(object)BagPatches.GetMainSeatObject(component) == (Object)(object)item4) { BaggedObjectPatches.RefreshUIOverlayForMainSeat(component, item4); } Log.Debug(" Successfully auto-grabbed " + ((Object)item4).name + " using direct assignment"); } catch (Exception ex3) { Log.Error("[ScheduleAutoGrab] Error assigning passenger: " + ex3.Message); } } } public static void HandleSpecialObjectRestoration(GameObject obj, bool duringSceneRestoration = false) { //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Expected O, but got Unknown if ((Object)(object)obj == (Object)null) { return; } if (PluginConfig.IsPersistenceBlacklisted(obj)) { Log.Debug("[HandleSpecialObjectRestoration] Destroying blacklisted object " + ((Object)obj).name); Object.Destroy((Object)(object)obj); return; } TeleporterInteraction component = obj.GetComponent(); string text = ((Object)obj).name.ToLower(); Log.Debug(" Checking for TeleporterInteraction on persisted object " + ((Object)obj).name); if ((Object)(object)component != (Object)null) { Log.Debug(" Found TeleporterInteraction on " + ((Object)((Component)component).gameObject).name + " for persisted object " + ((Object)obj).name + ". Registering as secondary and patching references."); if (isRestoringFromSceneChange) { TeleporterPatches.PatchStaleReferences(component); } MultiTeleporterTracker.RegisterSecondary(component); Log.Debug("[HandleSpecialObjectRestoration] Successfully patched stale references for " + ((Object)obj).name); } if (duringSceneRestoration) { VisualRefreshUtility.Refresh(obj); } else { Log.Debug(" No TeleporterInteraction found on persisted object " + ((Object)obj).name); } CharacterMaster component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { CharacterBody body = component2.GetBody(); if ((Object)(object)body != (Object)null) { GameObject val = new GameObject("BossGroupCleanupRunner"); BossGroupCleanupRunner bossGroupCleanupRunner = val.AddComponent(); bossGroupCleanupRunner.Initialize(component2, ((Object)obj).name); } } Animator component3 = obj.GetComponent(); if (!((Object)(object)component3 != (Object)null)) { return; } try { if (!((Object)(object)component3.runtimeAnimatorController == (Object)null)) { return; } ModelLocator component4 = obj.GetComponent(); if ((Object)(object)component4 != (Object)null && (Object)(object)component4.modelTransform != (Object)null) { Animator component5 = ((Component)component4.modelTransform).GetComponent(); if ((Object)(object)component5 != (Object)null && (Object)(object)component5.runtimeAnimatorController != (Object)null) { component3.runtimeAnimatorController = component5.runtimeAnimatorController; Log.Debug(" Restored Animator controller on " + ((Object)obj).name + " from model"); } } if ((Object)(object)component3.runtimeAnimatorController == (Object)null) { ((Behaviour)component3).enabled = false; Log.Debug(" Disabled broken Animator on " + ((Object)obj).name + " to prevent NullReferenceException spam"); } } catch (Exception ex) { Log.Error("[HandleSpecialObjectRestoration] Error fixing animator: " + ex.Message); } } private static void RegisterLocalObjectReflectively(NetworkIdentity networkIdentity) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) try { if (_clientSceneObjects != null) { if (!_clientSceneObjects.ContainsKey(networkIdentity.netId)) { _clientSceneObjects.Add(networkIdentity.netId, networkIdentity); Log.Debug($"[RegisterLocalObjectReflectively] Successfully registered NetID {networkIdentity.netId} with ClientScene via cached reflection."); } else { Log.Debug($"[RegisterLocalObjectReflectively] NetID {networkIdentity.netId} already registered in ClientScene."); } } else if (_clientSceneObjectsField == null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[RegisterLocalObjectReflectively] Could not find 'objects' dictionary in ClientScene"); } } else if (_clientSceneObjectsField.GetValue(null) is IDictionary dictionary) { if (!dictionary.ContainsKey(networkIdentity.netId)) { dictionary.Add(networkIdentity.netId, networkIdentity); Log.Debug($"[RegisterLocalObjectReflectively] Successfully registered NetID {networkIdentity.netId} with ClientScene via fallback Reflection."); } else { Log.Debug($"[RegisterLocalObjectReflectively] NetID {networkIdentity.netId} already registered in ClientScene."); } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[RegisterLocalObjectReflectively] Field found but value is null or not IDictionary"); } } catch (Exception ex) { Log.Error("[RegisterLocalObjectReflectively] Error: " + ex.Message); } } } public class RecoveryFeature : FeatureToggleBase { public override string FeatureName => "Recovery"; public override bool IsEnabled => PluginConfig.Instance.EnableRecoveryFeature.Value; protected override void ApplyPatches(Harmony harmony) { harmony.CreateClassProcessor(typeof(ProjectileRecoveryPatches.MapZone_TryZoneStart_Patch)).Patch(); } } public class TeleporterFeature : FeatureToggleBase { public override string FeatureName => "Teleporter"; public override bool IsEnabled { get { if (PluginConfig.Instance.EnableObjectPersistence.Value) { return !PluginConfig.IsPersistenceBlacklisted("Teleporter"); } return false; } } protected override void ApplyPatches(Harmony harmony) { harmony.CreateClassProcessor(typeof(TeleporterPatches)).Patch(); harmony.CreateClassProcessor(typeof(BossGroupPatches)).Patch(); harmony.CreateClassProcessor(typeof(TeleporterSafetyPatches)).Patch(); harmony.CreateClassProcessor(typeof(CombatDirectorPatches)).Patch(); } } public interface IConfigObserver { void OnConfigChanged(string key, object value); } public interface IGrabbingStrategy { bool CanGrab(GameObject obj); } public interface IPluginConfig { ConfigEntry BreakoutTimeMultiplier { get; } ConfigEntry EnableBossGrabbing { get; } ConfigEntry EnableNPCGrabbing { get; } ConfigEntry EnableEnvironmentGrabbing { get; } ConfigEntry EnableLockedObjectGrabbing { get; } ConfigEntry ProjectileGrabbingMode { get; } ConfigEntry MaxSmacks { get; } ConfigEntry EnableDebugLogs { get; } ConfigEntry BodyBlacklist { get; } ConfigEntry RecoveryObjectBlacklist { get; } ConfigEntry GrabbableComponentTypes { get; } ConfigEntry GrabbableKeywordBlacklist { get; } ConfigEntry EnableObjectPersistence { get; } ConfigEntry EnableAutoGrab { get; } ConfigEntry PersistBaggedBosses { get; } ConfigEntry PersistBaggedNPCs { get; } ConfigEntry PersistBaggedEnvironmentObjects { get; } ConfigEntry PersistenceBlacklist { get; } ConfigEntry BottomlessBagEnabled { get; } ConfigEntry AddedCapacity { get; } ConfigEntry EnableMouseWheelScrolling { get; } bool IsBlacklisted(string? name); bool IsRecoveryBlacklisted(string? name); bool IsKeywordBlacklisted(string? name); bool IsGrabbable(GameObject? obj); void Init(ConfigFile cfg); void RemoveEventHandlers(EventHandler debugLogsHandler, EventHandler blacklistHandler, EventHandler recoveryBlacklistHandler, EventHandler grabbableComponentTypesHandler, EventHandler grabbableKeywordBlacklistHandler, EventHandler bossGrabbingHandler, EventHandler npcGrabbingHandler, EventHandler environmentGrabbingHandler, EventHandler lockedObjectGrabbingHandler); void ClearBlacklistCache(); void ClearRecoveryBlacklistCache(); void ClearGrabbableComponentTypesCache(); void ClearGrabbableKeywordBlacklistCache(); } } namespace DrifterBossGrabMod.Input { internal static class InputSetup { private delegate void UserDataInitDelegate(UserData self); private static bool _initialized; private static MethodInfo? _actionElementMapApplyMethod; private static Hook? _userDataHook; internal static void Init() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Expected O, but got Unknown //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Expected O, but got Unknown //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Expected O, but got Unknown if (_initialized) { return; } _initialized = true; Log.Debug("[InputSetup] Initializing Rewired input actions..."); AddActionsToInputCatalog(); Harmony val = new Harmony("com.pwdcat.DrifterBossGrab.input"); MethodInfo methodInfo = FindUserDataInitMethod(); if (methodInfo != null) { Log.Debug("[InputSetup] Found UserData init method: " + methodInfo.Name + " (DeclaringType: " + methodInfo.DeclaringType?.FullName + ")"); try { _userDataHook = new Hook((MethodBase)methodInfo, typeof(InputSetup).GetMethod("AddCustomActions", BindingFlags.Static | BindingFlags.NonPublic)); Log.Debug("[InputSetup] Successfully hooked UserData init method via MonoMod.RuntimeDetour.Hook"); } catch (Exception arg) { Log.Warning($"[InputSetup] Failed to hook UserData init via MonoMod.RuntimeDetour.Hook: {arg}"); } } else { Log.Warning("[InputSetup] Could not find UserData initialization method!"); Log.Warning("[InputSetup] Dumping all non-public void instance methods on UserData:"); MethodInfo[] methods = typeof(UserData).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.ReturnType == typeof(void) && methodInfo2.GetParameters().Length == 0) { Log.Debug("[InputSetup] Candidate: " + methodInfo2.Name); } } } _actionElementMapApplyMethod = FindActionElementMapApplyMethod(); if (_actionElementMapApplyMethod != null) { Log.Debug("[InputSetup] Found ActionElementMap apply method: " + _actionElementMapApplyMethod.Name); } else { Log.Debug("[InputSetup] ActionElementMap apply method not found. Using fallback for profile bindings."); } MethodInfo methodInfo3 = AccessTools.Method(typeof(UserProfile), "LoadDefaultProfile", (Type[])null, (Type[])null); if (methodInfo3 != null) { val.Patch((MethodBase)methodInfo3, (HarmonyMethod)null, new HarmonyMethod(typeof(InputSetup), "OnLoadDefaultProfile", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo4 = AccessTools.Method(typeof(UserProfile), "FillDefaultJoystickMaps", (Type[])null, (Type[])null); if (methodInfo4 != null) { val.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(typeof(InputSetup), "OnFillDefaultJoystickMaps", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo5 = AccessTools.Method(typeof(SaveSystem), "LoadUserProfiles", (Type[])null, (Type[])null); if (methodInfo5 != null) { val.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(typeof(InputSetup), "OnLoadUserProfiles", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo6 = AccessTools.Method(typeof(SettingsPanelController), "Start", (Type[])null, (Type[])null); if (methodInfo6 != null) { val.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(typeof(InputSetup), "OnSettingsPanelStart", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } MethodInfo methodInfo7 = AccessTools.Method(typeof(Language), "GetString", new Type[1] { typeof(string) }, (Type[])null); if (methodInfo7 != null) { val.Patch((MethodBase)methodInfo7, new HarmonyMethod(typeof(InputSetup), "OnLanguageGetString", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } Log.Debug("[InputSetup] Rewired input actions registered successfully."); } private static bool OnLanguageGetString(string token, ref string __result) { if (token == RewiredActions.ScrollBagUp.DisplayToken) { __result = "Scroll Bag Up"; return false; } if (token == RewiredActions.ScrollBagDown.DisplayToken) { __result = "Scroll Bag Down"; return false; } return true; } private static MethodInfo? FindUserDataInitMethod() { FieldInfo actionsField = AccessTools.Field(typeof(UserData), "actions"); if (actionsField == null) { Log.Warning("[InputSetup] Could not find UserData.actions field for method discovery."); return null; } Log.Debug($"[InputSetup] Looking for methods referencing field: {actionsField.Name} ({actionsField.FieldType})"); MethodInfo methodInfo = null; int num = 0; MethodInfo[] methods = typeof(UserData).GetMethods(BindingFlags.Instance | BindingFlags.NonPublic); foreach (MethodInfo methodInfo2 in methods) { if (methodInfo2.ReturnType != typeof(void) || methodInfo2.GetParameters().Length != 0) { continue; } try { List currentInstructions = PatchProcessor.GetCurrentInstructions((MethodBase)methodInfo2, int.MaxValue, (ILGenerator)null); if (currentInstructions.Any((CodeInstruction instr) => (instr.opcode == OpCodes.Ldfld || instr.opcode == OpCodes.Stfld) && instr.operand is FieldInfo fieldInfo && fieldInfo == actionsField)) { int num2 = methodInfo2.GetMethodBody()?.LocalVariables.Count ?? 0; Log.Debug($"[InputSetup] Found candidate method: {methodInfo2.Name} (locals={num2}, IL instructions={currentInstructions.Count})"); if (num2 > num) { methodInfo = methodInfo2; num = num2; } } } catch (Exception ex) { Log.Debug("[InputSetup] Could not analyze method " + methodInfo2.Name + ": " + ex.GetType().Name); } } if (methodInfo != null) { Log.Debug($"[InputSetup] Selected best candidate: {methodInfo.Name} (locals={num})"); } return methodInfo; } private static MethodInfo? FindActionElementMapApplyMethod() { return ReflectionCache.Rewired.ActionElementMap.GetApplyToControllerMapMethod(); } private static void ApplyElementMapToControllerMap(ActionElementMap elementMap, ControllerMap controllerMap) { if (_actionElementMapApplyMethod != null) { _actionElementMapApplyMethod.Invoke(elementMap, new object[1] { controllerMap }); } } private static void AddActionsToInputCatalog() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) InputCatalog.actionToToken[RewiredActions.ScrollBagUp] = RewiredActions.ScrollBagUp.DisplayToken; InputCatalog.actionToToken[RewiredActions.ScrollBagDown] = RewiredActions.ScrollBagDown.DisplayToken; } private static void AddCustomActions(UserDataInitDelegate orig, UserData self) { Log.Debug("[InputSetup] AddCustomActions hook fired!"); if (self.actions != null) { RewiredActions[] array = new RewiredActions[2] { RewiredActions.ScrollBagUp, RewiredActions.ScrollBagDown }; foreach (RewiredActions action in array) { InputAction val = self.actions.Find((InputAction a) => a.name == action.Name); if (val != null) { Log.Debug($"[InputSetup] Action '{action.Name}' already registered (id={val.id}). Skipping."); continue; } int actionId = action.ActionId; int num = 0; while (self.actions.Exists((InputAction a) => a.id == action.ActionId) && num < 50) { action.ActionId++; num++; } if (num >= 50) { Log.Warning($"[InputSetup] Could not find free ActionId for '{action.Name}' after 50 attempts starting from {actionId}. Skipping."); continue; } if (action.ActionId != actionId) { Log.Warning($"[InputSetup] ActionId collision for '{action.Name}': {actionId} was taken, resolved to {action.ActionId}."); } self.actions.Add(action); Log.Debug($"[InputSetup] Added action '{action.Name}' (id={action.ActionId}) to UserData.actions"); } if (self.keyboardMaps != null && self.joystickMaps != null) { FillActionMaps(RewiredActions.ScrollBagUp, self.keyboardMaps, self.joystickMaps); FillActionMaps(RewiredActions.ScrollBagDown, self.keyboardMaps, self.joystickMaps); } } else { Log.Warning("[InputSetup] UserData.actions is null!"); } orig(self); Log.Debug("[InputSetup] Original UserData init completed."); } private static void OnLoadUserProfiles(SaveSystem __instance) { foreach (var (arg, val2) in __instance.loadedUserProfiles) { try { AddMissingBindings(val2); val2.RequestEventualSave(); } catch (Exception arg2) { Log.Warning($"[InputSetup] Failed to add default bindings to '{arg}' profile: {arg2}"); } } } private static void OnLoadDefaultProfile() { try { AddMissingBindings(UserProfile.defaultProfile); } catch (Exception arg) { Log.Warning($"[InputSetup] Failed to add default bindings to default profile: {arg}"); } } private static void OnFillDefaultJoystickMaps(UserProfile __instance) { AddMissingBindings(__instance); } private static void OnSettingsPanelStart(SettingsPanelController __instance) { if (((Object)__instance).name == "SettingsSubPanel, Controls (M&KB)" || ((Object)__instance).name == "SettingsSubPanel, Controls (Gamepad)") { Transform val = ((Component)__instance).transform.Find("Scroll View/Viewport/VerticalLayout/SettingsEntryButton, Binding (Jump)"); if ((Object)(object)val != (Object)null) { AddActionBindingToSettings(RewiredActions.ScrollBagUp.Name, val); AddActionBindingToSettings(RewiredActions.ScrollBagDown.Name, val); Log.Debug("[InputSetup] Added keybind entries to " + ((Object)__instance).name); } else { Log.Warning("[InputSetup] Could not find Jump binding transform in " + ((Object)__instance).name); } } } private static void AddActionBindingToSettings(string actionName, Transform buttonToCopy) { Transform val = Object.Instantiate(buttonToCopy, buttonToCopy.parent); InputBindingControl component = ((Component)val).GetComponent(); component.actionName = actionName; component.Awake(); } private static void AddMissingBindings(UserProfile userProfile) { AddActionMaps(RewiredActions.ScrollBagUp, userProfile); AddActionMaps(RewiredActions.ScrollBagDown, userProfile); } private static void FillActionMaps(RewiredActions action, List keyboardMaps, List joystickMaps) { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) RewiredActions action2 = action; foreach (ControllerMap_Editor joystickMap in joystickMaps) { if (joystickMap.categoryId == 0 && joystickMap.actionElementMaps.All((ActionElementMap map) => map.actionId != action2.ActionId)) { joystickMap.actionElementMaps.Add(action2.DefaultJoystickMap); } } foreach (ControllerMap_Editor keyboardMap in keyboardMaps) { if (keyboardMap.categoryId == 0 && keyboardMap.actionElementMaps.All((ActionElementMap map) => map.actionId != action2.ActionId) && (int)action2.DefaultKeyboardKey != 0) { keyboardMap.actionElementMaps.Add(action2.DefaultKeyboardMap); } } } private static void AddActionMaps(RewiredActions action, UserProfile userProfile) { //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) RewiredActions action2 = action; foreach (var (_, val2) in userProfile.HardwareJoystickMaps2) { if (((ControllerMap)val2).AllMaps.All((ActionElementMap m) => m.actionId != action2.ActionId)) { ((ControllerMap)val2).CreateElementMap(action2.DefaultJoystickMap.actionId, action2.DefaultJoystickMap.axisContribution, action2.DefaultJoystickMap.elementIdentifierId, action2.DefaultJoystickMap.elementType, action2.DefaultJoystickMap.axisRange, action2.DefaultJoystickMap.invert); ApplyElementMapToControllerMap(action2.DefaultJoystickMap, (ControllerMap)(object)val2); } } if ((int)action2.DefaultKeyboardKey != 0 && ((ControllerMap)userProfile.keyboardMap).AllMaps.All((ActionElementMap m) => m.actionId != action2.ActionId)) { ActionElementMap val3 = default(ActionElementMap); ((ControllerMap)userProfile.keyboardMap).CreateElementMap(action2.DefaultKeyboardMap.actionId, action2.DefaultKeyboardMap.axisContribution, action2.DefaultKeyboardMap.elementIdentifierId, action2.DefaultJoystickMap.elementType, action2.DefaultJoystickMap.axisRange, action2.DefaultJoystickMap.invert, ref val3); val3._keyboardKeyCode = action2.DefaultKeyboardKey; ApplyElementMapToControllerMap(action2.DefaultKeyboardMap, (ControllerMap)(object)userProfile.keyboardMap); } } } public class RewiredActions { private ActionElementMap? _defaultJoystickMap; private ActionElementMap? _defaultKeyboardMap; private InputAction? _inputAction; public static RewiredActions ScrollBagUp { get; } public static RewiredActions ScrollBagDown { get; } public int ActionId { get; internal set; } public string Name { get; private set; } = ""; public string DisplayToken { get; private set; } = ""; public KeyboardKeyCode DefaultKeyboardKey { get; private set; } public int DefaultJoystickKey { get; private set; } public ActionElementMap DefaultJoystickMap { get { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0026: Expected O, but got Unknown ActionElementMap obj = _defaultJoystickMap; if (obj == null) { ActionElementMap val = new ActionElementMap(ActionId, (ControllerElementType)1, DefaultJoystickKey, (Pole)0, (AxisRange)1); ActionElementMap val2 = val; _defaultJoystickMap = val; obj = val2; } return obj; } } public ActionElementMap DefaultKeyboardMap { get { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Expected I4, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown //IL_0033: Expected O, but got Unknown ActionElementMap obj = _defaultKeyboardMap; if (obj == null) { ActionElementMap val = new ActionElementMap(ActionId, (ControllerElementType)1, DefaultKeyboardKey - 21) { _keyboardKeyCode = DefaultKeyboardKey }; ActionElementMap val2 = val; _defaultKeyboardMap = val; obj = val2; } return obj; } } static RewiredActions() { ScrollBagUp = new RewiredActions { ActionId = 420, Name = "ScrollBagUp", DisplayToken = "DRIFTERBOSSGRAB_SCROLL_BAG_UP", DefaultKeyboardKey = (KeyboardKeyCode)0, DefaultJoystickKey = 16 }; ScrollBagDown = new RewiredActions { ActionId = 690, Name = "ScrollBagDown", DisplayToken = "DRIFTERBOSSGRAB_SCROLL_BAG_DOWN", DefaultKeyboardKey = (KeyboardKeyCode)0, DefaultJoystickKey = 18 }; } public static implicit operator ActionAxisPair(RewiredActions action) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return new ActionAxisPair(action.Name, (AxisRange)0); } public static implicit operator InputAction(RewiredActions action) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0059: Expected O, but got Unknown InputAction obj = action._inputAction; if (obj == null) { InputAction val = new InputAction(); val.QurFqcdYtHIEpCpYBddZfQQtnImHA(action.ActionId); val.LEWtVuPGPZtPpCUSAMYCEbPqyAuf(action.Name); val.nLGCfekdjaMIxCLlcjdYgcEjEDxz((InputActionType)1); val.nfWwbfSEwQCdVSicPaIBIPkMqJfu(action.Name); val.MFwTFVDRoziRWNJMARlSUXIebtLw(0); val.BSFQAxJApIZsVFnOmINQEGShHPvFb(true); val.REsRGcKFtjbUwlqUSreCTUubayPb(0); InputAction val2 = val; action._inputAction = val; obj = val2; } return obj; } } } namespace DrifterBossGrabMod.ProperSave { public static class ProperSaveConstants { public static class Timing { public const int MaxDirectorCoreWaitAttempts = 300; public const float DirectorCoreWaitIncrement = 0.1f; public const float PostDirectorCoreWait = 0.5f; public const float PostRegistryRebuildWait = 0.3f; } } public static class ProperSaveIntegration { [CompilerGenerated] private sealed class d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(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 (_pendingSaveData == null) { return false; } Log.Debug($"[ProperSave] Starting WaitForDirectorCoreAndRestore coroutine for {_pendingSaveData.BaggedObjects?.Count ?? 0} objects"); ((MonoBehaviour)Run.instance).StartCoroutine(WaitForDirectorCoreAndRestore()); 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 d__21 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject obj; public BaggedObjectSaveData objData; public Action onComplete; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__21(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; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -1; RestoreObjectState(obj, objData); onComplete?.Invoke(); 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 d__24 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public List<(GameObject obj, BaggedObjectSaveData data)> objectsToRestore; private int 5__2; private int 5__3; private List<(GameObject obj, BaggedObjectSaveData data)>.Enumerator <>7__wrap3; private GameObject 5__5; private BaggedObjectSaveData 5__6; private GameObject 5__7; private bool 5__8; private CharacterMaster 5__9; private int 5__10; private int 5__11; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__24(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { int num = <>1__state; if (num == -3 || (uint)(num - 1) <= 2u) { try { } finally { <>m__Finally1(); } } <>7__wrap3 = default(List<(GameObject, BaggedObjectSaveData)>.Enumerator); 5__5 = null; 5__6 = null; 5__7 = null; 5__9 = null; <>1__state = -2; } private bool MoveNext() { try { CharacterBody body; switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0; 5__3 = 0; <>7__wrap3 = objectsToRestore.GetEnumerator(); <>1__state = -3; break; case 1: <>1__state = -3; <>2__current = null; <>1__state = 2; return true; case 2: <>1__state = -3; 5__7 = 5__5; 5__8 = (Object)(object)5__5.GetComponent() != (Object)null; if (5__8) { 5__9 = 5__5.GetComponent(); if ((Object)(object)5__9 != (Object)null) { 5__10 = 0; 5__11 = 30; goto IL_0145; } goto IL_01b3; } goto IL_01bb; case 3: { <>1__state = -3; 5__10++; goto IL_0145; } IL_01b3: 5__9 = null; goto IL_01bb; IL_0145: if ((Object)(object)5__9.GetBody() == (Object)null && 5__10 < 5__11) { <>2__current = null; <>1__state = 3; return true; } body = 5__9.GetBody(); if ((Object)(object)body != (Object)null) { 5__7 = ((Component)body).gameObject; 5__8 = false; Log.Debug("[RestoreAllObjects] Auto-grabbing body " + ((Object)body).name + " from master " + ((Object)5__9).name); } goto IL_01b3; IL_01bb: try { Log.Debug($"[RestoreAllObjects] Restoring {((Object)5__5).name} (frame {Time.frameCount})"); BodyColliderCache component = 5__5.GetComponent(); if ((Object)(object)component != (Object)null) { component.RefreshCache(); Log.Debug("[RestoreAllObjects] Refreshed BodyColliderCache for " + ((Object)5__5).name); } HealthComponent component2 = 5__5.GetComponent(); if ((Object)(object)component2 != (Object)null) { Log.Debug($"[RestoreAllObjects] Health BEFORE restoration: health={component2.health}, fullHealth={component2.fullHealth}"); } RestoreObjectState(5__5, 5__6); HealthComponent component3 = 5__5.GetComponent(); if ((Object)(object)component3 != (Object)null) { Log.Debug($"[RestoreAllObjects] Health AFTER restoration: health={component3.health}, fullHealth={component3.fullHealth}, healthFraction={component3.healthFraction}"); } if (!5__8 && (5__6.IsMainSeatObject.GetValueOrDefault() || 5__6.AdditionalSeatIndex.HasValue || PersistenceObjectManager.GetCachedEnableAutoGrab())) { PersistenceSceneHandler.ScheduleAutoGrabForObject(5__7, 5__6.OwnerPlayerId); } 5__2++; } catch (Exception ex) { 5__3++; Log.Error("[ProperSave] Exception restoring " + 5__6?.PrefabName + ": " + ex.Message); } 5__7 = null; 5__5 = null; 5__6 = null; break; } if (<>7__wrap3.MoveNext()) { (GameObject, BaggedObjectSaveData) current = <>7__wrap3.Current; 5__5 = current.Item1; 5__6 = current.Item2; <>2__current = null; <>1__state = 1; return true; } <>m__Finally1(); <>7__wrap3 = default(List<(GameObject, BaggedObjectSaveData)>.Enumerator); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[ProperSave] Restoration complete: {5__2} success, {5__3} failed"); } return false; } catch { //try-fault ((IDisposable)this).Dispose(); throw; } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } private void <>m__Finally1() { <>1__state = -1; ((IDisposable)<>7__wrap3).Dispose(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class d__11 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private int 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 0; goto IL_005f; case 1: <>1__state = -1; 5__2++; goto IL_005f; case 2: <>1__state = -1; try { SpawnCardRegistry.RebuildRegistry(); } catch (Exception ex) { Log.Error("[ProperSave] Failed to rebuild spawn card registry: " + ex.Message); _pendingSaveData = null; return false; } <>2__current = (object)new WaitForSeconds(0.3f); <>1__state = 3; return true; case 3: { <>1__state = -1; Log.Debug($"[ProperSave] Restoring {_pendingSaveData.BaggedObjects.Count} bagged objects"); RestoreBagState(_pendingSaveData); _pendingSaveData = null; return false; } IL_005f: if ((Object)(object)DirectorCore.instance == (Object)null && 5__2 < 300) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } if ((Object)(object)DirectorCore.instance == (Object)null) { Log.Error("[ProperSave] DirectorCore not available after 30 seconds, aborting restoration"); _pendingSaveData = null; return false; } if (_pendingSaveData == null) { return false; } if (_pendingSaveData.BaggedObjects == null) { Log.Error("[ProperSave] BaggedObjects list is null in save data, aborting restoration"); _pendingSaveData = null; return false; } <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 2; return true; } } 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 const string SAVE_KEY = "DrifterBossGrabMod_BagData"; private const string PROPER_SAVE_GUID = "com.KingEnderBrine.ProperSave"; private static readonly List _serializerPlugins = new List(); private static bool _initialized = false; private static bool _properSaveAvailable = false; private static DrifterBagSaveData? _pendingSaveData; public static void Initialize() { if (_initialized) { return; } _properSaveAvailable = IsProperSaveAvailable(); if (!_properSaveAvailable) { return; } RegisterBuiltInPlugins(); Run.onRunStartGlobal += OnRunStart; SceneManager.activeSceneChanged += OnActiveSceneChanged; Assembly assembly = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly a) => a.GetName().Name == "ProperSave"); if (assembly == null) { Log.Error("[ProperSave] Could not find ProperSave assembly"); return; } Type type = assembly.GetType("ProperSave.SaveFile"); Type type2 = assembly.GetType("ProperSave.Loading"); if (type == null || type2 == null) { Log.Error("[ProperSave] Could not find ProperSave types"); return; } EventInfo @event = type.GetEvent("OnGatherSaveData"); EventInfo event2 = type2.GetEvent("OnLoadingStarted"); if (@event == null || event2 == null) { Log.Error("[ProperSave] Could not find ProperSave events"); return; } MethodInfo method = typeof(ProperSaveIntegration).GetMethod("OnGatherSaveData", BindingFlags.Static | BindingFlags.NonPublic); MethodInfo method2 = typeof(ProperSaveIntegration).GetMethod("OnLoadingStarted", BindingFlags.Static | BindingFlags.NonPublic); if (method == null || method2 == null) { Log.Error("[ProperSave] Could not find handler methods"); return; } @event.AddEventHandler(null, Delegate.CreateDelegate(@event.EventHandlerType, method)); event2.AddEventHandler(null, Delegate.CreateDelegate(event2.EventHandlerType, method2)); _initialized = true; Log.Debug($"[ProperSave] Integration initialized with {_serializerPlugins.Count} plugins"); } public static void Cleanup() { if (_initialized) { Run.onRunStartGlobal -= OnRunStart; SceneManager.activeSceneChanged -= OnActiveSceneChanged; SpawnCardRegistry.Cleanup(); _serializerPlugins.Clear(); _pendingSaveData = null; _initialized = false; } } private static void OnRunStart(Run run) { Log.Debug("[ProperSave] OnRunStart called, _pendingSaveData is " + ((_pendingSaveData == null) ? "null" : $"not null ({_pendingSaveData.BaggedObjects?.Count ?? 0} objects)")); } private static void OnActiveSceneChanged(Scene prevScene, Scene nextScene) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) Log.Debug("[ProperSave] OnActiveSceneChanged called - prevScene: " + ((Scene)(ref prevScene)).name + ", nextScene: " + ((Scene)(ref nextScene)).name); if (_pendingSaveData != null) { ((MonoBehaviour)Run.instance).StartCoroutine(DelayedSceneLoadRestoration(nextScene)); } } [IteratorStateMachine(typeof(d__10))] private static IEnumerator DelayedSceneLoadRestoration(Scene scene) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0); } [IteratorStateMachine(typeof(d__11))] private static IEnumerator WaitForDirectorCoreAndRestore() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__11(0); } private static void RegisterBuiltInPlugins() { Log.Debug("[ProperSaveIntegration] Registering built-in serializer plugins..."); IObjectSerializerPlugin objectSerializerPlugin = BuiltInSerializersAPI.ForCharacterMaster(); _serializerPlugins.Add(objectSerializerPlugin); Log.Debug($" - Added: {objectSerializerPlugin.GetType().Name} (Priority: {objectSerializerPlugin.Priority})"); IObjectSerializerPlugin objectSerializerPlugin2 = BuiltInSerializersAPI.ForCharacterBody(); _serializerPlugins.Add(objectSerializerPlugin2); Log.Debug($" - Added: {objectSerializerPlugin2.GetType().Name} (Priority: {objectSerializerPlugin2.Priority})"); IObjectSerializerPlugin objectSerializerPlugin3 = BuiltInSerializersAPI.ForChest(); _serializerPlugins.Add(objectSerializerPlugin3); Log.Debug($" - Added: {objectSerializerPlugin3.GetType().Name} (Priority: {objectSerializerPlugin3.Priority})"); IObjectSerializerPlugin objectSerializerPlugin4 = BuiltInSerializersAPI.ForDuplicator(); _serializerPlugins.Add(objectSerializerPlugin4); Log.Debug($" - Added: {objectSerializerPlugin4.GetType().Name} (Priority: {objectSerializerPlugin4.Priority})"); IObjectSerializerPlugin objectSerializerPlugin5 = BuiltInSerializersAPI.ForShrine(); _serializerPlugins.Add(objectSerializerPlugin5); Log.Debug($" - Added: {objectSerializerPlugin5.GetType().Name} (Priority: {objectSerializerPlugin5.Priority})"); IObjectSerializerPlugin objectSerializerPlugin6 = BuiltInSerializersAPI.ForSpecialObjectAttributes(); _serializerPlugins.Add(objectSerializerPlugin6); Log.Debug($" - Added: {objectSerializerPlugin6.GetType().Name} (Priority: {objectSerializerPlugin6.Priority})"); IObjectSerializerPlugin objectSerializerPlugin7 = BuiltInSerializersAPI.ForJunkCubeController(); _serializerPlugins.Add(objectSerializerPlugin7); Log.Debug($" - Added: {objectSerializerPlugin7.GetType().Name} (Priority: {objectSerializerPlugin7.Priority})"); IObjectSerializerPlugin objectSerializerPlugin8 = BuiltInSerializersAPI.ForHalcyoniteShrineInteractable(); _serializerPlugins.Add(objectSerializerPlugin8); Log.Debug($" - Added: {objectSerializerPlugin8.GetType().Name} (Priority: {objectSerializerPlugin8.Priority})"); IObjectSerializerPlugin objectSerializerPlugin9 = BuiltInSerializersAPI.ForTinkerableObjectAttributes(); _serializerPlugins.Add(objectSerializerPlugin9); Log.Debug($" - Added: {objectSerializerPlugin9.GetType().Name} (Priority: {objectSerializerPlugin9.Priority})"); IObjectSerializerPlugin objectSerializerPlugin10 = BuiltInSerializersAPI.ForTeleporterInteraction(); _serializerPlugins.Add(objectSerializerPlugin10); Log.Debug($" - Added: {objectSerializerPlugin10.GetType().Name} (Priority: {objectSerializerPlugin10.Priority})"); IObjectSerializerPlugin objectSerializerPlugin11 = BuiltInSerializersAPI.ForPurchaseInteraction(); _serializerPlugins.Add(objectSerializerPlugin11); Log.Debug($" - Added: {objectSerializerPlugin11.GetType().Name} (Priority: {objectSerializerPlugin11.Priority})"); IObjectSerializerPlugin objectSerializerPlugin12 = BuiltInSerializersAPI.ForGenericComponentSerializer(); _serializerPlugins.Add(objectSerializerPlugin12); Log.Debug($" - Added: {objectSerializerPlugin12.GetType().Name} (Priority: {objectSerializerPlugin12.Priority})"); IObjectSerializerPlugin objectSerializerPlugin13 = BuiltInSerializersAPI.ForQualityIntegration(); _serializerPlugins.Add(objectSerializerPlugin13); Log.Debug($" - Added: {objectSerializerPlugin13.GetType().Name} (Priority: {objectSerializerPlugin13.Priority})"); _serializerPlugins.Sort((IObjectSerializerPlugin a, IObjectSerializerPlugin b) => b.Priority.CompareTo(a.Priority)); Log.Debug($"[ProperSaveIntegration] Total registered plugins: {_serializerPlugins.Count}"); } public static void RegisterPlugin(IObjectSerializerPlugin plugin) { if (plugin != null) { _serializerPlugins.Add(plugin); _serializerPlugins.Sort((IObjectSerializerPlugin a, IObjectSerializerPlugin b) => b.Priority.CompareTo(a.Priority)); Log.Debug($"[Serializer] Registered plugin: {plugin.GetType().Name} (Priority: {plugin.Priority})"); } } public static List GetSerializerPlugins() { return new List(_serializerPlugins); } private static void OnGatherSaveData(Dictionary gatheredData) { if (PluginConfig.Instance.EnableObjectPersistence.Value) { DrifterBagSaveData drifterBagSaveData2 = (DrifterBagSaveData)(gatheredData["DrifterBossGrabMod_BagData"] = CreateSaveData()); Log.Debug($"[ProperSave] Saved {drifterBagSaveData2.BaggedObjects.Count} bagged objects"); } } private static void OnLoadingStarted(object saveFile) { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return; } try { Type type = saveFile.GetType(); MethodInfo method = type.GetMethod("GetModdedData"); if (method == null) { Log.Error("[ProperSave] Could not find GetModdedData method"); return; } MethodInfo methodInfo = method.MakeGenericMethod(typeof(DrifterBagSaveData)); DrifterBagSaveData drifterBagSaveData = (DrifterBagSaveData)methodInfo.Invoke(saveFile, new object[1] { "DrifterBossGrabMod_BagData" }); if (drifterBagSaveData != null) { _pendingSaveData = drifterBagSaveData; Log.Debug($"[ProperSave] Queued {drifterBagSaveData.BaggedObjects.Count} bagged objects for restoration"); } } catch (Exception ex) { Log.Error("[ProperSave] Failed to queue bag data: " + ex.Message); } } private static DrifterBagSaveData CreateSaveData() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) DrifterBagSaveData drifterBagSaveData = new DrifterBagSaveData(); Scene activeScene = SceneManager.GetActiveScene(); drifterBagSaveData.SaveSceneName = ((Scene)(ref activeScene)).name; drifterBagSaveData.StageClearCount = Run.instance?.stageClearCount ?? 0; DrifterBagSaveData drifterBagSaveData2 = drifterBagSaveData; SpawnCardRegistry.Initialize(); GameObject[] persistedObjects = PersistenceObjectManager.GetPersistedObjects(); HashSet capturedInstanceIds = new HashSet(); Dictionary dictionary = new Dictionary(); DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { if ((Object)(object)val == (Object)null) { continue; } BagState state = BagPatches.GetState(val); if (state?.BaggedObjects == null) { continue; } lock (state.BagLock) { for (int j = 0; j < state.BaggedObjects.Count; j++) { GameObject val2 = state.BaggedObjects[j]; if ((Object)(object)val2 != (Object)null) { dictionary[((Object)val2).GetInstanceID()] = j; } } } } GameObject[] array3 = persistedObjects; foreach (GameObject val3 in array3) { if ((Object)(object)val3 == (Object)null) { continue; } TeleporterInteraction component = val3.GetComponent(); if ((Object)(object)component != (Object)null && PluginConfig.IsPersistenceBlacklisted("Teleporter")) { Log.Debug("[ProperSaveIntegration] Skipping teleporter object " + ((Object)val3).name + " (Teleporter is blacklisted)"); continue; } BaggedObjectSaveData baggedObjectSaveData = CaptureObjectData(val3, capturedInstanceIds); if (baggedObjectSaveData != null) { if (dictionary.TryGetValue(((Object)val3).GetInstanceID(), out var value)) { baggedObjectSaveData.BagSlotIndex = value; } drifterBagSaveData2.BaggedObjects.Add(baggedObjectSaveData); } } return drifterBagSaveData2; } private static BaggedObjectSaveData? CaptureObjectData(GameObject obj, HashSet? capturedInstanceIds = null) { //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return null; } if (PersistenceObjectManager.IsPlayerOrSurvivor(obj)) { Log.Debug("[ProperSaveIntegration.CaptureObjectData] Skipping " + ((Object)obj).name + ": Represents a player or survivor."); return null; } NetworkIdentity component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return null; } CharacterBody component2 = obj.GetComponent(); CharacterMaster val = (((Object)(object)component2 != (Object)null) ? component2.master : obj.GetComponent()); bool flag = (Object)(object)val != (Object)null; GameObject val2 = (GameObject)((flag && (Object)(object)val != (Object)null) ? ((object)((Component)val).gameObject) : ((object)obj)); if (capturedInstanceIds != null) { int instanceID = ((Object)val2).GetInstanceID(); if (capturedInstanceIds.Contains(instanceID)) { Log.Debug("[CaptureObjectData] Skipping duplicate capture for " + ((Object)val2).name + " (from source " + ((Object)obj).name + ")"); return null; } capturedInstanceIds.Add(instanceID); } if (PluginConfig.Instance.EnableDebugLogs.Value) { if (flag && (Object)(object)val != (Object)null) { Log.Debug("[CaptureObjectData] Capturing master " + ((Object)val).name + " for object " + ((Object)obj).name); } else { Log.Debug("[CaptureObjectData] Capturing body/object " + ((Object)obj).name); } } string text = ((val != null) ? ((Object)val).name : null); bool? isMainSeatObject = null; int? additionalSeatIndex = null; CheckObjectInSeats(obj, out isMainSeatObject, out additionalSeatIndex); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[CaptureObjectData] Capturing data for " + ((Object)obj).name); Component[] components = obj.GetComponents(); Log.Debug(string.Format("[CaptureObjectData] Components on object ({0} total): {1}", components.Length, string.Join(", ", from c in components.Take(10) select ((object)c).GetType().Name))); CharacterMaster component3 = obj.GetComponent(); if ((Object)(object)component3 != (Object)null) { Log.Debug("[CaptureObjectData] Object HAS CharacterMaster component: " + ((Object)component3).name); } else { Log.Debug("[CaptureObjectData] Object does not have CharacterMaster component"); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.master != (Object)null) { Log.Debug("[CaptureObjectData] CharacterBody's master is: " + ((Object)component2.master).name + " (saved as: " + text + ")"); } } } string prefabName = Regex.Replace(((Object)val2).name, "\\(Clone\\)(\\(\\d+\\))?$", ""); NetworkIdentity val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = component; } BaggedObjectSaveData obj2 = new BaggedObjectSaveData { ObjectName = ((Object)obj).name, SaveType = (flag ? "CharacterMaster" : "Body"), PrefabName = prefabName, ObjectInstanceId = ((Object)val2).GetInstanceID() }; Scene activeScene = SceneManager.GetActiveScene(); obj2.SceneName = ((Scene)(ref activeScene)).name; obj2.OwnerPlayerId = PersistenceObjectManager.GetPersistedObjectOwnerPlayerId(obj) ?? string.Empty; obj2.Position = SerializationHelpers.SerializeVector3(obj.transform.position); obj2.Rotation = SerializationHelpers.SerializeQuaternion(obj.transform.rotation); NetworkHash128 assetId = val3.assetId; obj2.AssetId = SerializationHelpers.SerializeGuid(new Guid(((object)(NetworkHash128)(ref assetId)).ToString())); assetId = val3.assetId; obj2.PrefabHash = ((object)(NetworkHash128)(ref assetId)).ToString(); obj2.ComponentType = GetPrimaryComponentType(val2); obj2.MasterName = text; obj2.IsMainSeatObject = isMainSeatObject; obj2.AdditionalSeatIndex = additionalSeatIndex; BaggedObjectSaveData baggedObjectSaveData = obj2; baggedObjectSaveData.SpawnCardPath = GetSpawnCardPath(val2); foreach (IObjectSerializerPlugin serializerPlugin in _serializerPlugins) { if (!serializerPlugin.CanHandle(val2)) { continue; } Dictionary dictionary = serializerPlugin.CaptureState(val2); if (dictionary == null) { continue; } Log.Debug($"[ProperSaveIntegration] Plugin '{serializerPlugin.PluginName}' handled {((Object)obj).name}, captured {dictionary.Count} values"); ComponentStateEntry componentStateEntry = new ComponentStateEntry { PluginName = serializerPlugin.PluginName }; foreach (KeyValuePair item in dictionary) { object value = item.Value; string type = value?.GetType().FullName ?? "System.String"; string value2 = SerializationHelpers.SerializeValue(value); componentStateEntry.Values.Add(new StateValue { Key = item.Key, Type = type, Value = value2 }); if (item.Key == "ObjectType" && string.IsNullOrEmpty(baggedObjectSaveData.ObjectType)) { baggedObjectSaveData.ObjectType = value?.ToString() ?? string.Empty; } } baggedObjectSaveData.ComponentStates.Add(componentStateEntry); } if (baggedObjectSaveData.ComponentStates.Count > 0) { Log.Debug($"[ProperSaveIntegration] Total serializers handling {((Object)obj).name}: {baggedObjectSaveData.ComponentStates.Count}"); } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[ProperSaveIntegration] No serializers handled " + ((Object)obj).name + "!"); } return baggedObjectSaveData; } private static void CheckObjectInSeats(GameObject obj, out bool? isMainSeatObject, out int? additionalSeatIndex) { isMainSeatObject = null; additionalSeatIndex = null; DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { if ((Object)(object)val == (Object)null) { continue; } BagState state = BagPatches.GetState(val); if (state == null) { continue; } if ((Object)(object)state.MainSeatObject != (Object)null && ((Object)state.MainSeatObject).GetInstanceID() == ((Object)obj).GetInstanceID()) { isMainSeatObject = true; break; } int num = 0; foreach (KeyValuePair additionalSeat in state.AdditionalSeats) { if ((Object)(object)additionalSeat.Key != (Object)null && ((Object)additionalSeat.Key).GetInstanceID() == ((Object)obj).GetInstanceID()) { additionalSeatIndex = num; return; } num++; } } } private static string GetPrimaryComponentType(GameObject obj) { MonoBehaviour[] components = obj.GetComponents(); foreach (MonoBehaviour val in components) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); string? @namespace = type.Namespace; if (@namespace == null || !@namespace.StartsWith("UnityEngine")) { string? namespace2 = type.Namespace; if (namespace2 == null || !namespace2.StartsWith("System")) { return type.AssemblyQualifiedName; } } } return string.Empty; } [IteratorStateMachine(typeof(d__21))] private static IEnumerator DelayedStateRestoration(GameObject obj, BaggedObjectSaveData objData, Action onComplete) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__21(0) { obj = obj, objData = objData, onComplete = onComplete }; } private static void EnsureSOAFromSaveData(GameObject obj, BaggedObjectSaveData objData) { if (!((Object)(object)obj == (Object)null) && objData != null && objData.ComponentStates != null && objData.ComponentStates.Any((ComponentStateEntry entry) => entry.PluginName.Contains("SpecialObjectAttributes", StringComparison.OrdinalIgnoreCase)) && !((Object)(object)obj.GetComponent() != (Object)null)) { GrabbableObjectPatches.AddSpecialObjectAttributesToGrabbableObject(obj); } } private static void RestoreBagState(DrifterBagSaveData saveData) { if (saveData == null || saveData.BaggedObjects == null) { Log.Error("[ProperSave] Invalid save data"); return; } List<(GameObject, BaggedObjectSaveData)> list = new List<(GameObject, BaggedObjectSaveData)>(); HashSet spawnedMasters = new HashSet(); List list2 = saveData.BaggedObjects.OrderBy((BaggedObjectSaveData o) => (o.BagSlotIndex < 0) ? int.MaxValue : o.BagSlotIndex).ToList(); foreach (BaggedObjectSaveData item in list2) { try { if (item != null) { GameObject val = ObjectSpawner.SpawnObjectFromSaveData(item, item.OwnerPlayerId, spawnedMasters); if ((Object)(object)val != (Object)null) { list.Add((val, item)); } else { Log.Warning("[ProperSave] Failed to spawn object: " + item.PrefabName); } } } catch (Exception ex) { Log.Error("[ProperSave] Exception spawning " + item?.PrefabName + ": " + ex.Message); } } Log.Debug($"[ProperSave] Spawning complete, restoring {list.Count} objects..."); ((MonoBehaviour)Run.instance).StartCoroutine(RestoreAllObjects(list)); } [IteratorStateMachine(typeof(d__24))] private static IEnumerator RestoreAllObjects(List<(GameObject obj, BaggedObjectSaveData data)> objectsToRestore) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__24(0) { objectsToRestore = objectsToRestore }; } private static void RestoreObjectState(GameObject obj, BaggedObjectSaveData objData) { if ((Object)(object)obj == (Object)null) { Log.Error("[ProperSave] RestoreObjectState: obj is null"); return; } if (objData == null) { Log.Error("[ProperSave] RestoreObjectState: objData is null"); return; } if (objData.ComponentStates == null) { Log.Warning("[ProperSave] RestoreObjectState: ComponentStates is null for " + objData.ObjectName); return; } EnsureSOAFromSaveData(obj, objData); foreach (ComponentStateEntry entry in objData.ComponentStates) { try { IObjectSerializerPlugin objectSerializerPlugin = _serializerPlugins.FirstOrDefault((IObjectSerializerPlugin p) => p.PluginName == entry.PluginName); if (objectSerializerPlugin == null) { continue; } GameObject val = obj; if (!objectSerializerPlugin.CanHandle(val)) { CharacterBody component = val.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.master != (Object)null && objectSerializerPlugin.CanHandle(((Component)component.master).gameObject)) { val = ((Component)component.master).gameObject; Log.Debug("[ProperSave] Cross-resolved CharacterBody to CharacterMaster " + ((Object)component.master).name + " for plugin '" + entry.PluginName + "'"); } else { CharacterMaster component2 = val.GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.GetBody() != (Object)null && objectSerializerPlugin.CanHandle(((Component)component2.GetBody()).gameObject)) { val = ((Component)component2.GetBody()).gameObject; Log.Debug("[ProperSave] Cross-resolved CharacterMaster to CharacterBody " + ((Object)component2.GetBody()).name + " for plugin '" + entry.PluginName + "'"); } } } if (!objectSerializerPlugin.CanHandle(val)) { continue; } Dictionary dictionary = new Dictionary(); foreach (StateValue value in entry.Values) { object obj2 = SerializationHelpers.DeserializeValue(value.Value, value.Type); if (obj2 != null) { dictionary[value.Key] = obj2; } } objectSerializerPlugin.RestoreState(val, dictionary); Log.Debug($"[ProperSave] Plugin '{entry.PluginName}' handled {((Object)val).name}, restored {dictionary.Count} values"); } catch (Exception ex) { Log.Error("[ProperSave] Failed to restore state for plugin '" + entry.PluginName + "' on " + ((Object)obj).name + ": " + ex.Message); } } } private static bool IsProperSaveAvailable() { return Chainloader.PluginInfos.ContainsKey("com.KingEnderBrine.ProperSave"); } private static string GetSpawnCardPath(GameObject obj) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) NetworkIdentity component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return string.Empty; } SpawnCard val = null; NetworkHash128 assetId = component.assetId; if (!((NetworkHash128)(ref assetId)).Equals(default(NetworkHash128))) { assetId = component.assetId; Guid assetId2 = new Guid(((object)(NetworkHash128)(ref assetId)).ToString()); val = SpawnCardRegistry.FindSpawnCardByAssetIdExact(assetId2); } if ((Object)(object)val == (Object)null) { val = SpawnCardRegistry.FindSpawnCardByPrefabHashExact(component.assetId); } if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(((Object)obj).name)) { val = SpawnCardRegistry.FindSpawnCardByExactName(((Object)obj).name); } if ((Object)(object)val != (Object)null) { return ((Object)val).name; } return string.Empty; } } } namespace DrifterBossGrabMod.ProperSave.Spawning { public static class ObjectSpawner { public static void Initialize() { SpawnCardRegistry.Initialize(); } public static GameObject? SpawnObjectFromSaveData(BaggedObjectSaveData objData, string? ownerPlayerId = null, HashSet? spawnedMasters = null) { //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Expected O, but got Unknown //IL_0488: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Expected O, but got Unknown //IL_04c8: Unknown result type (might be due to invalid IL or missing references) //IL_04d9: Unknown result type (might be due to invalid IL or missing references) //IL_04fb: Unknown result type (might be due to invalid IL or missing references) //IL_0506: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Expected O, but got Unknown //IL_0594: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_02cd: Unknown result type (might be due to invalid IL or missing references) //IL_02d9: Unknown result type (might be due to invalid IL or missing references) //IL_02b3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)DirectorCore.instance == (Object)null) { Log.Error("[ObjectSpawn] DirectorCore instance not available"); return null; } if (objData.SaveType == "CharacterMaster" || IsCharacterMaster(objData.PrefabName)) { Log.Debug("[ObjectSpawn] Detected CharacterMaster " + objData.PrefabName + " (SaveType: " + objData.SaveType + "), spawning master..."); string prefabName = objData.PrefabName; SpawnCard val = SpawnCardRegistry.FindSpawnCardByExactName(prefabName); if ((Object)(object)val != (Object)null && (Object)(object)val.prefab != (Object)null) { DirectorPlacementRule val2 = CreatePlacementRuleForRestoration(objData, ownerPlayerId); DirectorSpawnRequest val3 = new DirectorSpawnRequest(val, val2, RoR2Application.rng); GameObject val4 = DirectorCore.instance.TrySpawnObject(val3); if ((Object)(object)val4 != (Object)null) { spawnedMasters?.Add(objData.ObjectInstanceId); Log.Debug("[ObjectSpawn] Successfully spawned master " + ((Object)val4).name + " via DirectorCore"); return val4; } } spawnedMasters?.Add(objData.ObjectInstanceId); return PrefabSpawner.SpawnObjectFromPrefab(objData, ownerPlayerId); } if (IsEnemyBody(objData.PrefabName)) { string text = objData.MasterName ?? objData.PrefabName.Replace("Body", "Master"); Log.Debug("[ObjectSpawn] Enemy body detected, spawning via CharacterMaster '" + text + "'"); if (spawnedMasters != null && spawnedMasters.Contains(objData.ObjectInstanceId)) { Log.Debug($"[ObjectSpawn] Skipping duplicate spawn for {objData.PrefabName} - instance ID {objData.ObjectInstanceId} already spawned"); return null; } SpawnCard val5 = SpawnCardRegistry.FindSpawnCardByExactName(text); if ((Object)(object)val5 != (Object)null) { if ((Object)(object)val5.prefab == (Object)null) { Log.Error("[ObjectSpawn] Spawn card '" + ((Object)val5).name + "' has no prefab!"); spawnedMasters?.Add(objData.ObjectInstanceId); return null; } DirectorPlacementRule val6 = CreatePlacementRuleForRestoration(objData, ownerPlayerId); DirectorSpawnRequest val7 = new DirectorSpawnRequest(val5, val6, RoR2Application.rng); GameObject val8 = DirectorCore.instance.TrySpawnObject(val7); if ((Object)(object)val8 != (Object)null) { spawnedMasters?.Add(objData.ObjectInstanceId); CharacterMaster component = val8.GetComponent(); if ((Object)(object)component != (Object)null) { component.teamIndex = GetSavedTeamIndex(objData).GetValueOrDefault((TeamIndex)2); Log.Debug($"[ObjectSpawn] Assigned team {component.teamIndex} to {((Object)val8).name}"); } if ((Object)(object)val8.transform.parent != (Object)null && ((Object)val8.transform.parent).name == "DBG_PersistenceContainer") { val8.transform.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(val8, SceneManager.GetActiveScene()); } CharacterBody val9 = ((component != null) ? component.SpawnBody(val8.transform.position, val8.transform.rotation) : null); if ((Object)(object)val9 != (Object)null) { Log.Debug("[ObjectSpawn] Successfully spawned body " + ((Object)val9).name + " via master " + text); return ((Component)val9).gameObject; } } else { spawnedMasters?.Add(objData.ObjectInstanceId); Log.Warning("[ObjectSpawn] Failed to spawn via DirectorCore, falling back to PrefabSpawner"); } } BaggedObjectSaveData objData2 = new BaggedObjectSaveData { PrefabName = text, AssetId = objData.AssetId, PrefabHash = objData.PrefabHash, OwnerPlayerId = objData.OwnerPlayerId, ComponentStates = objData.ComponentStates }; spawnedMasters?.Add(objData.ObjectInstanceId); return PrefabSpawner.SpawnObjectFromPrefab(objData2, ownerPlayerId); } SpawnCard val10 = FindSpawnCardExact(objData); if ((Object)(object)val10 == (Object)null) { if (IsEnemyBody(objData.PrefabName)) { string text2 = objData.MasterName ?? objData.PrefabName.Replace("Body", "Master"); Log.Debug("[ObjectSpawn] Trying to find master spawn card '" + text2 + "' for enemy body '" + objData.PrefabName + "'"); SpawnCard val11 = SpawnCardRegistry.FindSpawnCardByExactName(text2); if ((Object)(object)val11 != (Object)null) { val10 = val11; Log.Debug("[ObjectSpawn] Found master spawn card for " + text2); } } if ((Object)(object)val10 == (Object)null) { Log.Warning("[ObjectSpawn] Could not find SpawnCard for " + objData.PrefabName + ", trying PrefabSpawner fallback"); return PrefabSpawner.SpawnObjectFromPrefab(objData, ownerPlayerId); } } if ((Object)(object)val10.prefab == (Object)null) { Log.Error("[ObjectSpawn] Spawn card '" + ((Object)val10).name + "' has no prefab!"); return null; } DirectorPlacementRule val12 = CreatePlacementRuleForRestoration(objData, ownerPlayerId); DirectorSpawnRequest val13 = new DirectorSpawnRequest(val10, val12, RoR2Application.rng); GameObject val14 = DirectorCore.instance.TrySpawnObject(val13); if ((Object)(object)val14 != (Object)null) { CharacterMaster component2 = val14.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.teamIndex = GetSavedTeamIndex(objData).GetValueOrDefault((TeamIndex)2); Log.Debug($"[ObjectSpawn] Assigned team {component2.teamIndex} to {((Object)val14).name}"); CharacterBody val15 = component2.SpawnBody(val14.transform.position, val14.transform.rotation); if ((Object)(object)val15 != (Object)null && objData.PrefabName.EndsWith("Body")) { Log.Debug("[ObjectSpawn] Using spawned body " + ((Object)val15).name + " instead of master " + ((Object)val14).name); val14 = ((Component)val15).gameObject; } } if ((Object)(object)val14.transform.parent != (Object)null && ((Object)val14.transform.parent).name == "DBG_PersistenceContainer") { val14.transform.SetParent((Transform)null, true); SceneManager.MoveGameObjectToScene(val14, SceneManager.GetActiveScene()); } if (PluginConfig.Instance.EnableDebugLogs.Value) { Component[] components = val14.GetComponents(); Log.Debug($"[ObjectSpawn] Spawned object has {components.Length} components:"); foreach (Component item in components.Take(15)) { Log.Debug(" - " + ((object)item).GetType().Name); } SpecialObjectAttributes component3 = val14.GetComponent(); HalcyoniteShrineInteractable component4 = val14.GetComponent(); CharacterBody component5 = val14.GetComponent(); if ((Object)(object)component3 == (Object)null) { Log.Warning(" - SpecialObjectAttributes: not FOUND"); } else { Log.Debug($" - SpecialObjectAttributes: FOUND (durability={component3.durability}, locked={component3.locked})"); } if ((Object)(object)component4 == (Object)null) { Log.Warning(" - HalcyoniteShrineInteractable: not FOUND"); } else { Log.Debug($" - HalcyoniteShrineInteractable: FOUND (interactions={component4.interactions})"); } if ((Object)(object)component5 == (Object)null) { Log.Warning(" - CharacterBody: not FOUND"); } else { Log.Debug(" - CharacterBody: FOUND"); } } Log.Debug("[ObjectSpawn] Successfully spawned " + ((Object)val14).name); return val14; } Log.Warning("[ObjectSpawn] Failed to spawn " + objData.PrefabName + ", trying PrefabSpawner fallback"); return PrefabSpawner.SpawnObjectFromPrefab(objData, ownerPlayerId); } private static DirectorPlacementRule CreatePlacementRuleForRestoration(BaggedObjectSaveData objData, string? ownerPlayerId) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Expected O, but got Unknown //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown CharacterBody val = FindOwnerBody(ownerPlayerId); if ((Object)(object)val != (Object)null) { Vector3 position = val.transform.position; Vector3 forward = val.transform.forward; Vector3 position2 = position + forward * 0.5f + Vector3.up * 0.5f; return new DirectorPlacementRule { placementMode = (PlacementMode)0, position = position2, spawnOnTarget = null }; } Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 position3 = ((Component)main).transform.position; Vector3 forward2 = ((Component)main).transform.forward; Vector3 position4 = position3 + forward2 * 2f; return new DirectorPlacementRule { placementMode = (PlacementMode)0, position = position4, spawnOnTarget = null }; } return new DirectorPlacementRule { placementMode = (PlacementMode)0, position = new Vector3(0f, 1f, 0f), spawnOnTarget = null }; } private static CharacterBody? FindOwnerBody(string? ownerId) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(ownerId)) { NetworkUser val = ((IEnumerable)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func)((NetworkUser nu) => ((NetworkBehaviour)nu).isServer)); if ((Object)(object)val != (Object)null && (Object)(object)val.master != (Object)null) { return val.master.GetBody(); } return null; } NetworkUser val2 = null; foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { NetworkUserId id = readOnlyInstances.id; string text = ((id.strValue != null) ? id.strValue : $"{id.value}_{id.subId}"); if (text == ownerId) { val2 = readOnlyInstances; break; } } if ((Object)(object)val2 != (Object)null) { CharacterMaster master = val2.master; if (master == null) { return null; } return master.GetBody(); } return null; } private static TeamIndex? GetSavedTeamIndex(BaggedObjectSaveData objData) { if (objData == null || objData.ComponentStates == null) { return null; } foreach (ComponentStateEntry componentState in objData.ComponentStates) { foreach (StateValue value in componentState.Values) { if (value.Key == "teamIndex" && value.Type == "System.Byte" && byte.TryParse(value.Value, out var result)) { return (TeamIndex)(sbyte)result; } } } return null; } private static bool IsCharacterMaster(string prefabName) { if (string.IsNullOrEmpty(prefabName)) { return false; } if (!prefabName.EndsWith("Master")) { return prefabName.Contains("Master(Clone)"); } return true; } private static bool IsEnemyBody(string prefabName) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0013: Invalid comparison between Unknown and I4 //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Invalid comparison between Unknown and I4 if (string.IsNullOrEmpty(prefabName)) { return false; } BodyIndex val = BodyCatalog.FindBodyIndex(prefabName); if ((int)val == -1) { return false; } SurvivorIndex survivorIndexFromBodyIndex = SurvivorCatalog.GetSurvivorIndexFromBodyIndex(val); return (int)survivorIndexFromBodyIndex == -1; } private static SpawnCard? FindSpawnCardExact(BaggedObjectSaveData objData) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) Guid? guid = SerializationHelpers.ParseGuid(objData.AssetId); NetworkHash128 prefabHash = SerializationHelpers.ParsePrefabHash(objData.PrefabHash); if (guid.HasValue && guid.Value != Guid.Empty) { SpawnCard val = SpawnCardRegistry.FindSpawnCardByAssetIdExact(guid.Value); if ((Object)(object)val != (Object)null) { return val; } } if (!((NetworkHash128)(ref prefabHash)).Equals(default(NetworkHash128))) { SpawnCard val2 = SpawnCardRegistry.FindSpawnCardByPrefabHashExact(prefabHash); if ((Object)(object)val2 != (Object)null) { return val2; } } if (!string.IsNullOrEmpty(objData.PrefabName)) { SpawnCard val3 = SpawnCardRegistry.FindSpawnCardByExactName(objData.PrefabName); if ((Object)(object)val3 != (Object)null) { return val3; } } return null; } } public static class PrefabSpawner { public static GameObject? SpawnObjectFromPrefab(BaggedObjectSaveData objData, string? ownerPlayerId = null) { //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_0305: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0329: Unknown result type (might be due to invalid IL or missing references) if (objData == null) { return null; } Guid? assetId = SerializationHelpers.ParseGuid(objData.AssetId); if (!assetId.HasValue || assetId == Guid.Empty) { Log.Warning("[PrefabSpawner] No AssetId provided, cannot spawn from prefab"); return null; } GameObject val = null; if ((Object)(object)NetworkManager.singleton != (Object)null && NetworkManager.singleton.spawnPrefabs != null) { val = ((IEnumerable)NetworkManager.singleton.spawnPrefabs).FirstOrDefault((Func)delegate(GameObject p) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)p == (Object)null) { return false; } NetworkIdentity component3 = p.GetComponent(); if ((Object)(object)component3 == (Object)null) { return false; } NetworkHash128 assetId3 = component3.assetId; Guid guid2 = new Guid(((object)(NetworkHash128)(ref assetId3)).ToString()); return guid2 == assetId.Value; }); } if ((Object)(object)val == (Object)null && !string.IsNullOrEmpty(objData.PrefabName)) { val = ((IEnumerable)Resources.FindObjectsOfTypeAll()).FirstOrDefault((Func)delegate(GameObject g) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)g == (Object)null) { return false; } if (!Util.IsPrefab(g)) { return false; } NetworkIdentity component2 = g.GetComponent(); if ((Object)(object)component2 == (Object)null) { return false; } NetworkHash128 assetId2 = component2.assetId; Guid guid = new Guid(((object)(NetworkHash128)(ref assetId2)).ToString()); return guid == assetId.Value; }); if ((Object)(object)val != (Object)null) { Log.Debug("[PrefabSpawner] Found prefab by AssetId in Resources: " + ((Object)val).name); } } if ((Object)(object)val == (Object)null) { Log.Warning($"[PrefabSpawner] Could not find prefab with AssetId {assetId}"); return null; } GameObject val2; try { val2 = Object.Instantiate(val); if ((Object)(object)val2 == (Object)null) { Log.Error("[PrefabSpawner] Object.Instantiate returned null"); return null; } } catch (Exception ex) { Log.Error("[PrefabSpawner] Failed to instantiate prefab: " + ex.Message); return null; } PositionObjectNearPlayer(val2, ownerPlayerId); val2.transform.rotation = Quaternion.identity; CharacterMaster component = val2.GetComponent(); CharacterBody val3 = null; if ((Object)(object)component != (Object)null) { Log.Debug("[PrefabSpawner] Found CharacterMaster " + ((Object)val2).name); component.teamIndex = GetSavedTeamIndex(objData).GetValueOrDefault((TeamIndex)2); Log.Debug($"[PrefabSpawner] Assigned team {component.teamIndex} to {((Object)val2).name}"); GameObject val4 = BodyCatalog.FindBodyPrefab(objData.PrefabName); if ((Object)(object)val4 != (Object)null) { component.bodyPrefab = val4; } } Log.Debug("[PrefabSpawner] Spawning master on network..."); if (NetworkServer.active) { NetworkServer.Spawn(val2); } else { Log.Warning("[PrefabSpawner] NetworkServer is not active, skipping NetworkServer.Spawn"); } if ((Object)(object)component != (Object)null) { Log.Debug("[PrefabSpawner] Spawning body from master..."); val3 = component.SpawnBody(val2.transform.position, val2.transform.rotation); if ((Object)(object)val3 != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[PrefabSpawner] Spawned body " + ((Object)val3).name + " from master " + ((Object)val2).name); string name = ((Object)val3).name; CharacterMaster master = val3.master; Log.Debug("[PrefabSpawner] Body " + name + " master: " + (((master != null) ? ((Object)master).name : null) ?? "null")); string name2 = ((Object)val2).name; CharacterBody body = component.GetBody(); Log.Debug("[PrefabSpawner] Master " + name2 + " body: " + (((body != null) ? ((Object)body).name : null) ?? "null")); } val2 = ((Component)val3).gameObject; } else { Log.Error("[PrefabSpawner] Failed to spawn body from master " + ((Object)val2).name); } } Scene val5 = val2.scene; string name3 = ((Scene)(ref val5)).name; val5 = SceneManager.GetActiveScene(); if (name3 != ((Scene)(ref val5)).name) { SceneManager.MoveGameObjectToScene(val2, SceneManager.GetActiveScene()); } Log.Debug("[PrefabSpawner] Successfully spawned prefab: " + ((Object)val2).name); return val2; } private static TeamIndex? GetSavedTeamIndex(BaggedObjectSaveData objData) { if (objData == null || objData.ComponentStates == null) { return null; } foreach (ComponentStateEntry componentState in objData.ComponentStates) { foreach (StateValue value in componentState.Values) { if (value.Key == "teamIndex" && value.Type == "System.Byte" && byte.TryParse(value.Value, out var result)) { return (TeamIndex)(sbyte)result; } } } return null; } private static void PositionObjectNearPlayer(GameObject obj, string? ownerPlayerId) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) CharacterBody val = FindOwnerBody(ownerPlayerId); if ((Object)(object)val != (Object)null) { Vector3 position = val.transform.position; Vector3 forward = val.transform.forward; Vector3 position2 = position + forward * 0.5f + Vector3.up * 0.5f; obj.transform.position = position2; return; } Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 position3 = ((Component)main).transform.position; Vector3 forward2 = ((Component)main).transform.forward; Vector3 position4 = position3 + forward2 * 2f; obj.transform.position = position4; } else { obj.transform.position = new Vector3(0f, 1f, 0f); } } private static CharacterBody? FindOwnerBody(string? ownerId) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(ownerId)) { NetworkUser val = ((IEnumerable)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func)((NetworkUser nu) => ((NetworkBehaviour)nu).isServer)); if ((Object)(object)val != (Object)null && (Object)(object)val.master != (Object)null) { return val.master.GetBody(); } return null; } NetworkUser val2 = null; foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { NetworkUserId id = readOnlyInstances.id; string text = ((id.strValue != null) ? id.strValue : $"{id.value}_{id.subId}"); if (text == ownerId) { val2 = readOnlyInstances; break; } } if ((Object)(object)val2 != (Object)null) { CharacterMaster master = val2.master; if (master == null) { return null; } return master.GetBody(); } return null; } } public static class SpawnCardRegistry { private static readonly Dictionary _spawnCardByAssetId = new Dictionary(); private static readonly Dictionary _spawnCardByPrefabHash = new Dictionary(); private static readonly Dictionary _spawnCardByExactName = new Dictionary(); private static bool _initialized = false; public static void Initialize() { if (!_initialized) { Run.onRunStartGlobal += OnRunStart; OnRunStart(null); _initialized = true; Log.Debug("[SpawnCardRegistry] Initialized"); } } private static void OnRunStart(Run run) { RebuildRegistry(); } public static void RebuildRegistry() { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) _spawnCardByAssetId.Clear(); _spawnCardByPrefabHash.Clear(); _spawnCardByExactName.Clear(); SpawnCard[] allSpawnCards = GetAllSpawnCards(); SpawnCard[] array = allSpawnCards; foreach (SpawnCard val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.prefab == (Object)null)) { _spawnCardByExactName[((Object)val).name] = val; NetworkIdentity component = val.prefab.GetComponent(); if ((Object)(object)component != (Object)null) { NetworkHash128 assetId = component.assetId; Guid key = new Guid(((object)(NetworkHash128)(ref assetId)).ToString()); _spawnCardByAssetId[key] = val; _spawnCardByPrefabHash[component.assetId] = val; } } } Log.Debug($"[SpawnCardRegistry] Indexed {_spawnCardByAssetId.Count} spawn cards by AssetId"); } private static SpawnCard[] GetAllSpawnCards() { List list = new List(); try { SpawnCard[] array = Resources.FindObjectsOfTypeAll(); if (array != null && array.Length != 0) { list.AddRange(array); Log.Debug($"[SpawnCardRegistry] Found {array.Length} spawn cards via Resources.FindObjectsOfTypeAll"); } ClassicStageInfo instance = ClassicStageInfo.instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.monsterDccsPool != (Object)null) { IEnumerable collection = from x in (from x in (from x in instance.monsterDccsPool.GenerateWeightedSelection().choices where (Object)(object)x.value != (Object)null select x.value into x where x.categories != null select x).SelectMany((DirectorCardCategorySelection x) => x.categories) where x.cards != null select x).SelectMany((Category x) => x.cards) select x.spawnCard into x where (Object)(object)x != (Object)null select x; list.AddRange(collection); } if ((Object)(object)instance.interactableDccsPool != (Object)null) { IEnumerable collection2 = from x in (from x in (from x in instance.interactableDccsPool.GenerateWeightedSelection().choices where (Object)(object)x.value != (Object)null select x.value into x where x.categories != null select x).SelectMany((DirectorCardCategorySelection x) => x.categories) where x.cards != null select x).SelectMany((Category x) => x.cards) select x.spawnCard into x where (Object)(object)x != (Object)null select x; list.AddRange(collection2); } } SceneDirector val = Object.FindFirstObjectByType(); if ((Object)(object)val != (Object)null) { IEnumerable collection3 = from x in val.GenerateInteractableCardSelection().choices where x.value != null && (Object)(object)x.value.spawnCard != (Object)null select x.value.spawnCard into x where (Object)(object)x != (Object)null select x; list.AddRange(collection3); } } catch (Exception ex) { Log.Error("[SpawnCardRegistry] Failed to get spawn cards: " + ex.Message); } return list.Distinct().ToArray(); } public static SpawnCard? FindSpawnCardByAssetIdExact(Guid assetId) { if (!_spawnCardByAssetId.TryGetValue(assetId, out SpawnCard value)) { return null; } return value; } public static SpawnCard? FindSpawnCardByPrefabHashExact(NetworkHash128 prefabHash) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) if (!_spawnCardByPrefabHash.TryGetValue(prefabHash, out SpawnCard value)) { return null; } return value; } public static SpawnCard? FindSpawnCardByExactName(string name) { if (string.IsNullOrEmpty(name)) { return null; } if (_spawnCardByExactName.TryGetValue(name, out SpawnCard value)) { return value; } string text = Regex.Replace(name, "\\(Clone\\)(\\(\\d+\\))?$", ""); if (!string.IsNullOrEmpty(text) && _spawnCardByExactName.TryGetValue(text, out value)) { return value; } return null; } public static void Cleanup() { Run.onRunStartGlobal -= OnRunStart; _spawnCardByAssetId.Clear(); _spawnCardByPrefabHash.Clear(); _spawnCardByExactName.Clear(); _initialized = false; } } } namespace DrifterBossGrabMod.ProperSave.Serializers { public interface IObjectSerializerPlugin { int Priority { get; } string PluginName { get; } bool CanHandle(GameObject obj); Dictionary? CaptureState(GameObject obj); bool RestoreState(GameObject obj, Dictionary state); } } namespace DrifterBossGrabMod.ProperSave.Serializers.Plugins { public class GenericComponentSerializerPlugin : IObjectSerializerPlugin { private static readonly Type[] _skippedTypes = new Type[11] { typeof(Transform), typeof(Rigidbody), typeof(Renderer), typeof(MeshRenderer), typeof(SkinnedMeshRenderer), typeof(ParticleSystem), typeof(Light), typeof(Camera), typeof(AudioSource), typeof(Animation), typeof(Animator) }; public int Priority => 0; public string PluginName => "GenericComponentSerializerPlugin"; public bool CanHandle(GameObject obj) { return (Object)(object)obj != (Object)null; } public Dictionary? CaptureState(GameObject obj) { Dictionary dictionary = new Dictionary(); Component[] components = obj.GetComponents(); foreach (Component val in components) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); if (!_skippedTypes.Contains(type)) { Dictionary dictionary2 = new Dictionary(); dictionary[type.Name] = dictionary2; NetworkBehaviour val2 = (NetworkBehaviour)(object)((val is NetworkBehaviour) ? val : null); if (val2 != null) { CaptureNetworkBehaviourFields(val2, dictionary2); } CaptureSerializableFields(val, dictionary2); } } return dictionary; } private void CaptureNetworkBehaviourFields(NetworkBehaviour networkBehaviour, Dictionary state) { PropertyInfo[] properties = ((object)networkBehaviour).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { if (!propertyInfo.Name.StartsWith("Network") || !propertyInfo.CanRead) { continue; } try { object value = propertyInfo.GetValue(networkBehaviour); if (value != null && IsTypeSerializable(propertyInfo.PropertyType)) { state[propertyInfo.Name] = value; } } catch (Exception ex) { Log.Warning("[GenericComponentSerializer] Failed to serialize field on " + ((object)networkBehaviour)?.GetType().Name + ": " + ex.Message); } } } public bool RestoreState(GameObject obj, Dictionary state) { foreach (KeyValuePair item in state) { string componentName = item.Key; if (!(item.Value is Dictionary state2)) { continue; } Component val = ((IEnumerable)obj.GetComponents()).FirstOrDefault((Func)((Component c) => (Object)(object)c != (Object)null && ((object)c).GetType().Name == componentName)); if (!((Object)(object)val == (Object)null)) { NetworkBehaviour val2 = (NetworkBehaviour)(object)((val is NetworkBehaviour) ? val : null); if (val2 != null) { RestoreNetworkBehaviourFields(val2, state2); } RestoreSerializableFields(val, state2); } } return true; } private void RestoreNetworkBehaviourFields(NetworkBehaviour networkBehaviour, Dictionary state) { PropertyInfo[] properties = ((object)networkBehaviour).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); PropertyInfo[] array = properties; foreach (PropertyInfo propertyInfo in array) { if (propertyInfo.Name.StartsWith("Network") && propertyInfo.CanWrite && state.TryGetValue(propertyInfo.Name, out object value)) { try { object value2 = Convert.ChangeType(value, propertyInfo.PropertyType); propertyInfo.SetValue(networkBehaviour, value2); } catch (Exception ex) { Log.Warning("[GenericComponentSerializer] Failed to restore field on " + propertyInfo.Name + ": " + ex.Message); } } } } private void CaptureSerializableFields(Component component, Dictionary state) { FieldInfo[] fields = ((object)component).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); FieldInfo[] array = fields; foreach (FieldInfo fieldInfo in array) { if (fieldInfo.IsStatic || fieldInfo.IsLiteral || (!fieldInfo.IsPublic && !Attribute.IsDefined(fieldInfo, typeof(SerializeField))) || !IsTypeSerializable(fieldInfo.FieldType)) { continue; } try { object value = fieldInfo.GetValue(component); if (value != null) { state[fieldInfo.Name] = ConvertFieldValueToString(value, fieldInfo.FieldType); } } catch (Exception ex) { Log.Warning("[GenericComponentSerializer] Failed to serialize field on " + ((object)component)?.GetType().Name + ": " + ex.Message); } } } private bool IsTypeSerializable(Type type) { if (type.IsPrimitive || type == typeof(string)) { return true; } if (type == typeof(Vector3) || type == typeof(Quaternion)) { return true; } if (type.IsEnum) { return true; } if (!type.IsArray) { _ = type.IsGenericType; } return false; } private object ConvertFieldValueToString(object value, Type fieldType) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) if (value == null) { return string.Empty; } if (fieldType == typeof(Vector3)) { Vector3 val = (Vector3)value; return $"{val.x}|{val.y}|{val.z}"; } if (fieldType == typeof(Quaternion)) { Quaternion val2 = (Quaternion)value; return $"{val2.x}|{val2.y}|{val2.z}|{val2.w}"; } return value; } private void RestoreSerializableFields(Component component, Dictionary state) { Type type = ((object)component).GetType(); foreach (KeyValuePair item in state) { string key = item.Key; object value = item.Value; FieldInfo field = type.GetField(key, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field != null) || field.IsLiteral || field.IsStatic) { continue; } try { object obj = ConvertStringToFieldValue(value?.ToString(), field.FieldType); if (obj != null) { field.SetValue(component, obj); } } catch (Exception ex) { Log.Warning("[GenericComponentSerializer] Failed to set field value: " + ex.Message); } } } private object? ConvertStringToFieldValue(string? value, Type fieldType) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(value)) { return null; } if (fieldType == typeof(Vector3)) { string[] array = value.Split('|'); if (array.Length == 3) { float.TryParse(array[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var result); float.TryParse(array[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var result2); float.TryParse(array[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var result3); return (object)new Vector3(result, result2, result3); } return Vector3.zero; } if (fieldType == typeof(Quaternion)) { string[] array2 = value.Split('|'); if (array2.Length == 4) { float.TryParse(array2[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var result4); float.TryParse(array2[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var result5); float.TryParse(array2[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var result6); float.TryParse(array2[3], NumberStyles.Any, CultureInfo.InvariantCulture, out var result7); return (object)new Quaternion(result4, result5, result6, result7); } return Quaternion.identity; } try { return Convert.ChangeType(value, fieldType); } catch { return null; } } } public class QualityIntegration : APISerializerBase { private Assembly? _qualityAssembly; private Type? _qualityDuplicatorType; private Type? _qualityItemBodyType; private Type? _itemQualityGroupType; private Type? _qualityCatalogType; private Type? _qualityContentManagerType; public override int Priority => 60; public override string PluginName => "QualityIntegration"; private bool IsQualityModLoaded() { if (_qualityAssembly != null) { return true; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); _qualityAssembly = assemblies.FirstOrDefault((Assembly a) => a.GetName().Name == "ItemQualities"); return _qualityAssembly != null; } private void EnsureTypesLoaded() { if (IsQualityModLoaded() && !(_qualityAssembly == null)) { _qualityDuplicatorType = _qualityAssembly.GetType("ItemQualities.QualityDuplicatorBehavior"); _qualityItemBodyType = _qualityAssembly.GetType("ItemQualities.Items.QualityItemBodyBehavior"); _itemQualityGroupType = _qualityAssembly.GetType("ItemQualities.ItemQualityGroup"); _qualityCatalogType = _qualityAssembly.GetType("ItemQualities.QualityCatalog"); _qualityContentManagerType = _qualityAssembly.GetType("ItemQualities.ContentManagement.QualityContentManager"); } } protected override bool CanHandleObject(GameObject obj) { if (!IsQualityModLoaded()) { return false; } EnsureTypesLoaded(); if (_qualityDuplicatorType != null && (Object)(object)obj.GetComponent(_qualityDuplicatorType) != (Object)null) { return true; } return false; } protected override void CaptureObjectState(GameObject obj, Dictionary state) { EnsureTypesLoaded(); try { if (_qualityDuplicatorType != null) { Component component = obj.GetComponent(_qualityDuplicatorType); if ((Object)(object)component != (Object)null) { CaptureFieldValue(component, state, "_available", "Available"); } } } catch (Exception ex) { Log.Warning("[QualityIntegration] Failed to serialize quality data: " + ex.Message); } } protected override void RestoreObjectState(GameObject obj, Dictionary state) { EnsureTypesLoaded(); try { if (!(_qualityDuplicatorType != null)) { return; } Component component = obj.GetComponent(_qualityDuplicatorType); if ((Object)(object)component != (Object)null && state.TryGetValue("Available", out object value) && value is bool) { bool flag = (bool)value; MethodInfo method = _qualityDuplicatorType.GetMethod("SetAvailable", BindingFlags.Instance | BindingFlags.Public); if (method != null) { method.Invoke(component, new object[1] { flag }); } else { RestoreFieldValue(component, state, "Available", "_available"); } } } catch (Exception ex) { Log.Warning("[QualityIntegration] Failed to restore quality data: " + ex.Message); } } private void CaptureFieldValue(object obj, Dictionary dict, string fieldName, string stateKey) { try { FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(obj); dict[stateKey] = value; } } catch (Exception ex) { Log.Warning("[QualityIntegration] Failed to capture field " + fieldName + ": " + ex.Message); } } private void RestoreFieldValue(object obj, Dictionary dict, string stateKey, string fieldName) { try { if (dict.TryGetValue(stateKey, out object value) && value != null) { FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value2 = Convert.ChangeType(value, field.FieldType); field.SetValue(obj, value2); } } } catch (Exception ex) { Log.Warning("[QualityIntegration] Failed to restore field " + fieldName + ": " + ex.Message); } } } } namespace DrifterBossGrabMod.ProperSave.Data { [Serializable] public class DrifterBagSaveData { public List BaggedObjects { get; set; } = new List(); public string? MainSeatObjectInstanceId { get; set; } public string SaveSceneName { get; set; } = string.Empty; public int StageClearCount { get; set; } } [Serializable] public class BaggedObjectSaveData { public string ObjectName { get; set; } = string.Empty; public string SaveType { get; set; } = "Body"; public string ObjectType { get; set; } = string.Empty; public string SpawnCardPath { get; set; } = string.Empty; public int ObjectInstanceId { get; set; } public string NetworkId { get; set; } = string.Empty; public string OwnerPlayerId { get; set; } = string.Empty; public string SceneName { get; set; } = string.Empty; public string AssetId { get; set; } = string.Empty; public string PrefabName { get; set; } = string.Empty; public string PrefabHash { get; set; } = string.Empty; public string? MasterName { get; set; } public string ComponentType { get; set; } = string.Empty; public string Position { get; set; } = string.Empty; public string Rotation { get; set; } = string.Empty; public List ComponentStates { get; set; } = new List(); public int? AdditionalSeatIndex { get; set; } public bool? IsMainSeatObject { get; set; } public int BagSlotIndex { get; set; } = -1; } [Serializable] public class ComponentStateEntry { public string PluginName { get; set; } = string.Empty; public List Values { get; set; } = new List(); } [Serializable] public class StateValue { public string Key { get; set; } = string.Empty; public string Type { get; set; } = string.Empty; public string Value { get; set; } = string.Empty; } } namespace DrifterBossGrabMod.ProperSave.Core { public static class SerializationHelpers { public static string SerializeVector3(Vector3 v) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) return $"{v.x}|{v.y}|{v.z}"; } public static string SerializeQuaternion(Quaternion q) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) return $"{q.x}|{q.y}|{q.z}|{q.w}"; } public static string SerializeGuid(Guid? guid) { return guid?.ToString() ?? string.Empty; } public static string SerializeValue(object? value) { if (value == null) { return ""; } if (value is bool flag) { return flag.ToString(); } if (value is int num) { return num.ToString(); } if (value is uint num2) { return num2.ToString(); } if (value is float num3) { return num3.ToString(CultureInfo.InvariantCulture); } if (value is double num4) { return num4.ToString(CultureInfo.InvariantCulture); } if (value is string result) { return result; } if (value is List values) { return string.Join(",", values); } return value.ToString() ?? ""; } public static Vector3 ParseVector3(string s) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(s)) { return Vector3.zero; } string[] array = s.Split('|'); if (array.Length != 3) { return Vector3.zero; } float.TryParse(array[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var result); float.TryParse(array[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var result2); float.TryParse(array[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var result3); return new Vector3(result, result2, result3); } public static Quaternion ParseQuaternion(string s) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(s)) { return Quaternion.identity; } string[] array = s.Split('|'); if (array.Length != 4) { return Quaternion.identity; } float.TryParse(array[0], NumberStyles.Any, CultureInfo.InvariantCulture, out var result); float.TryParse(array[1], NumberStyles.Any, CultureInfo.InvariantCulture, out var result2); float.TryParse(array[2], NumberStyles.Any, CultureInfo.InvariantCulture, out var result3); float.TryParse(array[3], NumberStyles.Any, CultureInfo.InvariantCulture, out var result4); return new Quaternion(result, result2, result3, result4); } public static Guid? ParseGuid(string s) { if (string.IsNullOrEmpty(s)) { return null; } if (Guid.TryParse(s, out var result)) { return result; } return null; } public static NetworkHash128 ParsePrefabHash(string s) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrEmpty(s)) { return default(NetworkHash128); } try { return NetworkHash128.Parse(s); } catch { return default(NetworkHash128); } } public static object? DeserializeValue(string value, string typeStr) { if (string.IsNullOrEmpty(value)) { return null; } try { if (typeStr != null && typeStr.Contains("System.Collections.Generic.List`1[[System.Int32")) { List list = new List(); if (!string.IsNullOrEmpty(value)) { string[] array = value.Split(','); string[] array2 = array; foreach (string s in array2) { if (int.TryParse(s, out var result)) { list.Add(result); } } } return list; } if (typeStr != null) { switch (typeStr.Length) { default: goto end_IL_000b; case 4: { char c = typeStr[0]; if (c != 'b') { if (c == 'u' && typeStr == "uint") { goto IL_0234; } } else if (typeStr == "bool") { goto IL_0216; } goto end_IL_000b; } case 13: { char c = typeStr[8]; if ((uint)c <= 105u) { if (c != 'I') { if (c == 'i' && typeStr == "System.Single") { goto IL_0243; } } else if (typeStr == "System.UInt32") { goto IL_0234; } } else if (c != 'o') { if (c == 't' && typeStr == "System.String") { break; } } else if (typeStr == "System.Double") { goto IL_0257; } goto end_IL_000b; } case 6: { char c = typeStr[0]; if (c != 'd') { if (c == 's' && typeStr == "string") { break; } } else if (typeStr == "double") { goto IL_0257; } goto end_IL_000b; } case 14: if (typeStr == "System.Boolean") { goto IL_0216; } goto end_IL_000b; case 12: if (typeStr == "System.Int32") { goto IL_0225; } goto end_IL_000b; case 3: if (typeStr == "int") { goto IL_0225; } goto end_IL_000b; case 5: if (typeStr == "float") { goto IL_0243; } goto end_IL_000b; case 7: case 8: case 9: case 10: case 11: goto end_IL_000b; IL_0225: return int.Parse(value); IL_0257: return double.Parse(value, CultureInfo.InvariantCulture); IL_0234: return uint.Parse(value); IL_0243: return float.Parse(value, CultureInfo.InvariantCulture); IL_0216: return bool.Parse(value); } return value; } end_IL_000b:; } catch (Exception ex) { Log.Warning("[SerializationHelpers] Failed to convert value: " + ex.Message); } return value; } } } namespace DrifterBossGrabMod.Networking { public static class AuthorityGuard { public static bool CanModifyBag(DrifterBagController? controller) { if ((Object)(object)controller == (Object)null) { return false; } if (!NetworkServer.active) { return ((NetworkBehaviour)controller).hasAuthority; } return true; } public static bool ShouldAutoPromote(DrifterBagController? controller) { if ((Object)(object)controller == (Object)null) { return false; } BottomlessBagNetworkController component = ((Component)controller).GetComponent(); if ((Object)(object)component != (Object)null && NetworkServer.active && !((NetworkBehaviour)controller).hasAuthority) { return component.autoPromoteMainSeat; } if (PluginConfig.Instance.AutoPromoteMainSeat.Value) { if (!NetworkServer.active) { return ((NetworkBehaviour)controller).hasAuthority; } return true; } return false; } public static bool IsServerWithPassenger(DrifterBagController? controller, GameObject obj) { if (NetworkServer.active && (Object)(object)controller != (Object)null && (Object)(object)controller.vehicleSeat != (Object)null) { return (Object)(object)controller.vehicleSeat.NetworkpassengerBodyObject == (Object)(object)obj; } return false; } public static bool ShouldSendPersistence(DrifterBagController? controller) { if (NetworkServer.active) { return (Object)(object)controller != (Object)null; } return false; } } public static class BagStateSync { [CompilerGenerated] private sealed class d__10 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private float 5__2; private float 5__3; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__10(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = 5f; 5__3 = 0f; break; case 1: <>1__state = -1; 5__3 += 0.1f; break; } if (!NetworkServer.active && 5__3 < 5__2) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } if (NetworkServer.active) { Log.Debug($"[BagStateSync] NetworkServer.active became true after {5__3:F1}s, initializing server hooks"); PersistenceNetworkHandler.RegisterServerHooks(); } else { Log.Warning($"[BagStateSync] Timed out waiting for NetworkServer.active after {5__2}s"); } 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 Harmony? _harmony; public static GameObject? AdditionalSeatPrefab { get; private set; } public static void Init(Harmony harmony) { _harmony = harmony; NetworkManagerSystem.onClientConnectGlobal += OnClientConnect; NetworkManagerSystem.onStartServerGlobal += OnServerStart; Run.onRunStartGlobal += OnRunStart; ((ResourceAvailability)(ref BodyCatalog.availability)).CallWhenAvailable((Action)delegate { AddControllerToDrifterPrefab(); }); CreateSeatPrefab(); } private static void AddControllerToDrifterPrefab() { GameObject val = BodyCatalog.FindBodyPrefab("DrifterBody"); if (Object.op_Implicit((Object)(object)val)) { if (!Object.op_Implicit((Object)(object)val.GetComponent())) { Log.Debug("[BagStateSync] Adding BottomlessBagNetworkController to DrifterBody prefab"); val.AddComponent(); Log.Debug("[BagStateSync] Successfully added BottomlessBagNetworkController to DrifterBody prefab!"); } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[BagStateSync] Could not find DrifterBody prefab to add BottomlessBagNetworkController!"); } } private static void CreateSeatPrefab() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)AdditionalSeatPrefab != (Object)null)) { AdditionalSeatPrefab = new GameObject("DrifterBossGrabAdditionalSeat"); NetworkIdentity val = AdditionalSeatPrefab.AddComponent(); val.localPlayerAuthority = false; val.serverOnly = false; VehicleSeat val2 = AdditionalSeatPrefab.AddComponent(); GameObject val3 = new GameObject("SeatPosition"); val3.transform.SetParent(AdditionalSeatPrefab.transform); val3.transform.localPosition = Vector3.zero; val2.seatPosition = val3.transform; GameObject val4 = new GameObject("ExitPosition"); val4.transform.SetParent(AdditionalSeatPrefab.transform); val4.transform.localPosition = Vector3.zero; val2.exitPosition = val4.transform; val2.passengerState = new SerializableEntityStateType(typeof(Idle)); val2.hidePassenger = true; val2.disablePassengerMotor = true; val2.disableAllCollidersAndHurtboxes = true; val2.isEquipmentActivationAllowed = true; val2.shouldSetIdle = true; Guid guid = new Guid("d62f2e5a-7b3c-4e8a-9d1f-8c5e2a3b4d5e"); ReflectionCache.NetworkIdentity.AssetId?.SetValue(val, NetworkHash128.Parse(guid.ToString())); Object.DontDestroyOnLoad((Object)(object)AdditionalSeatPrefab); AdditionalSeatPrefab.SetActive(false); ClientScene.RegisterPrefab(AdditionalSeatPrefab); } } private static void OnClientConnect(NetworkConnection conn) { Log.Debug("[BagStateSync] OnClientConnect firing"); _ = NetworkManager.singleton?.client; } private static void OnServerStart() { Log.Debug("[BagStateSync] OnServerStart firing"); if ((Object)(object)DrifterBossGrabPlugin.Instance != (Object)null) { ((MonoBehaviour)DrifterBossGrabPlugin.Instance).StartCoroutine(DelayedServerHooksInit()); } } [IteratorStateMachine(typeof(d__10))] private static IEnumerator DelayedServerHooksInit() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__10(0); } private static void OnRunStart(Run run) { if (NetworkServer.active) { Log.Debug("[BagStateSync] OnRunStart - re-initializing server hooks"); PersistenceNetworkHandler.RegisterServerHooks(); } } public static void Cleanup() { NetworkManagerSystem.onClientConnectGlobal -= OnClientConnect; NetworkManagerSystem.onStartServerGlobal -= OnServerStart; Run.onRunStartGlobal -= OnRunStart; Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } _harmony = null; } } internal struct DoSyncContext { public GameObject? MainSeatObject; public List SyncedObjects; public List Seats; public ConcurrentDictionary AdditionalSeatDict; public DoSyncContext(List syncedObjects, List seats) { MainSeatObject = null; SyncedObjects = syncedObjects; Seats = seats; AdditionalSeatDict = new ConcurrentDictionary(); } } public class BottomlessBagNetworkController : NetworkBehaviour { [CompilerGenerated] private sealed class d__30 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public BottomlessBagNetworkController <>4__this; private DrifterBagController 5__2; private float 5__3; private float 5__4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__30(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0154: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; BottomlessBagNetworkController bottomlessBagNetworkController = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = ((Component)bottomlessBagNetworkController).GetComponent(); if (!Object.op_Implicit((Object)(object)5__2)) { return false; } 5__3 = 2f; 5__4 = 0f; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[BottomlessBagNetworkController] Starting state sync for " + ((Object)5__2).name); } break; case 1: <>1__state = -1; 5__4 += 0.1f; break; } if (5__4 < 5__3) { bool flag = true; foreach (uint item in bottomlessBagNetworkController._baggedObjectNetIdsTarget) { if (item != 0) { GameObject val = ClientScene.FindLocalObject(new NetworkInstanceId(item)) ?? NetworkServer.FindLocalObject(new NetworkInstanceId(item)); if ((Object)(object)val == (Object)null) { flag = false; break; } } } if (flag) { foreach (uint item2 in bottomlessBagNetworkController._additionalSeatNetIdsTarget) { if (item2 != 0) { GameObject val2 = ClientScene.FindLocalObject(new NetworkInstanceId(item2)) ?? NetworkServer.FindLocalObject(new NetworkInstanceId(item2)); if ((Object)(object)val2 == (Object)null) { flag = false; break; } } } } if (!flag) { <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; } } if (5__4 >= 5__3) { Log.Warning($"[SyncStateCoroutine] Timed out waiting for objects after {5__3:F2}s"); } bottomlessBagNetworkController._baggedObjectNetIds = new List(bottomlessBagNetworkController._baggedObjectNetIdsTarget); bottomlessBagNetworkController._additionalSeatNetIds = new List(bottomlessBagNetworkController._additionalSeatNetIdsTarget); bottomlessBagNetworkController.DoSync(5__2, triggerUIUpdate: true, bottomlessBagNetworkController._lastScrollDirection); bottomlessBagNetworkController._syncCoroutine = 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 readonly MethodInfo _tryOverrideUtilityMethod = ReflectionCache.BaggedObject.TryOverrideUtility; private static readonly MethodInfo _tryOverridePrimaryMethod = ReflectionCache.BaggedObject.TryOverridePrimary; public int selectedIndex = -1; private List _baggedObjectNetIds = new List(); private List _additionalSeatNetIds = new List(); private int _lastScrollDirection; private int _previousSelectedIndex = -1; private readonly Dictionary _netIdCache = new Dictionary(); private static readonly List _setBagStateIdBuffer = new List(); private static readonly List _setBagStateBoolBuffer = new List(); private static readonly List _setBagStateFloatBuffer = new List(); private static readonly List _setBagStateAttemptsBuffer = new List(); private static readonly List _setBagStateTotalTimesBuffer = new List(); private float _lastCarouselUpdateTime; private const float CAROUSEL_UPDATE_MIN_INTERVAL = 0.05f; public bool autoPromoteMainSeat; public bool prioritizeMainSeat; private List _baggedObjectNetIdsTarget = new List(); private List _additionalSeatNetIdsTarget = new List(); private Coroutine? _syncCoroutine; public override void OnStartClient() { ((NetworkBehaviour)this).OnStartClient(); OnBagStateChanged(); } public override void OnStartAuthority() { ((NetworkBehaviour)this).OnStartAuthority(); NetworkIdentity component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null) { CycleNetworkHandler.SendClientPreferences(component, PluginConfig.Instance.AutoPromoteMainSeat.Value, PluginConfig.Instance.PrioritizeMainSeat.Value); } } [Server] public void SetBagState(int index, List baggedObjects, List additionalSeats, int direction = 0) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) List setBagStateIdBuffer = _setBagStateIdBuffer; setBagStateIdBuffer.Clear(); NetworkInstanceId netId; foreach (GameObject baggedObject in baggedObjects) { if (Object.op_Implicit((Object)(object)baggedObject)) { NetworkIdentity component = baggedObject.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { netId = component.netId; setBagStateIdBuffer.Add(((NetworkInstanceId)(ref netId)).Value); } } } List list = new List(); foreach (GameObject additionalSeat in additionalSeats) { if (Object.op_Implicit((Object)(object)additionalSeat)) { NetworkIdentity component2 = additionalSeat.GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { netId = component2.netId; list.Add(((NetworkInstanceId)(ref netId)).Value); } } } if (NetworkServer.active) { if (CycleNetworkHandler.SuppressBroadcasts) { return; } DrifterBagController component3 = ((Component)this).GetComponent(); BagState bagState = (((Object)(object)component3 != (Object)null) ? BagPatches.GetState(component3) : null); List setBagStateBoolBuffer = _setBagStateBoolBuffer; setBagStateBoolBuffer.Clear(); List setBagStateFloatBuffer = _setBagStateFloatBuffer; setBagStateFloatBuffer.Clear(); List setBagStateAttemptsBuffer = _setBagStateAttemptsBuffer; setBagStateAttemptsBuffer.Clear(); List setBagStateTotalTimesBuffer = _setBagStateTotalTimesBuffer; setBagStateTotalTimesBuffer.Clear(); foreach (uint item5 in setBagStateIdBuffer) { GameObject val = NetworkServer.FindLocalObject(new NetworkInstanceId(item5)); bool item = false; float item2 = 0f; float item3 = 0f; float item4 = 0f; if ((Object)(object)val != (Object)null && (Object)(object)component3 != (Object)null) { if (bagState != null && bagState.DisabledCollidersByObject != null && bagState.DisabledCollidersByObject.TryGetValue(val, out Dictionary value)) { item = value.Count > 0; } BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(component3, val); if (baggedObjectStateData != null) { item2 = baggedObjectStateData.elapsedBreakoutTime; item3 = baggedObjectStateData.breakoutAttempts; item4 = baggedObjectStateData.breakoutTime; } } setBagStateBoolBuffer.Add(item); setBagStateFloatBuffer.Add(item2); setBagStateAttemptsBuffer.Add(item3); setBagStateTotalTimesBuffer.Add(item4); } UpdateBagStateMessage updateBagStateMessage = new UpdateBagStateMessage { controllerNetId = ((Component)this).GetComponent().netId, selectedIndex = index, baggedIds = setBagStateIdBuffer.ToArray(), seatIds = list.ToArray(), scrollDirection = direction, collidersDisabled = setBagStateBoolBuffer.ToArray(), elapsedBreakoutTimes = setBagStateFloatBuffer.ToArray(), breakoutAttempts = setBagStateAttemptsBuffer.ToArray(), breakoutTimes = setBagStateTotalTimesBuffer.ToArray() }; NetworkServer.SendToAll((short)206, (MessageBase)(object)updateBagStateMessage); UpdateLocalState(index, setBagStateIdBuffer, list); } else if (((NetworkBehaviour)this).hasAuthority) { DrifterBagController component4 = ((Component)this).GetComponent(); if ((Object)(object)component4 != (Object)null) { CycleNetworkHandler.SendClientBagState(component4, index, setBagStateIdBuffer.ToArray(), list.ToArray()); } UpdateLocalState(index, setBagStateIdBuffer, list); } } public void ApplyStateFromMessage(int index, uint[] baggedIds, uint[] seatIds, int direction, float[] elapsedTimes, float[] attempts, float[] totalTimes) { //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) _lastScrollDirection = direction; DrifterBagController component = ((Component)this).GetComponent(); if ((Object)(object)component != (Object)null && baggedIds != null && elapsedTimes != null && attempts != null && totalTimes != null && elapsedTimes.Length == baggedIds.Length && attempts.Length == baggedIds.Length && totalTimes.Length == baggedIds.Length) { NetworkInstanceId val = default(NetworkInstanceId); for (int i = 0; i < baggedIds.Length; i++) { ((NetworkInstanceId)(ref val))..ctor(baggedIds[i]); GameObject val2 = ClientScene.FindLocalObject(val) ?? NetworkServer.FindLocalObject(val); if ((Object)(object)val2 != (Object)null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(component, val2) ?? new BaggedObjectStateData(); if ((Object)(object)baggedObjectStateData.targetObject == (Object)null) { baggedObjectStateData.CalculateFromObject(val2, component); } baggedObjectStateData.elapsedBreakoutTime = elapsedTimes[i]; baggedObjectStateData.breakoutAttempts = (int)attempts[i]; baggedObjectStateData.breakoutTime = totalTimes[i]; BaggedObjectPatches.SaveObjectState(component, val2, baggedObjectStateData); } } } UpdateLocalState(index, new List(baggedIds), new List(seatIds)); } private bool IsObjectInAnySeat(DrifterBagController controller, GameObject obj) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return false; } if ((Object)(object)controller.vehicleSeat != (Object)null && controller.vehicleSeat.hasPassenger && (Object)(object)controller.vehicleSeat.NetworkpassengerBodyObject == (Object)(object)obj) { return true; } ConcurrentDictionary additionalSeats = BagPatches.GetState(controller).AdditionalSeats; if (additionalSeats != null) { foreach (KeyValuePair item in additionalSeats) { if ((Object)(object)item.Value != (Object)null && item.Value.hasPassenger && (Object)(object)item.Value.NetworkpassengerBodyObject == (Object)(object)obj) { return true; } } } VehicleSeat[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val in array) { if ((Object)(object)val != (Object)(object)controller.vehicleSeat && val.hasPassenger && (Object)(object)val.NetworkpassengerBodyObject == (Object)(object)obj) { return true; } } return false; } public void ServerUpdateFromClient(int index, uint[] baggedIds, uint[] seatIds) { //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { return; } Log.Debug($"[BottomlessBagNetworkController] ServerUpdateFromClient for {((Object)((Component)this).gameObject).name}. index={index}, objects={baggedIds.Length}"); UpdateLocalState(index, new List(baggedIds), new List(seatIds)); DrifterBagController component = ((Component)this).GetComponent(); if (!((Object)(object)component != (Object)null)) { return; } TryFixNullTargetState(component, new List(baggedIds)); uint[] array = seatIds; ConcurrentDictionary additionalSeats = BagPatches.GetState(component).AdditionalSeats; NetworkInstanceId netId; if (additionalSeats != null && additionalSeats.Count > 0) { List list = new List(); foreach (KeyValuePair item2 in additionalSeats) { if (!((Object)(object)item2.Value != (Object)null)) { continue; } NetworkIdentity component2 = ((Component)item2.Value).GetComponent(); if ((Object)(object)component2 != (Object)null) { netId = component2.netId; if (((NetworkInstanceId)(ref netId)).Value != 0) { netId = component2.netId; list.Add(((NetworkInstanceId)(ref netId)).Value); } } } if (list.Count > 0) { array = list.ToArray(); Log.Debug($"[ServerUpdateFromClient] Replaced client seatIds (count={seatIds.Length}) with {array.Length} recovered seat IDs"); } } int num = index; if (index < 0 && baggedIds.Length != 0) { GameObject mainSeatObject = BagPatches.GetMainSeatObject(component); if ((Object)(object)mainSeatObject != (Object)null) { NetworkIdentity component3 = mainSeatObject.GetComponent(); if ((Object)(object)component3 != (Object)null) { for (int i = 0; i < baggedIds.Length; i++) { uint num2 = baggedIds[i]; netId = component3.netId; if (num2 == ((NetworkInstanceId)(ref netId)).Value) { num = i; Log.Debug($"[ServerUpdateFromClient] Corrected index from {index} to {num} for {((Object)mainSeatObject).name}"); break; } } } } } List list2 = new List(); BagState state = BagPatches.GetState(component); if (state != null && state.DisabledCollidersByObject != null) { foreach (uint num3 in baggedIds) { GameObject val = NetworkServer.FindLocalObject(new NetworkInstanceId(num3)); bool item = false; if ((Object)(object)val != (Object)null && state.DisabledCollidersByObject.TryGetValue(val, out Dictionary value)) { item = value.Count > 0; } list2.Add(item); } } UpdateBagStateMessage updateBagStateMessage = new UpdateBagStateMessage { controllerNetId = ((Component)this).GetComponent().netId, selectedIndex = num, baggedIds = baggedIds, seatIds = array, scrollDirection = 0, collidersDisabled = list2.ToArray() }; NetworkServer.SendToAll((short)206, (MessageBase)(object)updateBagStateMessage); if (array != seatIds) { _additionalSeatNetIds = new List(array); _additionalSeatNetIdsTarget = new List(array); } } private void TryFixNullTargetState(DrifterBagController controller, List baggedIds) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active || baggedIds.Count == 0) { return; } EntityStateMachine[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); EntityStateMachine[] array = componentsInChildren; foreach (EntityStateMachine val in array) { EntityState state = val.state; BaggedObject val2 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val2 != null && (Object)(object)val2.targetObject == (Object)null) { GameObject val3 = NetworkServer.FindLocalObject(new NetworkInstanceId(baggedIds[0])); if ((Object)(object)val3 != (Object)null) { val2.targetObject = val3; BagPatches.SetMainSeatObject(controller, val3); } break; } } } private void UpdateLocalState(int index, List baggedIds, List seatIds) { selectedIndex = index; _baggedObjectNetIdsTarget = baggedIds; _additionalSeatNetIdsTarget = seatIds; if (NetworkServer.active) { _baggedObjectNetIds = new List(_baggedObjectNetIdsTarget); _additionalSeatNetIds = new List(_additionalSeatNetIdsTarget); DrifterBagController component = ((Component)this).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { DoSync(component, triggerUIUpdate: false); } } else { OnBagStateChanged(); } } private void UpdateNetIdCache() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) _netIdCache.Clear(); NetworkInstanceId val = default(NetworkInstanceId); foreach (uint baggedObjectNetId in _baggedObjectNetIds) { ((NetworkInstanceId)(ref val))..ctor(baggedObjectNetId); GameObject val2 = ClientScene.FindLocalObject(val) ?? NetworkServer.FindLocalObject(val); if (Object.op_Implicit((Object)(object)val2)) { _netIdCache[val] = val2; } } NetworkInstanceId val3 = default(NetworkInstanceId); foreach (uint additionalSeatNetId in _additionalSeatNetIds) { ((NetworkInstanceId)(ref val3))..ctor(additionalSeatNetId); GameObject val4 = ClientScene.FindLocalObject(val3) ?? NetworkServer.FindLocalObject(val3); if (Object.op_Implicit((Object)(object)val4)) { _netIdCache[val3] = val4; } } } private void OnBagStateChanged() { if (!NetworkServer.active) { if (_syncCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(_syncCoroutine); } _syncCoroutine = ((MonoBehaviour)this).StartCoroutine(SyncStateCoroutine()); } } [IteratorStateMachine(typeof(d__30))] private IEnumerator SyncStateCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__30(0) { <>4__this = this }; } private void DoSync(DrifterBagController? controller, bool triggerUIUpdate, int scrollDirection = 0) { if ((Object)(object)controller == (Object)null) { return; } if (scrollDirection != 0) { DrifterBossGrabPlugin.LastCycleClientTime = Time.time; DrifterBossGrabPlugin._isSwappingPassengers = true; } try { List baggedObjects = GetBaggedObjects(); List additionalSeats = GetAdditionalSeats(); DoSyncContext ctx = new DoSyncContext(baggedObjects, additionalSeats); if (NetworkServer.active) { DoSync_Server(controller, ref ctx); } else { DoSync_Client_Populate(controller, ref ctx); } ResolveMainSeatObject(controller, ref ctx, NetworkServer.active); BagState state = BagPatches.GetState(controller); GameObject mainSeatObject = state.MainSeatObject; state.AdditionalSeats = ctx.AdditionalSeatDict; BagPatches.SetMainSeatObject(controller, ctx.MainSeatObject); if (ctx.SyncedObjects != null && (state.BaggedObjects == null || ctx.SyncedObjects.Count >= state.BaggedObjects.Count)) { state.BaggedObjects = ctx.SyncedObjects; } if (!NetworkServer.active) { DoSync_Client_Actions(controller, ref ctx); } DoSync_Shared(controller, ref ctx, triggerUIUpdate, scrollDirection, mainSeatObject); } finally { if (scrollDirection != 0) { DrifterBossGrabPlugin._isSwappingPassengers = false; } } } private void DoSync_Server(DrifterBagController? controller, ref DoSyncContext ctx) { if ((Object)(object)controller == (Object)null) { return; } VehicleSeat[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); if (componentsInChildren == null) { return; } VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val in array) { if ((Object)(object)val == (Object)(object)controller.vehicleSeat || !((Object)(object)val != (Object)null) || !val.hasPassenger) { continue; } GameObject networkpassengerBodyObject = val.NetworkpassengerBodyObject; if (!((Object)(object)networkpassengerBodyObject != (Object)null) || ctx.AdditionalSeatDict.ContainsKey(networkpassengerBodyObject)) { continue; } bool flag = false; foreach (GameObject syncedObject in ctx.SyncedObjects) { if ((Object)(object)syncedObject != (Object)null && ((Object)syncedObject).GetInstanceID() == ((Object)networkpassengerBodyObject).GetInstanceID()) { flag = true; break; } } if (flag) { ctx.AdditionalSeatDict[networkpassengerBodyObject] = val; } } } private void DoSync_Client_Populate(DrifterBagController? controller, ref DoSyncContext ctx) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } VehicleSeat[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val in array) { if ((Object)(object)val == (Object)(object)controller.vehicleSeat) { continue; } bool flag = false; if (ctx.Seats != null) { foreach (VehicleSeat seat in ctx.Seats) { if ((Object)(object)seat == (Object)(object)val) { flag = true; break; } } } if (flag) { continue; } NetworkIdentity component = ((Component)val).GetComponent(); if (!((Object)(object)component == (Object)null)) { NetworkInstanceId netId = component.netId; if (((NetworkInstanceId)(ref netId)).Value != 0) { continue; } } if (!val.hasPassenger) { Object.Destroy((Object)(object)((Component)val).gameObject); } } } private void DoSync_Client_Actions(DrifterBagController? controller, ref DoSyncContext ctx) { //IL_02b7: Unknown result type (might be due to invalid IL or missing references) //IL_02c8: Unknown result type (might be due to invalid IL or missing references) //IL_0311: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return; } if (ctx.SyncedObjects != null) { foreach (GameObject syncedObject in ctx.SyncedObjects) { if (!((Object)(object)syncedObject == (Object)null)) { if (!PersistenceObjectsTracker.IsObjectCurrentlyBagged(syncedObject)) { PersistenceObjectsTracker.TrackBaggedObject(syncedObject); } PersistenceObjectsTracker.SetBaggedObjectVisibility(syncedObject, isVisible: false); } } } if ((Object)(object)ctx.MainSeatObject != (Object)null && _previousSelectedIndex < 0) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(controller, ctx.MainSeatObject); if (baggedObjectStateData != null) { BaggedObject val = BaggedObjectPatches.FindOrCreateBaggedObjectState(controller, ctx.MainSeatObject); if (val != null) { baggedObjectStateData.ApplyToBaggedObject(val); } } } if ((Object)(object)ctx.MainSeatObject != (Object)null && (Object)(object)controller != (Object)null && ctx.SyncedObjects != null && ctx.SyncedObjects.Contains(ctx.MainSeatObject) && !ProjectileRecoveryPatches.IsInProjectileState(ctx.MainSeatObject)) { if ((Object)(object)ctx.MainSeatObject.transform.parent != (Object)null) { Log.Debug("[DoSync_Client_Actions] Unparenting main seat object " + ((Object)ctx.MainSeatObject).name + " from " + ((Object)ctx.MainSeatObject.transform.parent).name); ctx.MainSeatObject.transform.SetParent((Transform)null, true); } BaggedObject val2 = BaggedObjectPatches.FindOrCreateBaggedObjectState(controller, ctx.MainSeatObject); if (val2 != null) { val2.targetObject = ctx.MainSeatObject; BaggedObjectPatches.UpdateTargetFields(val2); EntityStateMachine outer = ((EntityState)val2).outer; SkillLocator val3 = ((outer != null) ? ((Component)outer).GetComponent() : null); if ((Object)(object)val3 != (Object)null) { if ((Object)(object)val3.utility != (Object)null) { _tryOverrideUtilityMethod?.Invoke(val2, new object[1] { val3.utility }); } if ((Object)(object)val3.primary != (Object)null) { _tryOverridePrimaryMethod?.Invoke(val2, new object[1] { val3.primary }); } } } } if (ctx.SyncedObjects == null || ctx.AdditionalSeatDict == null || !((Object)(object)controller != (Object)null)) { return; } foreach (GameObject syncedObject2 in ctx.SyncedObjects) { if ((Object)(object)syncedObject2 == (Object)null || (Object)(object)syncedObject2 == (Object)(object)ctx.MainSeatObject || !ctx.AdditionalSeatDict.TryGetValue(syncedObject2, out VehicleSeat value) || (Object)(object)value == (Object)null || ProjectileRecoveryPatches.IsInProjectileState(syncedObject2)) { continue; } if ((Object)(object)syncedObject2.transform.parent != (Object)(object)((Component)controller).transform) { syncedObject2.transform.SetParent(((Component)controller).transform); syncedObject2.transform.localPosition = Vector3.zero; syncedObject2.transform.localRotation = Quaternion.identity; } BaggedObjectStateData baggedObjectStateData2 = BaggedObjectPatches.LoadObjectState(controller, syncedObject2); if (baggedObjectStateData2 != null) { CharacterBody component = syncedObject2.GetComponent(); if ((Object)(object)component != (Object)null) { baggedObjectStateData2.ApplyToCharacterBody(component); } } CharacterBody component2 = syncedObject2.GetComponent(); if ((Object)(object)component2 != (Object)null && ((Enum)component2.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288)) { BagState state = BagPatches.GetState(controller); if (state != null && !state.DisabledCollidersByObject.ContainsKey(syncedObject2)) { state.DisabledCollidersByObject[syncedObject2] = new Dictionary(); } if (state != null) { BodyColliderCache.DisableMovementColliders(syncedObject2, state.DisabledCollidersByObject[syncedObject2]); } } } } private void ResolveMainSeatObject(DrifterBagController? controller, ref DoSyncContext ctx, bool isServer) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if (ctx.Seats != null) { foreach (VehicleSeat seat in ctx.Seats) { if (!((Object)(object)seat != (Object)null)) { continue; } if ((Object)(object)seat != (Object)null && (Object)(object)controller != (Object)null && (Object)(object)((Component)seat).transform.parent != (Object)(object)((Component)controller).transform) { ((Component)seat).transform.SetParent(((Component)controller).transform); ((Component)seat).transform.localPosition = Vector3.zero; ((Component)seat).transform.localRotation = Quaternion.identity; } if ((Object)(object)seat != (Object)null && seat.hasPassenger) { GameObject networkpassengerBodyObject = seat.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject != (Object)null) { ctx.AdditionalSeatDict[networkpassengerBodyObject] = seat; } } } } if (ctx.SyncedObjects == null || selectedIndex < 0 || selectedIndex >= ctx.SyncedObjects.Count) { return; } GameObject val = ctx.SyncedObjects[selectedIndex]; bool flag = false; if (isServer) { if ((Object)(object)controller != (Object)null && (Object)(object)controller.vehicleSeat != (Object)null && controller.vehicleSeat.hasPassenger && controller.vehicleSeat.NetworkpassengerBodyObject == val) { flag = true; } } else { flag = true; } if (flag) { ctx.MainSeatObject = val; if ((Object)(object)ctx.MainSeatObject != (Object)null) { ctx.AdditionalSeatDict.TryRemove(ctx.MainSeatObject, out VehicleSeat _); } } } private void DoSync_Shared(DrifterBagController? controller, ref DoSyncContext ctx, bool triggerUIUpdate, int scrollDirection, GameObject? oldMain) { _previousSelectedIndex = selectedIndex; if (!((Object)(object)controller != (Object)null)) { return; } BagPassengerManager.ForceRecalculateMass(controller); if (ctx.SyncedObjects != null) { BagPassengerManager.MarkMassDirty(controller); } if (!triggerUIUpdate) { return; } if (BagPassengerManager.IsProcessingThrowRemoval) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[DoSync] Skipping carousel update - processing throw removal"); } return; } float num = Time.time - _lastCarouselUpdateTime; if (num >= 0.05f) { BagCarouselUpdater.UpdateCarousel(controller, scrollDirection); _lastCarouselUpdateTime = Time.time; if ((Object)(object)ctx.MainSeatObject != (Object)(object)oldMain && (Object)(object)ctx.MainSeatObject != (Object)null) { BaggedObjectPatches.RefreshUIOverlayForMainSeat(controller, ctx.MainSeatObject); } else if ((Object)(object)ctx.MainSeatObject == (Object)null) { BaggedObjectPatches.RemoveUIOverlayForNullState(controller); } } } public int GetTotalObjectCount() { if (NetworkServer.active) { return _baggedObjectNetIds.Count; } return Math.Max(_baggedObjectNetIds.Count, _baggedObjectNetIdsTarget.Count); } public List GetBaggedObjects() { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if (_netIdCache.Count == 0) { UpdateNetIdCache(); } List list = new List(); List list2 = new List(); NetworkInstanceId val = default(NetworkInstanceId); for (int i = 0; i < _baggedObjectNetIds.Count; i++) { uint num = _baggedObjectNetIds[i]; ((NetworkInstanceId)(ref val))..ctor(num); if (_netIdCache.TryGetValue(val, out GameObject value) && Object.op_Implicit((Object)(object)value)) { list.Add(value); continue; } GameObject val2 = ClientScene.FindLocalObject(val) ?? NetworkServer.FindLocalObject(val); if (Object.op_Implicit((Object)(object)val2)) { list.Add(val2); _netIdCache[val] = val2; } else { list2.Add(i); } } if (NetworkServer.active) { for (int num2 = list2.Count - 1; num2 >= 0; num2--) { _baggedObjectNetIds.RemoveAt(list2[num2]); _baggedObjectNetIdsTarget.RemoveAt(list2[num2]); } } return list; } public List GetAdditionalSeats() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) List list = new List(); NetworkInstanceId val = default(NetworkInstanceId); foreach (uint additionalSeatNetId in _additionalSeatNetIds) { ((NetworkInstanceId)(ref val))..ctor(additionalSeatNetId); GameObject val2 = ClientScene.FindLocalObject(val) ?? NetworkServer.FindLocalObject(val); if (Object.op_Implicit((Object)(object)val2)) { VehicleSeat component = val2.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { list.Add(component); } } } return list; } public void RemoveBaggedObjectId(NetworkInstanceId netId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!(netId == NetworkInstanceId.Invalid)) { _baggedObjectNetIds.Remove(((NetworkInstanceId)(ref netId)).Value); _baggedObjectNetIdsTarget.Remove(((NetworkInstanceId)(ref netId)).Value); _netIdCache.Remove(netId); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[BottomlessBagNetworkController] Removed netId={((NetworkInstanceId)(ref netId)).Value} from bagged state"); } } } public void TryAddBaggedObjectId(NetworkInstanceId netId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) if (!(netId == NetworkInstanceId.Invalid)) { if (!_baggedObjectNetIds.Contains(((NetworkInstanceId)(ref netId)).Value)) { _baggedObjectNetIds.Add(((NetworkInstanceId)(ref netId)).Value); } if (!_baggedObjectNetIdsTarget.Contains(((NetworkInstanceId)(ref netId)).Value)) { _baggedObjectNetIdsTarget.Add(((NetworkInstanceId)(ref netId)).Value); } } } } public class BaggedObjectsPersistenceMessage : MessageBase { public List baggedObjectNetIds = new List(); public List ownerPlayerIds = new List(); public List collidersDisabled = new List(); public override void Serialize(NetworkWriter writer) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) int num = Math.Min(baggedObjectNetIds.Count, 1000); writer.Write(num); for (int i = 0; i < num; i++) { writer.Write(baggedObjectNetIds[i]); } num = Math.Min(ownerPlayerIds.Count, 1000); writer.Write(num); for (int j = 0; j < num; j++) { writer.Write(ownerPlayerIds[j] ?? string.Empty); } num = Math.Min(collidersDisabled.Count, 1000); writer.Write(num); for (int k = 0; k < num; k++) { writer.Write(collidersDisabled[k]); } } public override void Deserialize(NetworkReader reader) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) int num = Math.Min(reader.ReadInt32(), 1000); baggedObjectNetIds.Clear(); for (int i = 0; i < num; i++) { baggedObjectNetIds.Add(reader.ReadNetworkId()); } num = Math.Min(reader.ReadInt32(), 1000); ownerPlayerIds.Clear(); for (int j = 0; j < num; j++) { ownerPlayerIds.Add(reader.ReadString()); } num = Math.Min(reader.ReadInt32(), 1000); collidersDisabled.Clear(); for (int k = 0; k < num; k++) { collidersDisabled.Add(reader.ReadBoolean()); } } } public class UpdateBagStateMessage : MessageBase { public NetworkInstanceId controllerNetId; public int selectedIndex; public uint[] baggedIds = Array.Empty(); public uint[] seatIds = Array.Empty(); public int scrollDirection; public bool[] collidersDisabled = Array.Empty(); public float[] elapsedBreakoutTimes = Array.Empty(); public float[] breakoutAttempts = Array.Empty(); public float[] breakoutTimes = Array.Empty(); public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(controllerNetId); writer.Write(selectedIndex); writer.Write(scrollDirection); int num = Math.Min(baggedIds.Length, 500); writer.Write(num); for (int i = 0; i < num; i++) { writer.Write(baggedIds[i]); } int num2 = Math.Min(seatIds.Length, 500); writer.Write(num2); for (int j = 0; j < num2; j++) { writer.Write(seatIds[j]); } int num3 = Math.Min(collidersDisabled.Length, 500); writer.Write(num3); for (int k = 0; k < num3; k++) { writer.Write(collidersDisabled[k]); } int num4 = Math.Min(elapsedBreakoutTimes.Length, 500); writer.Write(num4); for (int l = 0; l < num4; l++) { writer.Write(elapsedBreakoutTimes[l]); writer.Write(breakoutAttempts[l]); writer.Write(breakoutTimes[l]); } } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) controllerNetId = reader.ReadNetworkId(); selectedIndex = reader.ReadInt32(); scrollDirection = reader.ReadInt32(); int num = Math.Min(reader.ReadInt32(), 500); baggedIds = new uint[num]; for (int i = 0; i < num; i++) { baggedIds[i] = reader.ReadUInt32(); } int num2 = Math.Min(reader.ReadInt32(), 500); seatIds = new uint[num2]; for (int j = 0; j < num2; j++) { seatIds[j] = reader.ReadUInt32(); } int num3 = Math.Min(reader.ReadInt32(), 500); collidersDisabled = new bool[num3]; for (int k = 0; k < num3; k++) { collidersDisabled[k] = reader.ReadBoolean(); } int num4 = Math.Min(reader.ReadInt32(), 500); elapsedBreakoutTimes = new float[num4]; breakoutAttempts = new float[num4]; breakoutTimes = new float[num4]; for (int l = 0; l < num4; l++) { elapsedBreakoutTimes[l] = reader.ReadSingle(); breakoutAttempts[l] = reader.ReadSingle(); breakoutTimes[l] = reader.ReadSingle(); } } } public class CyclePassengersMessage : MessageBase { public NetworkInstanceId bagControllerNetId = NetworkInstanceId.Invalid; public int amount; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(bagControllerNetId); writer.Write(amount); } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) bagControllerNetId = reader.ReadNetworkId(); amount = reader.ReadInt32(); } } public class ClientUpdateBagStateMessage : MessageBase { public NetworkInstanceId controllerNetId; public int selectedIndex; public uint[] baggedIds = Array.Empty(); public uint[] seatIds = Array.Empty(); public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(controllerNetId); writer.Write(selectedIndex); int num = Math.Min(baggedIds.Length, 500); writer.Write(num); for (int i = 0; i < num; i++) { writer.Write(baggedIds[i]); } int num2 = Math.Min(seatIds.Length, 500); writer.Write(num2); for (int j = 0; j < num2; j++) { writer.Write(seatIds[j]); } } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) controllerNetId = reader.ReadNetworkId(); selectedIndex = reader.ReadInt32(); int num = Math.Min(reader.ReadInt32(), 500); baggedIds = new uint[num]; for (int i = 0; i < num; i++) { baggedIds[i] = reader.ReadUInt32(); } int num2 = Math.Min(reader.ReadInt32(), 500); seatIds = new uint[num2]; for (int j = 0; j < num2; j++) { seatIds[j] = reader.ReadUInt32(); } } } public class GrabObjectMessage : MessageBase { public NetworkInstanceId bagControllerNetId = NetworkInstanceId.Invalid; public NetworkInstanceId targetObjectNetId = NetworkInstanceId.Invalid; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) writer.Write(bagControllerNetId); writer.Write(targetObjectNetId); } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) bagControllerNetId = reader.ReadNetworkId(); targetObjectNetId = reader.ReadNetworkId(); } } public class SyncConfigMessage : MessageBase { public bool EnableBossGrabbing; public bool EnableNPCGrabbing; public bool EnableEnvironmentGrabbing; public bool EnableLockedObjectGrabbing; public ProjectileGrabbingMode ProjectileGrabbingMode; public float SearchRadiusMultiplier; public ComponentChooserSortMode ComponentChooserSortMode; public float BreakoutTimeMultiplier; public int MaxSmacks; public string MaxLaunchSpeed = "100"; public string BodyBlacklist = string.Empty; public string RecoveryObjectBlacklist = string.Empty; public string GrabbableComponentTypes = string.Empty; public string GrabbableKeywordBlacklist = string.Empty; public bool EnableObjectPersistence; public bool EnableAutoGrab; public bool PersistBaggedBosses; public bool PersistBaggedNPCs; public bool PersistBaggedEnvironmentObjects; public string PersistenceBlacklist = string.Empty; public float AutoGrabDelay; public bool BottomlessBagEnabled; public bool EnableStockRefreshClamping; public bool EnableSuccessiveGrabStockRefresh; public float CycleCooldown; public bool EnableBalance; public AoEDamageMode AoEDamageDistribution; public string BagScaleCap = "1"; public string MassCap = "700"; public StateCalculationMode StateCalculationMode; public float OverencumbranceMax; public string SlotScalingFormula = string.Empty; public string MassCapacityFormula = string.Empty; public string MovespeedPenaltyFormula = string.Empty; public string EliteFlagMultiplier = "1.0"; public string BossFlagMultiplier = "1.0"; public string ChampionFlagMultiplier = "1.0"; public string PlayerFlagMultiplier = "1.0"; public string MinionFlagMultiplier = "1.0"; public string DroneFlagMultiplier = "1.0"; public string MechanicalFlagMultiplier = "1.0"; public string VoidFlagMultiplier = "1.0"; public string AllFlagMultiplier = "1.0"; public override void Serialize(NetworkWriter writer) { writer.Write(EnableBossGrabbing); writer.Write(EnableNPCGrabbing); writer.Write(EnableEnvironmentGrabbing); writer.Write(EnableLockedObjectGrabbing); writer.Write((int)ProjectileGrabbingMode); writer.Write(SearchRadiusMultiplier); writer.Write((int)ComponentChooserSortMode); writer.Write(BreakoutTimeMultiplier); writer.Write(MaxSmacks); writer.Write(BodyBlacklist); writer.Write(RecoveryObjectBlacklist); writer.Write(GrabbableComponentTypes); writer.Write(GrabbableKeywordBlacklist); writer.Write(EnableObjectPersistence); writer.Write(EnableAutoGrab); writer.Write(PersistBaggedBosses); writer.Write(PersistBaggedNPCs); writer.Write(PersistBaggedEnvironmentObjects); writer.Write(PersistenceBlacklist); writer.Write(AutoGrabDelay); writer.Write(BottomlessBagEnabled); writer.Write(EnableStockRefreshClamping); writer.Write(EnableSuccessiveGrabStockRefresh); writer.Write(CycleCooldown); writer.Write(EnableBalance); writer.Write((int)AoEDamageDistribution); writer.Write(BagScaleCap); writer.Write(MassCap); writer.Write((int)StateCalculationMode); writer.Write(OverencumbranceMax); writer.Write(SlotScalingFormula); writer.Write(MassCapacityFormula); writer.Write(MovespeedPenaltyFormula); writer.Write(EliteFlagMultiplier); writer.Write(BossFlagMultiplier); writer.Write(ChampionFlagMultiplier); writer.Write(PlayerFlagMultiplier); writer.Write(MinionFlagMultiplier); writer.Write(DroneFlagMultiplier); writer.Write(MechanicalFlagMultiplier); writer.Write(VoidFlagMultiplier); writer.Write(AllFlagMultiplier); } public override void Deserialize(NetworkReader reader) { EnableBossGrabbing = reader.ReadBoolean(); EnableNPCGrabbing = reader.ReadBoolean(); EnableEnvironmentGrabbing = reader.ReadBoolean(); EnableLockedObjectGrabbing = reader.ReadBoolean(); ProjectileGrabbingMode = (ProjectileGrabbingMode)reader.ReadInt32(); SearchRadiusMultiplier = reader.ReadSingle(); ComponentChooserSortMode = (ComponentChooserSortMode)reader.ReadInt32(); BreakoutTimeMultiplier = reader.ReadSingle(); MaxSmacks = reader.ReadInt32(); BodyBlacklist = reader.ReadString(); RecoveryObjectBlacklist = reader.ReadString(); GrabbableComponentTypes = reader.ReadString(); GrabbableKeywordBlacklist = reader.ReadString(); EnableObjectPersistence = reader.ReadBoolean(); EnableAutoGrab = reader.ReadBoolean(); PersistBaggedBosses = reader.ReadBoolean(); PersistBaggedNPCs = reader.ReadBoolean(); PersistBaggedEnvironmentObjects = reader.ReadBoolean(); PersistenceBlacklist = reader.ReadString(); AutoGrabDelay = reader.ReadSingle(); BottomlessBagEnabled = reader.ReadBoolean(); EnableStockRefreshClamping = reader.ReadBoolean(); EnableSuccessiveGrabStockRefresh = reader.ReadBoolean(); CycleCooldown = reader.ReadSingle(); EnableBalance = reader.ReadBoolean(); AoEDamageDistribution = (AoEDamageMode)reader.ReadInt32(); BagScaleCap = reader.ReadString(); MassCap = reader.ReadString(); StateCalculationMode = (StateCalculationMode)reader.ReadInt32(); OverencumbranceMax = reader.ReadSingle(); SlotScalingFormula = reader.ReadString(); MassCapacityFormula = reader.ReadString(); MovespeedPenaltyFormula = reader.ReadString(); EliteFlagMultiplier = reader.ReadString(); BossFlagMultiplier = reader.ReadString(); ChampionFlagMultiplier = reader.ReadString(); PlayerFlagMultiplier = reader.ReadString(); MinionFlagMultiplier = reader.ReadString(); DroneFlagMultiplier = reader.ReadString(); MechanicalFlagMultiplier = reader.ReadString(); VoidFlagMultiplier = reader.ReadString(); AllFlagMultiplier = reader.ReadString(); } } public class ClientPreferencesMessage : MessageBase { public NetworkInstanceId controllerNetId; public bool autoPromoteMainSeat; public bool prioritizeMainSeat; public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) writer.Write(controllerNetId); writer.Write(autoPromoteMainSeat); writer.Write(prioritizeMainSeat); } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) controllerNetId = reader.ReadNetworkId(); autoPromoteMainSeat = reader.ReadBoolean(); prioritizeMainSeat = reader.ReadBoolean(); } } public class BagStateUpdatedMessage : MessageBase { public NetworkInstanceId controllerNetId; public int selectedIndex; public NetworkInstanceId removedObjectNetId; public uint[] baggedIds = Array.Empty(); public uint[] seatIds = Array.Empty(); public int scrollDirection; public bool isThrowOperation; public float[] elapsedBreakoutTimes = Array.Empty(); public float[] breakoutAttempts = Array.Empty(); public float[] breakoutTimes = Array.Empty(); public override void Serialize(NetworkWriter writer) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) writer.Write(controllerNetId); writer.Write(selectedIndex); writer.Write(removedObjectNetId); writer.Write(scrollDirection); writer.Write(isThrowOperation); int num = Math.Min(baggedIds.Length, 500); writer.Write(num); for (int i = 0; i < num; i++) { writer.Write(baggedIds[i]); } int num2 = Math.Min(seatIds.Length, 500); writer.Write(num2); for (int j = 0; j < num2; j++) { writer.Write(seatIds[j]); } int num3 = Math.Min(elapsedBreakoutTimes.Length, 500); writer.Write(num3); for (int k = 0; k < num3; k++) { writer.Write(elapsedBreakoutTimes[k]); writer.Write(breakoutAttempts[k]); writer.Write(breakoutTimes[k]); } } public override void Deserialize(NetworkReader reader) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) controllerNetId = reader.ReadNetworkId(); selectedIndex = reader.ReadInt32(); removedObjectNetId = reader.ReadNetworkId(); scrollDirection = reader.ReadInt32(); isThrowOperation = reader.ReadBoolean(); int num = Math.Min(reader.ReadInt32(), 500); baggedIds = new uint[num]; for (int i = 0; i < num; i++) { baggedIds[i] = reader.ReadUInt32(); } int num2 = Math.Min(reader.ReadInt32(), 500); seatIds = new uint[num2]; for (int j = 0; j < num2; j++) { seatIds[j] = reader.ReadUInt32(); } int num3 = Math.Min(reader.ReadInt32(), 500); elapsedBreakoutTimes = new float[num3]; breakoutAttempts = new float[num3]; breakoutTimes = new float[num3]; for (int k = 0; k < num3; k++) { elapsedBreakoutTimes[k] = reader.ReadSingle(); breakoutAttempts[k] = reader.ReadSingle(); breakoutTimes[k] = reader.ReadSingle(); } } } public static class ConfigSyncHandler { [CompilerGenerated] private sealed class d__5 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__5(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; _isBroadcastPending = false; if (!NetworkServer.active) { return false; } if (!PluginConfig.Instance.EnableConfigSync.Value) { Log.Debug("[ConfigSyncHandler] Sync disabled by host config. Skipping broadcast."); return false; } Log.Debug("[ConfigSyncHandler] Broadcasting updated config to all connected clients."); foreach (NetworkConnection connection in NetworkServer.connections) { if (connection != null && connection.isReady) { SendConfigToClient(connection); } } 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 volatile bool _isBroadcastPending; public static void SendConfigToClient(NetworkConnection conn) { if (NetworkServer.active) { if (!PluginConfig.Instance.EnableConfigSync.Value) { Log.Debug($"[ConfigSyncHandler] Sync disabled by host config. Skipping send to client {conn.connectionId}."); return; } SyncConfigMessage syncConfigMessage = new SyncConfigMessage { EnableBossGrabbing = PluginConfig.Instance.EnableBossGrabbing.Value, EnableNPCGrabbing = PluginConfig.Instance.EnableNPCGrabbing.Value, EnableEnvironmentGrabbing = PluginConfig.Instance.EnableEnvironmentGrabbing.Value, EnableLockedObjectGrabbing = PluginConfig.Instance.EnableLockedObjectGrabbing.Value, ProjectileGrabbingMode = PluginConfig.Instance.ProjectileGrabbingMode.Value, SearchRadiusMultiplier = PluginConfig.Instance.SearchRadiusMultiplier.Value, ComponentChooserSortMode = PluginConfig.Instance.ComponentChooserSortModeEntry.Value, BreakoutTimeMultiplier = PluginConfig.Instance.BreakoutTimeMultiplier.Value, MaxSmacks = PluginConfig.Instance.MaxSmacks.Value, MaxLaunchSpeed = PluginConfig.Instance.MaxLaunchSpeed.Value, BodyBlacklist = PluginConfig.Instance.BodyBlacklist.Value, RecoveryObjectBlacklist = PluginConfig.Instance.RecoveryObjectBlacklist.Value, GrabbableComponentTypes = PluginConfig.Instance.GrabbableComponentTypes.Value, GrabbableKeywordBlacklist = PluginConfig.Instance.GrabbableKeywordBlacklist.Value, EnableObjectPersistence = PluginConfig.Instance.EnableObjectPersistence.Value, EnableAutoGrab = PluginConfig.Instance.EnableAutoGrab.Value, PersistBaggedBosses = PluginConfig.Instance.PersistBaggedBosses.Value, PersistBaggedNPCs = PluginConfig.Instance.PersistBaggedNPCs.Value, PersistBaggedEnvironmentObjects = PluginConfig.Instance.PersistBaggedEnvironmentObjects.Value, PersistenceBlacklist = PluginConfig.Instance.PersistenceBlacklist.Value, AutoGrabDelay = PluginConfig.Instance.AutoGrabDelay.Value, BottomlessBagEnabled = PluginConfig.Instance.BottomlessBagEnabled.Value, EnableStockRefreshClamping = PluginConfig.Instance.EnableStockRefreshClamping.Value, EnableSuccessiveGrabStockRefresh = PluginConfig.Instance.EnableSuccessiveGrabStockRefresh.Value, CycleCooldown = PluginConfig.Instance.CycleCooldown.Value, EnableBalance = PluginConfig.Instance.EnableBalance.Value, AoEDamageDistribution = PluginConfig.Instance.AoEDamageDistribution.Value, BagScaleCap = PluginConfig.Instance.BagScaleCap.Value, MassCap = PluginConfig.Instance.MassCap.Value, StateCalculationMode = PluginConfig.Instance.StateCalculationMode.Value, OverencumbranceMax = PluginConfig.Instance.OverencumbranceMax.Value, SlotScalingFormula = PluginConfig.Instance.SlotScalingFormula.Value, MassCapacityFormula = PluginConfig.Instance.MassCapacityFormula.Value, MovespeedPenaltyFormula = PluginConfig.Instance.MovespeedPenaltyFormula.Value, EliteFlagMultiplier = PluginConfig.Instance.EliteFlagMultiplier.Value, BossFlagMultiplier = PluginConfig.Instance.BossFlagMultiplier.Value, ChampionFlagMultiplier = PluginConfig.Instance.ChampionFlagMultiplier.Value, PlayerFlagMultiplier = PluginConfig.Instance.PlayerFlagMultiplier.Value, MinionFlagMultiplier = PluginConfig.Instance.MinionFlagMultiplier.Value, DroneFlagMultiplier = PluginConfig.Instance.DroneFlagMultiplier.Value, MechanicalFlagMultiplier = PluginConfig.Instance.MechanicalFlagMultiplier.Value, VoidFlagMultiplier = PluginConfig.Instance.VoidFlagMultiplier.Value, AllFlagMultiplier = PluginConfig.Instance.AllFlagMultiplier.Value }; Log.Debug($"[ConfigSyncHandler] Sending config to client {conn.connectionId} (general, bottomlessbag, persistence, balance)"); conn.Send((short)210, (MessageBase)(object)syncConfigMessage); } } public static void BroadcastConfigToClients() { if (NetworkServer.active && !_isBroadcastPending) { _isBroadcastPending = true; if ((Object)(object)DrifterBossGrabPlugin.Instance != (Object)null) { ((MonoBehaviour)DrifterBossGrabPlugin.Instance).StartCoroutine(DelayBroadcast()); } } } [NetworkMessageHandler(msgType = 210, client = true, server = false)] public static void HandleSyncConfigMessage(NetworkMessage netMsg) { if (!NetworkServer.active) { if (!PluginConfig.Instance.EnableConfigSync.Value) { Log.Debug("[ConfigSyncHandler] Config sync disabled by client setting. Ignoring config from host."); return; } SyncConfigMessage msg = netMsg.ReadMessage(); Log.Debug("[ConfigSyncHandler] Received config from host (general, bottomlessbag, persistence, balance)."); ApplySyncedConfig(msg); } } private static void ApplySyncedConfig(SyncConfigMessage msg) { PluginConfig.Instance.EnableBossGrabbing.Value = msg.EnableBossGrabbing; PluginConfig.Instance.EnableNPCGrabbing.Value = msg.EnableNPCGrabbing; PluginConfig.Instance.EnableEnvironmentGrabbing.Value = msg.EnableEnvironmentGrabbing; PluginConfig.Instance.EnableLockedObjectGrabbing.Value = msg.EnableLockedObjectGrabbing; PluginConfig.Instance.ProjectileGrabbingMode.Value = msg.ProjectileGrabbingMode; PluginConfig.Instance.SearchRadiusMultiplier.Value = msg.SearchRadiusMultiplier; PluginConfig.Instance.ComponentChooserSortModeEntry.Value = msg.ComponentChooserSortMode; PluginConfig.Instance.BreakoutTimeMultiplier.Value = msg.BreakoutTimeMultiplier; PluginConfig.Instance.MaxSmacks.Value = msg.MaxSmacks; PluginConfig.Instance.MaxLaunchSpeed.Value = msg.MaxLaunchSpeed; PluginConfig.Instance.BodyBlacklist.Value = msg.BodyBlacklist; PluginConfig.Instance.RecoveryObjectBlacklist.Value = msg.RecoveryObjectBlacklist; PluginConfig.Instance.GrabbableComponentTypes.Value = msg.GrabbableComponentTypes; PluginConfig.Instance.GrabbableKeywordBlacklist.Value = msg.GrabbableKeywordBlacklist; PluginConfig.Instance.EnableObjectPersistence.Value = msg.EnableObjectPersistence; PluginConfig.Instance.EnableAutoGrab.Value = msg.EnableAutoGrab; PluginConfig.Instance.PersistBaggedBosses.Value = msg.PersistBaggedBosses; PluginConfig.Instance.PersistBaggedNPCs.Value = msg.PersistBaggedNPCs; PluginConfig.Instance.PersistBaggedEnvironmentObjects.Value = msg.PersistBaggedEnvironmentObjects; PluginConfig.Instance.PersistenceBlacklist.Value = msg.PersistenceBlacklist; PluginConfig.Instance.AutoGrabDelay.Value = msg.AutoGrabDelay; PluginConfig.Instance.BottomlessBagEnabled.Value = msg.BottomlessBagEnabled; PluginConfig.Instance.EnableStockRefreshClamping.Value = msg.EnableStockRefreshClamping; PluginConfig.Instance.EnableSuccessiveGrabStockRefresh.Value = msg.EnableSuccessiveGrabStockRefresh; PluginConfig.Instance.CycleCooldown.Value = msg.CycleCooldown; PluginConfig.Instance.EnableBalance.Value = msg.EnableBalance; PluginConfig.Instance.AoEDamageDistribution.Value = msg.AoEDamageDistribution; PluginConfig.Instance.BagScaleCap.Value = msg.BagScaleCap; PluginConfig.Instance.MassCap.Value = msg.MassCap; PluginConfig.Instance.StateCalculationMode.Value = msg.StateCalculationMode; PluginConfig.Instance.OverencumbranceMax.Value = msg.OverencumbranceMax; PluginConfig.Instance.SlotScalingFormula.Value = msg.SlotScalingFormula; PluginConfig.Instance.MassCapacityFormula.Value = msg.MassCapacityFormula; PluginConfig.Instance.MovespeedPenaltyFormula.Value = msg.MovespeedPenaltyFormula; PluginConfig.Instance.EliteFlagMultiplier.Value = msg.EliteFlagMultiplier; PluginConfig.Instance.BossFlagMultiplier.Value = msg.BossFlagMultiplier; PluginConfig.Instance.ChampionFlagMultiplier.Value = msg.ChampionFlagMultiplier; PluginConfig.Instance.PlayerFlagMultiplier.Value = msg.PlayerFlagMultiplier; PluginConfig.Instance.MinionFlagMultiplier.Value = msg.MinionFlagMultiplier; PluginConfig.Instance.DroneFlagMultiplier.Value = msg.DroneFlagMultiplier; PluginConfig.Instance.MechanicalFlagMultiplier.Value = msg.MechanicalFlagMultiplier; PluginConfig.Instance.VoidFlagMultiplier.Value = msg.VoidFlagMultiplier; PluginConfig.Instance.AllFlagMultiplier.Value = msg.AllFlagMultiplier; PluginConfig.InvalidateAllCaches(); GrabbableObjectPatches.EnsureAllGrabbableObjectsHaveSpecialObjectAttributes(); Log.Debug("[ConfigSyncHandler] Local config updated and scene objects re-scanned."); } [IteratorStateMachine(typeof(d__5))] private static IEnumerator DelayBroadcast() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__5(0); } } public static class CycleNetworkHandler { public static volatile bool SuppressBroadcasts; public static void SendClientPreferences(NetworkIdentity controllerIdentity, bool autoPromote, bool prioritize) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)NetworkManager.singleton) && NetworkManager.singleton.client != null) { ClientPreferencesMessage clientPreferencesMessage = new ClientPreferencesMessage { controllerNetId = controllerIdentity.netId, autoPromoteMainSeat = autoPromote, prioritizeMainSeat = prioritize }; NetworkManager.singleton.client.Send((short)209, (MessageBase)(object)clientPreferencesMessage); } } public static void SendCycleRequest(DrifterBagController bagController, int amount) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) NetworkIdentity component = ((Component)bagController).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { CyclePassengersMessage cyclePassengersMessage = new CyclePassengersMessage { bagControllerNetId = component.netId, amount = amount }; NetworkManager.singleton.client.Send((short)205, (MessageBase)(object)cyclePassengersMessage); } } public static void SendClientBagState(DrifterBagController bagController, int selectedIndex, uint[] baggedIds, uint[] seatIds) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) NetworkIdentity component = ((Component)bagController).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { ClientUpdateBagStateMessage clientUpdateBagStateMessage = new ClientUpdateBagStateMessage { controllerNetId = component.netId, selectedIndex = selectedIndex, baggedIds = baggedIds, seatIds = seatIds }; NetworkManager.singleton.client.Send((short)207, (MessageBase)(object)clientUpdateBagStateMessage); } } public static void SendGrabObjectRequest(DrifterBagController bagController, GameObject targetObject) { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) NetworkIdentity component = ((Component)bagController).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { NetworkIdentity component2 = targetObject.GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { GrabObjectMessage grabObjectMessage = new GrabObjectMessage { bagControllerNetId = component.netId, targetObjectNetId = component2.netId }; NetworkManager.singleton.client.Send((short)208, (MessageBase)(object)grabObjectMessage); } } } public static void SendBagStateUpdate(DrifterBagController bagController, NetworkInstanceId removedObjectNetId, bool isThrowOperation = false) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { return; } NetworkIdentity component = ((Component)bagController).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return; } BottomlessBagNetworkController component2 = ((Component)bagController).GetComponent(); if ((Object)(object)component2 == (Object)null) { return; } List baggedObjects = component2.GetBaggedObjects(); uint[] array = new uint[baggedObjects.Count]; uint[] array2 = new uint[baggedObjects.Count]; for (int i = 0; i < baggedObjects.Count; i++) { NetworkIdentity component3 = baggedObjects[i].GetComponent(); int num = i; int num2; NetworkInstanceId netId; if (!((Object)(object)component3 != (Object)null)) { num2 = 0; } else { netId = component3.netId; num2 = (int)((NetworkInstanceId)(ref netId)).Value; } array[num] = (uint)num2; int num3 = i; int num4; if (!((Object)(object)component3 != (Object)null)) { num4 = 0; } else { netId = component3.netId; num4 = (int)((NetworkInstanceId)(ref netId)).Value; } array2[num3] = (uint)num4; } float[] array3 = new float[baggedObjects.Count]; float[] array4 = new float[baggedObjects.Count]; float[] array5 = new float[baggedObjects.Count]; for (int j = 0; j < baggedObjects.Count; j++) { GameObject obj = baggedObjects[j]; BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(bagController, obj); if (baggedObjectStateData != null) { array3[j] = baggedObjectStateData.elapsedBreakoutTime; array4[j] = baggedObjectStateData.breakoutAttempts; array5[j] = baggedObjectStateData.breakoutTime; } } BagStateUpdatedMessage bagStateUpdatedMessage = new BagStateUpdatedMessage { controllerNetId = component.netId, selectedIndex = component2.selectedIndex, removedObjectNetId = removedObjectNetId, baggedIds = array, seatIds = array2, scrollDirection = 0, isThrowOperation = isThrowOperation, elapsedBreakoutTimes = array3, breakoutAttempts = array4, breakoutTimes = array5 }; NetworkServer.SendToAll((short)211, (MessageBase)(object)bagStateUpdatedMessage); Log.Debug(string.Format("[SendBagStateUpdate] Sent bag state update for {0} - selectedIndex={1}, isThrow={2}, removedObject={3}", ((Object)bagController).name, component2.selectedIndex, isThrowOperation, (removedObjectNetId == NetworkInstanceId.Invalid) ? "none" : ((NetworkInstanceId)(ref removedObjectNetId)).Value.ToString())); } [NetworkMessageHandler(msgType = 209, server = true, client = false)] public static void HandleClientPreferencesMessage(NetworkMessage netMsg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) ClientPreferencesMessage clientPreferencesMessage = netMsg.ReadMessage(); GameObject val = NetworkServer.FindLocalObject(clientPreferencesMessage.controllerNetId); if (Object.op_Implicit((Object)(object)val)) { BottomlessBagNetworkController component = val.GetComponent(); if (!((Object)(object)component == (Object)null)) { component.autoPromoteMainSeat = clientPreferencesMessage.autoPromoteMainSeat; component.prioritizeMainSeat = clientPreferencesMessage.prioritizeMainSeat; } } } [NetworkMessageHandler(msgType = 205, server = true, client = false)] public static void HandleCycleRequestMessage(NetworkMessage netMsg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) CyclePassengersMessage cyclePassengersMessage = netMsg.ReadMessage(); GameObject val = NetworkServer.FindLocalObject(cyclePassengersMessage.bagControllerNetId); if (Object.op_Implicit((Object)(object)val)) { DrifterBagController component = val.GetComponent(); if ((Object)(object)component != (Object)null) { Log.Debug($"[CycleNetworkHandler.HandleCycleRequestMessage] Processing request: Controller={((Object)component).name}, Amount={cyclePassengersMessage.amount}."); PassengerCycler.ServerCyclePassengers(component, cyclePassengersMessage.amount); } } } [NetworkMessageHandler(msgType = 207, server = true, client = false)] public static void HandleClientBagStateMessage(NetworkMessage netMsg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) ClientUpdateBagStateMessage clientUpdateBagStateMessage = netMsg.ReadMessage(); GameObject val = NetworkServer.FindLocalObject(clientUpdateBagStateMessage.controllerNetId); if (!Object.op_Implicit((Object)(object)val)) { return; } DrifterBagController component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return; } SuppressBroadcasts = true; try { uint[] baggedIds = clientUpdateBagStateMessage.baggedIds; foreach (uint num in baggedIds) { GameObject val2 = NetworkServer.FindLocalObject(new NetworkInstanceId(num)); if ((Object)(object)val2 != (Object)null && !IsObjectInAnySeat(component, val2)) { component.AssignPassenger(val2); } } BottomlessBagNetworkController component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.ServerUpdateFromClient(clientUpdateBagStateMessage.selectedIndex, clientUpdateBagStateMessage.baggedIds, clientUpdateBagStateMessage.seatIds); } } finally { SuppressBroadcasts = false; } } [NetworkMessageHandler(msgType = 208, server = true, client = false)] public static void HandleGrabObjectMessage(NetworkMessage netMsg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) GrabObjectMessage grabObjectMessage = netMsg.ReadMessage(); GameObject val = NetworkUtils.FindLocalObjectWithLogging(grabObjectMessage.bagControllerNetId, "HandleGrabObjectMessage"); if ((Object)(object)val == (Object)null) { return; } DrifterBagController component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Log.Warning("[HandleGrabObjectMessage] " + ((Object)val).name + " does not have DrifterBagController component"); return; } GameObject val2 = NetworkUtils.FindLocalObjectWithLogging(grabObjectMessage.targetObjectNetId, "HandleGrabObjectMessage"); if ((Object)(object)val2 == (Object)null) { return; } if (!NetworkUtils.ValidateObjectReady(val2)) { Log.Error("[HandleGrabObjectMessage] Target object " + ((Object)val2).name + " is not ready for network operations"); return; } NetworkUtils.LogNetworkOperation("HandleGrabObjectMessage", val2, isServer: true, new Dictionary { { "bagController", ((Object)component).name }, { "bagControllerNetId", ((NetworkInstanceId)(ref grabObjectMessage.bagControllerNetId)).Value }, { "targetObjectNetId", ((NetworkInstanceId)(ref grabObjectMessage.targetObjectNetId)).Value } }); if (IsObjectInAnySeat(component, val2)) { Log.Debug("[HandleGrabObjectMessage] " + ((Object)val2).name + " is already in a seat, skipping grab"); } else if (ProjectileRecoveryPatches.IsUndergoingThrowOperation(val2)) { Log.Warning("[HandleGrabObjectMessage] Blocking grab request for " + ((Object)val2).name + " - object is currently undergoing throw operation"); } else { component.AssignPassenger(val2); } } [NetworkMessageHandler(msgType = 211, server = false, client = true)] public static void HandleBagStateUpdatedMessage(NetworkMessage netMsg) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) BagStateUpdatedMessage bagStateUpdatedMessage = netMsg.ReadMessage(); GameObject val = ClientScene.FindLocalObject(bagStateUpdatedMessage.controllerNetId); if ((Object)(object)val == (Object)null) { Log.Debug($"[HandleBagStateUpdatedMessage] Controller (netId={((NetworkInstanceId)(ref bagStateUpdatedMessage.controllerNetId)).Value}) not found - likely destroyed"); return; } DrifterBagController component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Log.Warning("[HandleBagStateUpdatedMessage] " + ((Object)val).name + " does not have DrifterBagController component"); return; } BottomlessBagNetworkController component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null) { Log.Warning("[HandleBagStateUpdatedMessage] " + ((Object)component).name + " does not have BottomlessBagNetworkController component"); return; } NetworkUtils.LogNetworkOperation("HandleBagStateUpdatedMessage", val, isServer: false, new Dictionary { { "selectedIndex", bagStateUpdatedMessage.selectedIndex }, { "isThrowOperation", bagStateUpdatedMessage.isThrowOperation }, { "removedObjectNetId", ((NetworkInstanceId)(ref bagStateUpdatedMessage.removedObjectNetId)).Value }, { "baggedCount", bagStateUpdatedMessage.baggedIds.Length } }); component2.ApplyStateFromMessage(bagStateUpdatedMessage.selectedIndex, bagStateUpdatedMessage.baggedIds, bagStateUpdatedMessage.seatIds, bagStateUpdatedMessage.scrollDirection, bagStateUpdatedMessage.elapsedBreakoutTimes, bagStateUpdatedMessage.breakoutAttempts, bagStateUpdatedMessage.breakoutTimes); if (bagStateUpdatedMessage.removedObjectNetId != NetworkInstanceId.Invalid) { GameObject val2 = ClientScene.FindLocalObject(bagStateUpdatedMessage.removedObjectNetId); if ((Object)(object)val2 != (Object)null) { Log.Debug("[HandleBagStateUpdatedMessage] Cleaning up removed object " + ((Object)val2).name); NetworkUtils.InvalidateReadyCache(val2); PersistenceObjectsTracker.UntrackBaggedObject(val2); if (!bagStateUpdatedMessage.isThrowOperation || !NetworkServer.active) { BaggedObjectStatePatches.PerformPassengerRestoration(component, val2); BagPassengerManager.RemoveBaggedObject(component, val2); } } else { Log.Debug($"[HandleBagStateUpdatedMessage] Removed object (netId={((NetworkInstanceId)(ref bagStateUpdatedMessage.removedObjectNetId)).Value}) not found - likely destroyed/already thrown"); } } BagCarouselUpdater.UpdateCarousel(component); Log.Debug($"[HandleBagStateUpdatedMessage] About to sync bag state for {((Object)component).name} - baggedCount={bagStateUpdatedMessage.baggedIds.Length}, selectedIndex={bagStateUpdatedMessage.selectedIndex}, isThrow={bagStateUpdatedMessage.isThrowOperation}"); BagState state = BagPatches.GetState(component); if (state != null) { state.BaggedObjects.Clear(); uint[] baggedIds = bagStateUpdatedMessage.baggedIds; foreach (uint num in baggedIds) { GameObject val3 = ClientScene.FindLocalObject(new NetworkInstanceId(num)); if ((Object)(object)val3 != (Object)null) { state.BaggedObjects.Add(val3); BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(component, val3); if (baggedObjectStateData == null && bagStateUpdatedMessage.isThrowOperation) { BaggedObjectPatches.RestorePreservedState(component, val3); } } else { Log.Warning($"[HandleBagStateUpdatedMessage] Could not find object for netId={num}, skipping"); } } BaggedObjectPatches.ClearAllTemporaryPreservation(component); } Log.Debug($"[HandleBagStateUpdatedMessage] Bag state updated for {((Object)component).name} - new selectedIndex={component2.selectedIndex}"); } private static bool IsObjectInAnySeat(DrifterBagController controller, GameObject obj) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return false; } if ((Object)(object)controller.vehicleSeat != (Object)null && controller.vehicleSeat.hasPassenger && (Object)(object)controller.vehicleSeat.NetworkpassengerBodyObject == (Object)(object)obj) { return true; } ConcurrentDictionary additionalSeats = BagPatches.GetState(controller).AdditionalSeats; if (additionalSeats != null) { foreach (KeyValuePair item in additionalSeats) { if ((Object)(object)item.Value != (Object)null && item.Value.hasPassenger && (Object)(object)item.Value.NetworkpassengerBodyObject == (Object)(object)obj) { return true; } } } VehicleSeat[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val in array) { if ((Object)(object)val != (Object)(object)controller.vehicleSeat && val.hasPassenger && (Object)(object)val.NetworkpassengerBodyObject == (Object)(object)obj) { return true; } } return false; } } public static class NetworkMessageRegistry { private class HandlerInfo { public short msgType; public NetworkMessageDelegate handlerDelegate; } private static readonly List _clientHandlers = new List(); private static readonly List _serverHandlers = new List(); public static void Initialize() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Expected O, but got Unknown _clientHandlers.Clear(); _serverHandlers.Clear(); try { Type[] array; try { array = Assembly.GetExecutingAssembly().GetTypes(); } catch (ReflectionTypeLoadException ex) { array = ex.Types.Where((Type t) => t != null).ToArray(); Log.Warning(string.Format("[NetworkMessageRegistry] Some types failed to load (soft dependency missing?). Loaded {0} types. Loader exceptions: {1}", array.Length, string.Join(", ", ex.LoaderExceptions.Select((Exception e) => e?.Message ?? "null")))); } IEnumerable enumerable = array.SelectMany(delegate(Type t) { try { return t.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } catch (Exception) { return Array.Empty(); } }).Where(delegate(MethodInfo m) { try { return ((MemberInfo)m).GetCustomAttribute() != null; } catch (Exception) { return false; } }); foreach (MethodInfo item2 in enumerable) { NetworkMessageHandlerAttribute customAttribute = ((MemberInfo)item2).GetCustomAttribute(); if (customAttribute != null) { NetworkMessageDelegate handlerDelegate = (NetworkMessageDelegate)Delegate.CreateDelegate(typeof(NetworkMessageDelegate), item2); HandlerInfo item = new HandlerInfo { msgType = customAttribute.msgType, handlerDelegate = handlerDelegate }; if (customAttribute.client) { _clientHandlers.Add(item); } if (customAttribute.server) { _serverHandlers.Add(item); } } } } catch (Exception arg) { Log.Error($"[NetworkMessageRegistry] Failed to scan NetworkMessageHandler attributes: {arg}"); } Log.Debug($"[NetworkMessageRegistry] Found {_clientHandlers.Count} client handlers and {_serverHandlers.Count} server handlers."); NetworkManagerSystem.onStartClientGlobal += OnStartClientGlobal; NetworkManagerSystem.onStartServerGlobal += OnStartServerGlobal; } private static void OnStartClientGlobal(NetworkClient client) { foreach (HandlerInfo clientHandler in _clientHandlers) { client.RegisterHandler(clientHandler.msgType, clientHandler.handlerDelegate); Log.Debug($"[NetworkMessageRegistry] Client Registered MsgId {clientHandler.msgType} on {client.connection?.connectionId}"); } } private static void OnStartServerGlobal() { foreach (HandlerInfo serverHandler in _serverHandlers) { NetworkServer.RegisterHandler(serverHandler.msgType, serverHandler.handlerDelegate); Log.Debug($"[NetworkMessageRegistry] Server Registered MsgId {serverHandler.msgType}"); } } public static void Cleanup() { NetworkManagerSystem.onStartClientGlobal -= OnStartClientGlobal; NetworkManagerSystem.onStartServerGlobal -= OnStartServerGlobal; _clientHandlers.Clear(); _serverHandlers.Clear(); Log.Debug("[NetworkMessageRegistry] Cleanup called."); } } public static class NetworkUtils { private const int DefaultMaxRetries = 3; private const float DefaultRetryDelay = 0.1f; private const float MaxRetryDelay = 0.5f; private static readonly Dictionary _readyObjectCache = new Dictionary(); private static readonly object _readyObjectCacheLock = new object(); private const float CacheValidityDuration = 5f; public static GameObject? FindLocalObjectWithLogging(NetworkInstanceId netId, string operation, bool isServer = true) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) GameObject val = NetworkServer.FindLocalObject(netId); if ((Object)(object)val != (Object)null) { Log.Debug(string.Format("[NetworkUtils.{0}] Successfully found {1} (netId={2}) on {3}", operation, ((Object)val).name, ((NetworkInstanceId)(ref netId)).Value, isServer ? "server" : "client")); return val; } Log.Error(string.Format("[NetworkUtils.{0}] Failed to find object (netId={1}) on {2}", operation, ((NetworkInstanceId)(ref netId)).Value, isServer ? "server" : "client")); if (netId != NetworkInstanceId.Invalid) { bool flag = false; try { FieldInfo field = typeof(NetworkServer).GetField("s_Spawned", BindingFlags.Static | BindingFlags.NonPublic); if (field != null) { flag = field.GetValue(null) is Dictionary dictionary && dictionary.ContainsKey(netId); } } catch (Exception ex) { Log.Warning("[NetworkUtils." + operation + "] Could not check server lookup: " + ex.Message); } if (flag) { Log.Error("[NetworkUtils." + operation + "] NetworkInstanceId exists in server lookup but FindLocalObject returned null - object may be destroyed/inactive"); } else { Log.Error("[NetworkUtils." + operation + "] NetworkInstanceId not found in server lookup - object may not be spawned yet or was destroyed"); } } return null; } public static bool ValidateObjectReady(GameObject? obj) { //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { Log.Warning("[NetworkUtils.ValidateObjectReady] GameObject is null"); return false; } if (!obj.activeInHierarchy) { Log.Warning("[NetworkUtils.ValidateObjectReady] " + ((Object)obj).name + " is not active in hierarchy"); return false; } NetworkIdentity component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { Log.Warning("[NetworkUtils.ValidateObjectReady] " + ((Object)obj).name + " does not have NetworkIdentity component"); return false; } NetworkInstanceId netId; lock (_readyObjectCacheLock) { Dictionary readyObjectCache = _readyObjectCache; netId = component.netId; if (readyObjectCache.TryGetValue(((NetworkInstanceId)(ref netId)).Value, out var value) && Time.time - value < 5f) { return true; } } if (!((Behaviour)component).isActiveAndEnabled) { Log.Warning("[NetworkUtils.ValidateObjectReady] " + ((Object)obj).name + " NetworkIdentity is not active/enabled"); return false; } if ((Object)(object)obj == (Object)null) { Log.Warning("[NetworkUtils.ValidateObjectReady] Object is being destroyed"); return false; } lock (_readyObjectCacheLock) { Dictionary readyObjectCache2 = _readyObjectCache; netId = component.netId; readyObjectCache2[((NetworkInstanceId)(ref netId)).Value] = Time.time; } return true; } public static bool TryEnsureNetworkIdentityActive(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } NetworkIdentity component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (!obj.activeInHierarchy) { obj.SetActive(true); if (!obj.activeInHierarchy) { return false; } } if (((Behaviour)component).isActiveAndEnabled) { return true; } try { ((Behaviour)component).enabled = true; } catch (Exception ex) { Log.Warning("[NetworkUtils.TryEnsureNetworkIdentityActive] Failed to set enabled on " + ((Object)obj).name + ": " + ex.Message); return false; } if (!((Behaviour)component).isActiveAndEnabled) { Log.Warning("[NetworkUtils.TryEnsureNetworkIdentityActive] NetworkIdentity still not active after enable for " + ((Object)obj).name); return false; } InvalidateReadyCache(obj); Log.Debug("[NetworkUtils.TryEnsureNetworkIdentityActive] Successfully re-enabled NetworkIdentity for " + ((Object)obj).name); return true; } public static bool ValidateObjectReadyWithRecovery(GameObject? obj) { if (ValidateObjectReady(obj)) { return true; } if ((Object)(object)obj == (Object)null) { return false; } NetworkIdentity component = obj.GetComponent(); if ((Object)(object)component != (Object)null && !((Behaviour)component).isActiveAndEnabled && TryEnsureNetworkIdentityActive(obj)) { return ValidateObjectReady(obj); } return false; } public static bool IsNetworkIdentityInactive(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } NetworkIdentity component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { return !((Behaviour)component).isActiveAndEnabled; } return false; } public static void InvalidateReadyCache(GameObject? obj) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return; } NetworkIdentity component = obj.GetComponent(); if (!((Object)(object)component != (Object)null)) { return; } lock (_readyObjectCacheLock) { Dictionary readyObjectCache = _readyObjectCache; NetworkInstanceId netId = component.netId; readyObjectCache.Remove(((NetworkInstanceId)(ref netId)).Value); } } public static void LogObjectDetails(GameObject? obj, string context) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { Log.Warning("[NetworkUtils.LogObjectDetails] " + context + " - GameObject is null"); return; } NetworkIdentity component = obj.GetComponent(); Log.Debug("[NetworkUtils.LogObjectDetails] " + context + ":"); Log.Debug(" Name: " + ((Object)obj).name); Log.Debug($" activeInHierarchy: {obj.activeInHierarchy}"); object obj2; if (!((Object)(object)component != (Object)null)) { obj2 = "null"; } else { NetworkInstanceId netId = component.netId; obj2 = $"netId={((NetworkInstanceId)(ref netId)).Value}"; } Log.Debug(" NetworkIdentity: " + (string?)obj2); Log.Debug($" NetworkIdentity.isActiveAndEnabled: {(Object)(object)component != (Object)null && ((Behaviour)component).isActiveAndEnabled}"); Log.Debug($" InstanceID: {((Object)obj).GetInstanceID()}"); Log.Debug($" Transform.position: {obj.transform.position}"); Log.Debug(" Parent: " + (((Object)(object)obj.transform.parent != (Object)null) ? ((Object)obj.transform.parent).name : "null")); } public static string GetSafeObjectName(GameObject? obj) { if ((Object)(object)obj == (Object)null) { return "null"; } try { return (!Object.op_Implicit((Object)(object)obj)) ? "destroyed" : ((Object)obj).name; } catch { return "error"; } } public static void LogNetworkOperation(string operation, GameObject? obj, bool isServer, Dictionary? additionalContext = null) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append("[NetworkUtils." + operation + "] " + (isServer ? "SERVER" : "CLIENT")); if ((Object)(object)obj != (Object)null) { NetworkIdentity component = obj.GetComponent(); stringBuilder.Append(" | Object: " + GetSafeObjectName(obj)); object obj2; if (!((Object)(object)component != (Object)null)) { obj2 = "none"; } else { NetworkInstanceId netId = component.netId; obj2 = ((NetworkInstanceId)(ref netId)).Value.ToString(); } stringBuilder.Append(" | netId: " + (string?)obj2); stringBuilder.Append($" | activeInHierarchy: {obj.activeInHierarchy}"); } if (additionalContext != null) { foreach (KeyValuePair item in additionalContext) { stringBuilder.Append($" | {item.Key}: {item.Value}"); } } Log.Debug(stringBuilder.ToString()); } public static string GetPlayerIdString(NetworkUserId id) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) if (id.strValue != null) { return id.strValue; } return $"{id.value}_{id.subId}"; } } } namespace DrifterBossGrabMod.Features { public class UncappedBagScaleComponent : MonoBehaviour { private DrifterBagController? _bagController; private SkinnedMeshRenderer? _skinnedMeshRenderer; private Transform[]? _bones; private Transform[]? _filteredBones; private Vector3[]? _originalBoneScales; private float _targetScale = 1f; private float _currentScale = 1f; private bool _isInitialized; public bool IsInitialized => _isInitialized; public float TargetScale { get { return _targetScale; } set { _targetScale = Mathf.Max(value, 1f); } } public void Initialize(DrifterBagController bagController) { if (_isInitialized) { Log.Debug("[UncappedBagScaleComponent] Already initialized, skipping duplicate initialization"); return; } if ((Object)(object)bagController == (Object)null) { Log.Error("[UncappedBagScaleComponent] Cannot initialize with null bag controller"); return; } _bagController = bagController; FindMeshBagTransform(); if ((Object)(object)_skinnedMeshRenderer != (Object)null && _bones != null) { FilterAndCacheBagBones(); _isInitialized = true; Transform[]? filteredBones = _filteredBones; Log.Debug("[UncappedBagScaleComponent] Successfully initialized with " + ((filteredBones != null) ? filteredBones.Length : 0) + " bag bones"); } else { Log.Error("[UncappedBagScaleComponent] Failed to initialize - SkinnedMeshRenderer or bones not found"); _isInitialized = false; } } private void FindMeshBagTransform() { Transform val = null; CharacterBody val2 = (((Object)(object)_bagController != (Object)null) ? ((Component)_bagController).GetComponent() : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.modelLocator != (Object)null) { Transform modelTransform = val2.modelLocator.modelTransform; if ((Object)(object)modelTransform != (Object)null) { val = modelTransform.Find("meshBag"); if ((Object)(object)val != (Object)null) { Log.Debug("[UncappedBagScaleComponent] Found meshBag via modelLocator: " + ((Object)modelTransform).name + ">meshBag"); } } } if ((Object)(object)val != (Object)null) { _skinnedMeshRenderer = ((Component)val).GetComponent(); _bones = _skinnedMeshRenderer.bones; } } private void FilterAndCacheBagBones() { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) if (_bones == null || (Object)(object)_skinnedMeshRenderer == (Object)null) { return; } string[] keywords = new string[16] { "bagMaster_l", "bag04_l", "bagBulk_l", "bagBulk_l_end", "bagBulgeBt_l", "bagBulgeRt_l", "bagBulgeRt_l_end", "bagBulgeLf_l", "bagBulgeLf_l_end", "bagPocketRt_l", "bagPocketRt_l_end", "bagPocketLf_l", "bagPocketLf_l_end", "bagFlap1_l", "bagFlap2_l", "bagFlap3_l" }; int num = 0; for (int i = 0; i < _bones.Length; i++) { if ((Object)(object)_bones[i] != (Object)null && ShouldScaleBone(((Object)_bones[i]).name, keywords)) { num++; } } Log.Debug($"[UncappedBagScaleComponent] Found {num} bones matching scale keywords out of {_bones.Length} total bones"); _filteredBones = (Transform[]?)(object)new Transform[num]; _originalBoneScales = (Vector3[]?)(object)new Vector3[num]; int num2 = 0; for (int j = 0; j < _bones.Length; j++) { if ((Object)(object)_bones[j] != (Object)null && ShouldScaleBone(((Object)_bones[j]).name, keywords)) { _filteredBones[num2] = _bones[j]; _originalBoneScales[num2] = _bones[j].localScale; Log.Debug($"[UncappedBagScaleComponent] Filtered bone [{num2}]: {((Object)_bones[j]).name}"); num2++; } } } private bool ShouldScaleBone(string boneName, string[] keywords) { string text = boneName.ToLower(); foreach (string text2 in keywords) { if (text == text2.ToLower()) { return true; } } return false; } public void UpdateScaleFromMass(float mass) { if (!_isInitialized) { Log.Warning("[UncappedBagScaleComponent] UpdateScaleFromMass called but component is not initialized"); return; } if (_filteredBones == null) { Log.Warning("[UncappedBagScaleComponent] UpdateScaleFromMass called but filtered bones are null"); return; } DrifterBagController component = ((Component)this).GetComponent(); float num = (((Object)(object)component != (Object)null) ? CapacityScalingSystem.CalculateMassCapacity(component) : DrifterBagController.maxMass); if (mass <= num) { TargetScale = 1f; Log.Debug($"[UncappedBagScaleComponent] Mass {mass} <= maxCapacity {num}, using original animation system"); return; } float num2 = Mathf.Max(mass, 1f); float num3 = (num2 - 1f) / (num - 1f); float num4 = 1f + num3; if (!PluginConfig.Instance.IsBagScaleCapInfinite) { num4 = Mathf.Min(num4, PluginConfig.Instance.ParsedBagScaleCap); } TargetScale = num4; Log.Debug($"[UncappedBagScaleComponent] Mass {mass} > maxCapacity {num}, calculated scale {num4:F2} (t={num3:F2})"); } private void LateUpdate() { //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (!_isInitialized || _filteredBones == null || _originalBoneScales == null) { return; } if (_targetScale <= 1f) { if (_currentScale <= 1f) { return; } _currentScale = Mathf.Lerp(_currentScale, 1f, Time.deltaTime * 10f); if (Mathf.Approximately(_currentScale, 1f)) { _currentScale = 1f; ResetBoneScales(); return; } for (int i = 0; i < _filteredBones.Length; i++) { if ((Object)(object)_filteredBones[i] != (Object)null) { _filteredBones[i].localScale = _originalBoneScales[i] * _currentScale; } } } else { if (Mathf.Approximately(_currentScale, _targetScale)) { return; } _currentScale = Mathf.Lerp(_currentScale, _targetScale, Time.deltaTime * 10f); int num = 0; for (int j = 0; j < _filteredBones.Length; j++) { if ((Object)(object)_filteredBones[j] != (Object)null) { Vector3 localScale = _originalBoneScales[j] * _currentScale; _filteredBones[j].localScale = localScale; num++; } } if (num > 0) { Log.Debug($"[UncappedBagScaleComponent] Applied scale {_currentScale:F2} (target: {_targetScale:F2}) to {num} bag bones"); } } } private void OnDestroy() { ResetBoneScales(); _isInitialized = false; } public void ResetBoneScales() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (_filteredBones == null || _originalBoneScales == null) { return; } for (int i = 0; i < _filteredBones.Length; i++) { if ((Object)(object)_filteredBones[i] != (Object)null) { _filteredBones[i].localScale = _originalBoneScales[i]; } } _currentScale = 1f; _targetScale = 1f; Log.Debug($"[UncappedBagScaleComponent] Reset {_filteredBones.Length} bag bones to original scales"); } } } namespace DrifterBossGrabMod.UI { public class DamagePreviewOverlay : MonoBehaviour, IConfigObserver { public GameObject? targetObject; public DrifterBagController? bagController; private HealthBar? _healthBar; private Image? _previewImage; private RectTransform? _previewRect; private bool _initialized; private bool _eventHandlersRegistered; private float _logTimer; private const float LogInterval = 1f; private float _cachedDamageFraction; private int _cachedTargetInstanceId; private bool _cacheValid; private void OnEnable() { ConfigChangeNotifier.AddObserver(this); } private void OnDisable() { ConfigChangeNotifier.RemoveObserver(this); UnregisterEventHandlers(); } public void OnConfigChanged(string key, object value) { if (key == "DamagePreviewColor") { UpdateColor(); } } private void Awake() { _healthBar = ((Component)this).GetComponent(); } private void LateUpdate() { if (!PluginConfig.Instance.EnableDamagePreview.Value) { if (Object.op_Implicit((Object)(object)_previewRect) && ((Component)_previewRect).gameObject.activeSelf) { ((Component)_previewRect).gameObject.SetActive(false); } return; } if (!Object.op_Implicit((Object)(object)_healthBar) || !Object.op_Implicit((Object)(object)bagController) || !Object.op_Implicit((Object)(object)targetObject) || ((Object)targetObject).name.Contains("EmptySlotMarker")) { if (Object.op_Implicit((Object)(object)_previewRect) && ((Component)_previewRect).gameObject.activeSelf) { ((Component)_previewRect).gameObject.SetActive(false); } return; } if (!_initialized) { CreatePreviewBar(); _initialized = true; } if (!Object.op_Implicit((Object)(object)_previewImage)) { return; } if (!((Component)_previewRect).gameObject.activeSelf) { ((Component)_previewRect).gameObject.SetActive(true); } UpdatePreviewBar(); if (PluginConfig.Instance.EnableDebugLogs.Value) { _logTimer += Time.deltaTime; if (_logTimer >= 1f) { _logTimer = 0f; SlamDamageCalculator.LogDetails(bagController, targetObject); } } } private void CreatePreviewBar() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_healthBar)) { return; } RectTransform barContainer = _healthBar.barContainer; if (!Object.op_Implicit((Object)(object)barContainer)) { Log.Warning("[DamagePreviewOverlay] HealthBar.barContainer is null"); return; } GameObject val = _healthBar.style?.barPrefab; if ((Object)(object)val == (Object)null) { throw new InvalidOperationException("HealthBar.style.barPrefab is null - cannot create damage preview"); } GameObject val2 = Object.Instantiate(val, (Transform)(object)barContainer); ((Object)val2).name = "DamagePreview"; Log.Debug("[DamagePreviewOverlay] Created damage preview inside barContainer"); _previewRect = val2.GetComponent(); if (!Object.op_Implicit((Object)(object)_previewRect)) { _previewRect = val2.AddComponent(); } _previewImage = val2.GetComponent(); if (!Object.op_Implicit((Object)(object)_previewImage)) { _previewImage = val2.AddComponent(); } ((Graphic)_previewImage).color = PluginConfig.Instance.DamagePreviewColor.Value; ((Graphic)_previewImage).raycastTarget = false; } private void UpdatePreviewBar() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) int num = (Object.op_Implicit((Object)(object)targetObject) ? ((Object)targetObject).GetInstanceID() : 0); bool flag = num != _cachedTargetInstanceId; if (!_cacheValid || flag) { _cachedDamageFraction = SlamDamageCalculator.GetPredictedDamageFraction(bagController, targetObject); _cachedTargetInstanceId = num; _cacheValid = true; } float cachedDamageFraction = _cachedDamageFraction; float currentHealthFraction = GetCurrentHealthFraction(); if (cachedDamageFraction <= 0f) { if ((Object)(object)_previewImage != (Object)null) { ((Behaviour)_previewImage).enabled = false; } return; } if ((Object)(object)_previewImage != (Object)null) { ((Behaviour)_previewImage).enabled = true; ((Graphic)_previewImage).color = PluginConfig.Instance.DamagePreviewColor.Value; } float num2 = Mathf.Max(0f, currentHealthFraction - cachedDamageFraction); float num3 = currentHealthFraction; if ((Object)(object)_previewRect != (Object)null) { _previewRect.anchorMin = new Vector2(num2, 0f); _previewRect.anchorMax = new Vector2(num3, 1f); _previewRect.anchoredPosition = Vector2.zero; _previewRect.offsetMin = new Vector2(-0.5f, -0.5f); _previewRect.offsetMax = new Vector2(0.5f, 0.5f); } RectTransform val = _healthBar?.barContainer; if ((Object)(object)_previewRect != (Object)null && (Object)(object)val != (Object)null && ((Component)_previewRect).transform.GetSiblingIndex() < ((Transform)val).childCount - 1) { ((Transform)_previewRect).SetAsLastSibling(); } } private float GetCurrentHealthFraction() { if ((Object)(object)_healthBar != (Object)null && (Object)(object)_healthBar.source != (Object)null) { float fullCombinedHealth = _healthBar.source.fullCombinedHealth; if (fullCombinedHealth <= 0f) { return 0f; } return Mathf.Clamp01(_healthBar.source.combinedHealth / fullCombinedHealth); } if ((Object)(object)_healthBar != (Object)null && Object.op_Implicit((Object)(object)_healthBar.altSource)) { if (_healthBar.altSource.maxDurability <= 0) { return 0f; } return Mathf.Clamp01((float)_healthBar.altSource.durability / (float)_healthBar.altSource.maxDurability); } return 0f; } public void UpdateColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_previewImage)) { ((Graphic)_previewImage).color = PluginConfig.Instance.DamagePreviewColor.Value; } } public void SetTarget(GameObject? target, DrifterBagController? controller) { UnregisterEventHandlers(); targetObject = target; bagController = controller; InvalidateCache(); RegisterEventHandlers(); } public void InvalidateCache() { _cacheValid = false; } private void RegisterEventHandlers() { if (!_eventHandlersRegistered && !((Object)(object)bagController == (Object)null)) { DrifterBagAPI.OnMassRecalculated += OnMassRecalculated; _eventHandlersRegistered = true; } } private void UnregisterEventHandlers() { if (_eventHandlersRegistered) { DrifterBagAPI.OnMassRecalculated -= OnMassRecalculated; _eventHandlersRegistered = false; } } private void OnMassRecalculated(DrifterBagController controller, float totalMass, float previousTotalMass) { if ((Object)(object)controller == (Object)(object)bagController) { InvalidateCache(); } } public static void InvalidateAllCaches() { DamagePreviewOverlay[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DamagePreviewOverlay[] array2 = array; foreach (DamagePreviewOverlay damagePreviewOverlay in array2) { damagePreviewOverlay.InvalidateCache(); } } private void OnDestroy() { UnregisterEventHandlers(); if (Object.op_Implicit((Object)(object)_previewRect)) { Object.Destroy((Object)(object)((Component)_previewRect).gameObject); } } } public class MassCapacityUIController : MonoBehaviour, IConfigObserver { [CompilerGenerated] private sealed class d__19 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public MassCapacityUIController <>4__this; private AsyncOperationHandle 5__2; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__19(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) 5__2 = default(AsyncOperationHandle); <>1__state = -2; } private bool MoveNext() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Invalid comparison between Unknown and I4 //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; MassCapacityUIController massCapacityUIController = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = Addressables.LoadAssetAsync((object)"RoR2/DLC3/Drifter/Junk UI.prefab"); <>2__current = 5__2; <>1__state = 1; return true; case 1: <>1__state = -1; if ((int)5__2.Status == 1) { GameObject result = 5__2.Result; if ((Object)(object)result != (Object)null) { massCapacityUIController.InstantiateCapacityUI(result); } else { Log.Error("[CapacityUI] Failed to load Capacity UI prefab: prefab is null"); } } else { Log.Error($"[CapacityUI] Failed to load Capacity UI prefab: {5__2.Status}"); } Addressables.Release(5__2); 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 GameObject? _massCapacityUIInstance; private DrifterBagController? _bagController; private RectTransform? _massCapacityUIRectTransform; private HGTextMeshProUGUI? _percentageText; private Image? _fillBarImage; private Image? _overencumbranceFillImage; private CapacityUIGradient? _gradientEffect; private OverencumbranceUIGradient? _overencumbranceGradientEffect; private GameObject? _separatorTemplate; private List _separatorObjects = new List(); private float _currentCapacity; private float _currentUsedCapacity; private const float ShowUIThreshold = 1f; public float CurrentCapacity => _currentCapacity; public float CurrentUsedCapacity => _currentUsedCapacity; private void OnEnable() { ConfigChangeNotifier.AddObserver(this); } private void OnDisable() { ConfigChangeNotifier.RemoveObserver(this); } public void OnConfigChanged(string key, object value) { UpdateConfig(); UpdateCapacityUI(); } private void Start() { DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { if (((NetworkBehaviour)val).hasAuthority) { _bagController = val; break; } } if ((Object)(object)_bagController == (Object)null) { ((Behaviour)this).enabled = false; } else { InitializeCapacityUI(); } } private void InitializeCapacityUI() { if (!((Object)(object)_massCapacityUIInstance != (Object)null)) { LoadCapacityUIPrefab(); } } private void LoadCapacityUIPrefab() { ((MonoBehaviour)this).StartCoroutine(LoadCapacityUIPrefabCoroutine()); } [IteratorStateMachine(typeof(d__19))] private IEnumerator LoadCapacityUIPrefabCoroutine() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__19(0) { <>4__this = this }; } private void InstantiateCapacityUI(GameObject prefab) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) HUD val = Object.FindFirstObjectByType(); if ((Object)(object)val == (Object)null) { Log.Error("[CapacityUI] Failed to find HUD canvas"); return; } Transform val2 = null; Transform transform = val.mainContainer.transform; if ((Object)(object)transform != (Object)null) { Transform val3 = transform.Find("MainRect"); if ((Object)(object)val3 != (Object)null) { Transform val4 = val3.Find("BottomCenterCluster"); val2 = val4 ?? val3; } else { val2 = transform; } } _massCapacityUIInstance = Object.Instantiate(prefab, val2); ((Object)_massCapacityUIInstance).name = "CapacityUI"; _massCapacityUIRectTransform = _massCapacityUIInstance.GetComponent(); FindUIElements(); UpdateConfig(); UpdateCapacityUI(); if ((Object)(object)_massCapacityUIInstance != (Object)null) { HudDraggable hudDraggable = _massCapacityUIInstance.AddComponent(); hudDraggable.ElementType = HudElementType.CapacityUI; hudDraggable.DragSizePadding = new Vector2(-215f, -150f); hudDraggable.DragOffset = new Vector2(-140f, 0f); hudDraggable.XConfig = PluginConfig.Instance.MassCapacityUIPositionX; hudDraggable.YConfig = PluginConfig.Instance.MassCapacityUIPositionY; hudDraggable.ScaleConfig = PluginConfig.Instance.MassCapacityUIScale; } } private void FindUIElements() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_massCapacityUIInstance == (Object)null) { Log.Error("[CapacityUI] Cannot find UI elements: instance is null"); return; } _percentageText = _massCapacityUIInstance.GetComponentInChildren(); Image[] componentsInChildren = _massCapacityUIInstance.GetComponentsInChildren(); Image[] array = componentsInChildren; foreach (Image val in array) { if ((int)val.type == 3 && (int)val.fillMethod == 0) { _fillBarImage = val; break; } } if ((Object)(object)_fillBarImage != (Object)null) { ((Graphic)_fillBarImage).color = PluginConfig.Instance.CapacityGradientColorMid.Value; _gradientEffect = ((Component)_fillBarImage).gameObject.AddComponent(); Transform parent = ((Component)_fillBarImage).transform.parent; if ((Object)(object)parent != (Object)null) { for (int num = parent.childCount - 1; num >= 0; num--) { Transform child = parent.GetChild(num); if (((Object)child).name.StartsWith("Threshold")) { if ((Object)(object)_separatorTemplate == (Object)null) { ((Object)((Component)child).gameObject).name = "SeparatorTemplate"; ((Component)child).gameObject.SetActive(false); _separatorTemplate = ((Component)child).gameObject; } else { Object.Destroy((Object)(object)((Component)child).gameObject); } } } } } CreateOverencumbranceFillImage(); } private void CreateOverencumbranceFillImage() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fillBarImage == (Object)null) { return; } Transform parent = ((Component)_fillBarImage).transform.parent; if (!((Object)(object)parent == (Object)null)) { GameObject val = new GameObject("OverencumbranceFillImage"); val.transform.SetParent(parent, false); val.transform.localPosition = ((Component)_fillBarImage).transform.localPosition; val.transform.localRotation = ((Component)_fillBarImage).transform.localRotation; val.transform.localScale = ((Component)_fillBarImage).transform.localScale; Transform transform = ((Component)_fillBarImage).transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 != (Object)null) { RectTransform val3 = val.AddComponent(); val3.anchorMin = val2.anchorMin; val3.anchorMax = val2.anchorMax; val3.pivot = val2.pivot; val3.sizeDelta = val2.sizeDelta; val3.anchoredPosition = val2.anchoredPosition; } _overencumbranceFillImage = val.AddComponent(); _overencumbranceFillImage.type = (Type)3; _overencumbranceFillImage.fillMethod = _fillBarImage.fillMethod; _overencumbranceFillImage.fillOrigin = _fillBarImage.fillOrigin; _overencumbranceFillImage.fillClockwise = _fillBarImage.fillClockwise; _overencumbranceFillImage.fillAmount = 0f; _overencumbranceFillImage.preserveAspect = true; _overencumbranceFillImage.useSpriteMesh = _fillBarImage.useSpriteMesh; _overencumbranceFillImage.pixelsPerUnitMultiplier = _fillBarImage.pixelsPerUnitMultiplier; ((Graphic)_overencumbranceFillImage).color = PluginConfig.Instance.OverencumbranceGradientColorMid.Value; if ((Object)(object)_fillBarImage.sprite != (Object)null) { _overencumbranceFillImage.sprite = _fillBarImage.sprite; } ((Graphic)_overencumbranceFillImage).raycastTarget = false; _overencumbranceGradientEffect = val.AddComponent(); } } public void UpdateCapacityUI() { if ((Object)(object)_massCapacityUIInstance == (Object)null || !PluginConfig.Instance.EnableMassCapacityUI.Value) { return; } if ((Object)(object)_bagController != (Object)null) { if (PluginConfig.Instance.EnableBalance.Value) { _currentCapacity = CapacityScalingSystem.CalculateMassCapacity(_bagController); _currentUsedCapacity = BagCapacityCalculator.GetBaggedObjectMass(_bagController); } else { int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(_bagController); _currentCapacity = utilityMaxStock; _currentUsedCapacity = BagCapacityCalculator.GetCurrentBaggedCount(_bagController); } } bool flag = HudEditorManager.IsEditorActive || _currentCapacity >= 1f; _massCapacityUIInstance.SetActive(flag); if (!flag) { return; } float num = 0f; if (PluginConfig.Instance.EnableBalance.Value && _currentCapacity > 0f) { num = _currentUsedCapacity / _currentCapacity; } float num2 = 0f; if ((Object)(object)_bagController != (Object)null) { int utilityMaxStock2 = BagCapacityCalculator.GetUtilityMaxStock(_bagController); int num3 = BagCapacityCalculator.GetCurrentBaggedCount(_bagController); GameObject incomingObject = BagPatches.GetState(_bagController).IncomingObject; if ((Object)(object)incomingObject != (Object)null) { num3++; } if (utilityMaxStock2 > 0) { num2 = (float)num3 / (float)utilityMaxStock2; } } float num4 = (PluginConfig.Instance.EnableBalance.Value ? Mathf.Max(num, num2) : num2); if ((Object)(object)_fillBarImage != (Object)null) { _fillBarImage.fillAmount = Mathf.Clamp01(num4); } UpdateOverencumbranceFill(num4); if ((Object)(object)_percentageText != (Object)null) { ((TMP_Text)_percentageText).text = $"{Mathf.RoundToInt(num4 * 100f)}%"; } UpdateGradient(num4); UpdateSeparators(num4); } private void UpdateOverencumbranceFill(float currentPercentage) { if ((Object)(object)_overencumbranceFillImage == (Object)null) { return; } if (PluginConfig.Instance.OverencumbranceMax.Value <= 0f) { ((Component)_overencumbranceFillImage).gameObject.SetActive(false); return; } float num = 0f; if (currentPercentage > 1f) { float num2 = (PluginConfig.Instance.EnableBalance.Value ? (PluginConfig.Instance.OverencumbranceMax.Value / 100f) : 0f); float num3 = currentPercentage - 1f; num = Mathf.Clamp01(num3 / num2); } _overencumbranceFillImage.fillAmount = num; ((Component)_overencumbranceFillImage).gameObject.SetActive(num > 0f); } public void UpdateConfig() { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) bool flag = HudEditorManager.IsEditorActive || PluginConfig.Instance.EnableMassCapacityUI.Value; if ((Object)(object)_massCapacityUIInstance == (Object)null) { if (flag) { InitializeCapacityUI(); } return; } _massCapacityUIInstance.SetActive(flag); if (!flag) { return; } if ((Object)(object)_massCapacityUIRectTransform != (Object)null) { HudDraggable hudDraggable = (((Object)(object)_massCapacityUIInstance != (Object)null) ? _massCapacityUIInstance.GetComponent() : null); if ((Object)(object)hudDraggable == (Object)null || !hudDraggable.IsDragging) { _massCapacityUIRectTransform.anchoredPosition = new Vector2(PluginConfig.Instance.MassCapacityUIPositionX.Value, PluginConfig.Instance.MassCapacityUIPositionY.Value); } } float value = PluginConfig.Instance.MassCapacityUIScale.Value; if ((Object)(object)_massCapacityUIInstance != (Object)null) { _massCapacityUIInstance.transform.localScale = Vector3.one * value; } } private void OnDestroy() { if ((Object)(object)_massCapacityUIInstance != (Object)null) { Object.Destroy((Object)(object)_massCapacityUIInstance); _massCapacityUIInstance = null; } _overencumbranceFillImage = null; } private void UpdateGradient(float percentage) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fillBarImage != (Object)null) { ((Graphic)_fillBarImage).color = PluginConfig.Instance.CapacityGradientColorMid.Value; } if ((Object)(object)_overencumbranceFillImage != (Object)null) { ((Graphic)_overencumbranceFillImage).color = PluginConfig.Instance.OverencumbranceGradientColorMid.Value; } if ((Object)(object)_gradientEffect != (Object)null && (Object)(object)_fillBarImage != (Object)null) { _gradientEffect.Intensity = PluginConfig.Instance.GradientIntensity.Value; ((Graphic)_fillBarImage).SetVerticesDirty(); } if ((Object)(object)_overencumbranceGradientEffect != (Object)null && (Object)(object)_overencumbranceFillImage != (Object)null) { _overencumbranceGradientEffect.Intensity = PluginConfig.Instance.GradientIntensity.Value; ((Graphic)_overencumbranceFillImage).SetVerticesDirty(); } } private void CreateSeparator() { if (!((Object)(object)_fillBarImage == (Object)null) && !((Object)(object)_separatorTemplate == (Object)null)) { GameObject val = Object.Instantiate(_separatorTemplate, _separatorTemplate.transform.parent); ((Object)val).name = $"Separator_{_separatorObjects.Count}"; _separatorObjects.Add(val); } } private void UpdateSeparators(float percentage) { //IL_046a: Unknown result type (might be due to invalid IL or missing references) //IL_0482: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_massCapacityUIInstance == (Object)null) { return; } if (!PluginConfig.Instance.EnableSeparators.Value || _currentCapacity <= 0f) { foreach (GameObject separatorObject in _separatorObjects) { separatorObject.SetActive(false); } return; } List list = new List(); if (PluginConfig.Instance.EnableBalance.Value) { float num = 0f; if ((Object)(object)_bagController != (Object)null) { int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(_bagController); bool flag = PluginConfig.Instance.IsAddedCapacityInfinite && PluginConfig.Instance.BottomlessBagEnabled.Value; int num2 = 1; List baggedObjects = BagPatches.GetState(_bagController).BaggedObjects; if (baggedObjects != null) { HashSet hashSet = new HashSet(); foreach (GameObject item2 in baggedObjects) { if (!((Object)(object)item2 != (Object)null) || ProjectileRecoveryPatches.IsInProjectileState(item2)) { continue; } int instanceID = ((Object)item2).GetInstanceID(); if (!hashSet.Contains(instanceID)) { hashSet.Add(instanceID); float num3 = BaggedObjectPatches.LoadObjectState(_bagController, item2)?.baggedMass ?? _bagController.CalculateBaggedObjectMass(item2); num += num3; float num4 = num / _currentCapacity; if (!flag && utilityMaxStock > 0) { num4 = Mathf.Max((float)num2 / (float)utilityMaxStock, num4); } list.Add(num4); num2++; } } } GameObject incomingObject = BagPatches.GetState(_bagController).IncomingObject; if ((Object)(object)incomingObject != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(incomingObject)) { float num5 = BaggedObjectPatches.LoadObjectState(_bagController, incomingObject)?.baggedMass ?? _bagController.CalculateBaggedObjectMass(incomingObject); num += num5; float num6 = num / _currentCapacity; if (!flag && utilityMaxStock > 0) { num6 = Mathf.Max((float)num2 / (float)utilityMaxStock, num6); } list.Add(num6); num2++; } if (!flag && utilityMaxStock > 1) { int num7 = Mathf.Min(utilityMaxStock, 15); int num8 = num7; for (int i = num2; i < num8; i++) { float num9 = (float)i / (float)num7; float num10 = num / _currentCapacity; if (num9 > num10) { list.Add(num9); } } } } if (PluginConfig.Instance.OverencumbranceMax.Value > 0f) { float num11 = PluginConfig.Instance.OverencumbranceMax.Value / 100f; if (num > _currentCapacity) { List list2 = new List(); foreach (float item3 in list) { if (item3 > 1f) { float num12 = item3 - 1f; float item = Mathf.Clamp01(num12 / num11); list2.Add(item); } } list = list2; } } } else { int num13 = (((Object)(object)_bagController != (Object)null) ? BagCapacityCalculator.GetUtilityMaxStock(_bagController) : 3); if (num13 > 1) { int num14 = Mathf.Min(num13, 15); int num15 = num14; for (int j = 1; j < num15; j++) { list.Add((float)j / (float)num14); } } } while (_separatorObjects.Count < list.Count) { CreateSeparator(); } for (int k = 0; k < _separatorObjects.Count; k++) { if (k < list.Count) { float num16 = list[k]; if (num16 > 0.01f && num16 < 0.99f) { _separatorObjects[k].SetActive(true); RectTransform component = _separatorObjects[k].GetComponent(); if ((Object)(object)component != (Object)null) { float num17 = -37.76f; float num18 = 51.92f; float num19 = 21.53f; float num20 = 226.44f; float num21 = 98.88f; float num22 = num20 - num16 * num21; float num23 = num22 * (MathF.PI / 180f); float num24 = num17 + Mathf.Cos(num23) * num19; float num25 = num18 + Mathf.Sin(num23) * num19; float num26 = num22 + 90.5f; ((Transform)component).localPosition = new Vector3(num24, num25, 0f); ((Transform)component).localEulerAngles = new Vector3(0f, 0f, num26); } } else { _separatorObjects[k].SetActive(false); } } else { _separatorObjects[k].SetActive(false); } } } } public class CapacityUIGradient : BaseMeshEffect { public float Intensity = 1f; public override void ModifyMesh(VertexHelper vh) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) if (!((UIBehaviour)this).IsActive()) { return; } List list = new List(); vh.GetUIVertexStream(list); if (list.Count != 0) { Rect rect = ((BaseMeshEffect)this).graphic.rectTransform.rect; float xMin = ((Rect)(ref rect)).xMin; float width = ((Rect)(ref rect)).width; Color value = PluginConfig.Instance.CapacityGradientColorStart.Value; Color value2 = PluginConfig.Instance.CapacityGradientColorMid.Value; Color value3 = PluginConfig.Instance.CapacityGradientColorEnd.Value; for (int i = 0; i < list.Count; i++) { UIVertex val = list[i]; float num = ((width > 0f) ? ((val.position.x - xMin) / width) : 0f); num = Mathf.Clamp01(num); Color val2 = ((!(num <= 0.5f)) ? Color.Lerp(value2, value3, (num - 0.5f) * 2f) : Color.Lerp(value, value2, num * 2f)); Color val3 = val2; val3.a *= (int)val.color.a; val.color = Color32.op_Implicit(Color.Lerp(Color32.op_Implicit(val.color), val3, Intensity)); list[i] = val; } vh.Clear(); vh.AddUIVertexTriangleStream(list); } } } public class OverencumbranceUIGradient : BaseMeshEffect { public float Intensity = 1f; public override void ModifyMesh(VertexHelper vh) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) if (!((UIBehaviour)this).IsActive()) { return; } List list = new List(); vh.GetUIVertexStream(list); if (list.Count != 0) { Rect rect = ((BaseMeshEffect)this).graphic.rectTransform.rect; float xMin = ((Rect)(ref rect)).xMin; float width = ((Rect)(ref rect)).width; Color value = PluginConfig.Instance.OverencumbranceGradientColorStart.Value; Color value2 = PluginConfig.Instance.OverencumbranceGradientColorMid.Value; Color value3 = PluginConfig.Instance.OverencumbranceGradientColorEnd.Value; for (int i = 0; i < list.Count; i++) { UIVertex val = list[i]; float num = ((width > 0f) ? ((val.position.x - xMin) / width) : 0f); num = Mathf.Clamp01(num); Color val2 = ((!(num <= 0.5f)) ? Color.Lerp(value2, value, (num - 0.5f) * 2f) : Color.Lerp(value3, value2, num * 2f)); Color val3 = val2; val3.a *= (int)val.color.a; val.color = Color32.op_Implicit(Color.Lerp(Color32.op_Implicit(val.color), val3, Intensity)); list[i] = val; } vh.Clear(); vh.AddUIVertexTriangleStream(list); } } } public class BaggedObjectCarousel : MonoBehaviour, IConfigObserver { [CompilerGenerated] private sealed class d__43 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject slot; public float targetXOffset; public float targetYOffset; public float targetScale; public bool useFading; public float targetOpacity; public bool hideAfter; public BaggedObjectCarousel <>4__this; private RectTransform 5__2; private CanvasGroup 5__3; private float 5__4; private float 5__5; private Vector2 5__6; private Vector2 5__7; private float 5__8; private float 5__9; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__43(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; 5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; BaggedObjectCarousel baggedObjectCarousel = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; 5__2 = slot.GetComponent(); 5__3 = slot.GetComponent() ?? slot.AddComponent(); 5__4 = PluginConfig.Instance.CarouselAnimationDuration.Value; 5__5 = 0f; 5__6 = (Object.op_Implicit((Object)(object)5__2) ? 5__2.anchoredPosition : Vector2.zero); 5__7 = new Vector2(targetXOffset, targetYOffset); 5__8 = slot.transform.localScale.x; 5__9 = 5__3.alpha; break; case 1: <>1__state = -1; break; } if (5__5 < 5__4) { 5__5 += Time.deltaTime; float num2 = Mathf.Clamp01(5__5 / 5__4); float num3 = ((num2 < 0.5f) ? (4f * num2 * num2 * num2) : (1f - Mathf.Pow(-2f * num2 + 2f, 3f) / 2f)); if (Object.op_Implicit((Object)(object)5__2)) { 5__2.anchoredPosition = Vector2.Lerp(5__6, 5__7, num3); } slot.transform.localScale = Vector3.one * Mathf.Lerp(5__8, targetScale, num3); if (useFading) { 5__3.alpha = Mathf.Lerp(5__9, targetOpacity, num3); } <>2__current = null; <>1__state = 1; return true; } if (Object.op_Implicit((Object)(object)5__2)) { 5__2.anchoredPosition = 5__7; } slot.transform.localScale = Vector3.one * targetScale; 5__3.alpha = targetOpacity; if (hideAfter) { slot.SetActive(false); baggedObjectCarousel._slotToPassenger.Remove(slot); } baggedObjectCarousel._activeCoroutines.Remove(slot); 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 d__48 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject slot; object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object? IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__48(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: 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 switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: <>1__state = -1; ApplyWeightIconTransformImmediate(slot); <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 2; return true; case 2: <>1__state = -1; ApplyWeightIconTransformImmediate(slot); 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(); } } public GameObject? slotPrefab; public float sideScale = 0.8f; private static Texture2D? _weightIconTexture; private static Sprite? _newWeightIconSprite; private static Sprite? _oldWeightIconSprite; private static Sprite? _overencumbranceIconSprite; private GameObject? aboveInstance; private GameObject? centerInstance; private GameObject? belowInstance; private List _slots = new List(); private Dictionary _slotToPassenger = new Dictionary(); private Dictionary _slotToIndex = new Dictionary(); private DrifterBagController? _cachedBagController; private static GameObject? _emptySlotMarker; private Dictionary _activeCoroutines = new Dictionary(); private static Texture2D? WeightIconTexture => _weightIconTexture ?? (_weightIconTexture = LoadWeightIconTexture()); private static Sprite? NewWeightIconSprite => _newWeightIconSprite ?? (_newWeightIconSprite = (((Object)(object)WeightIconTexture != (Object)null) ? Sprite.Create(WeightIconTexture, new Rect(0f, 0f, (float)((Texture)WeightIconTexture).width, (float)((Texture)WeightIconTexture).height), new Vector2(0.5f, 0.5f)) : null)); private static Sprite OldWeightIconSprite => _oldWeightIconSprite ?? (_oldWeightIconSprite = Addressables.LoadAssetAsync((object)"RoR2/Base/Common/texMovespeedBuffIcon.tif").WaitForCompletion()); private static Sprite? OverencumbranceIconSprite => _overencumbranceIconSprite ?? (_overencumbranceIconSprite = LoadOverencumbranceIconSprite()); private static GameObject EmptySlotMarker { get { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown object obj = _emptySlotMarker; if (obj == null) { GameObject val = new GameObject("EmptySlotMarker"); _emptySlotMarker = val; obj = (object)val; } return (GameObject)obj; } } private static Sprite? LoadOverencumbranceIconSprite() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("DrifterBossGrabMod.Resources.Arrow.png"); if (stream == null) { Debug.LogError((object)"Could not find embedded resource: DrifterBossGrabMod.Resources.Arrow.png"); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); } private static Texture2D? LoadWeightIconTexture() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected O, but got Unknown Assembly executingAssembly = Assembly.GetExecutingAssembly(); using Stream stream = executingAssembly.GetManifestResourceStream("DrifterBossGrabMod.WeightIcon.png"); if (stream == null) { Debug.LogError((object)"Could not find embedded resource: DrifterBossGrabMod.WeightIcon.png"); return null; } byte[] array = new byte[stream.Length]; stream.Read(array, 0, array.Length); Texture2D val = new Texture2D(2, 2); ImageConversion.LoadImage(val, array); return val; } private void OnEnable() { BagCarouselUpdater.ActiveCarousels.Add(this); ConfigChangeNotifier.AddObserver(this); } private void OnDisable() { BagCarouselUpdater.ActiveCarousels.Remove(this); ConfigChangeNotifier.RemoveObserver(this); } public void OnConfigChanged(string key, object value) { UpdateToggles(); UpdateParentPosition(); PopulateCarousel(); } public void UpdateScales() { PopulateCarousel(); } public void UpdateToggles() { bool flag = HudEditorManager.IsEditorActive || PluginConfig.Instance.EnableCarouselHUD.Value; if (!flag) { if (Object.op_Implicit((Object)(object)aboveInstance)) { aboveInstance.SetActive(false); } if (Object.op_Implicit((Object)(object)centerInstance)) { centerInstance.SetActive(false); } if (Object.op_Implicit((Object)(object)belowInstance)) { belowInstance.SetActive(false); } { foreach (GameObject slot in _slots) { slot.SetActive(false); } return; } } if (Object.op_Implicit((Object)(object)aboveInstance)) { aboveInstance.SetActive(true); ToggleSlotElements(aboveInstance, isCenter: false); } if (Object.op_Implicit((Object)(object)centerInstance)) { centerInstance.SetActive(true); ToggleSlotElements(centerInstance, isCenter: true); } if (Object.op_Implicit((Object)(object)belowInstance)) { belowInstance.SetActive(true); ToggleSlotElements(belowInstance, isCenter: false); } if (flag && (!Object.op_Implicit((Object)(object)centerInstance) || !centerInstance.activeSelf)) { PopulateCarousel(); } UpdateParentPosition(); } public void UpdateParentPosition() { //IL_0046: Unknown result type (might be due to invalid IL or missing references) RectTransform component = ((Component)this).GetComponent(); if (Object.op_Implicit((Object)(object)component)) { HudDraggable component2 = ((Component)this).GetComponent(); if ((Object)(object)component2 == (Object)null || !component2.IsDragging) { component.anchoredPosition = new Vector2(PluginConfig.Instance.CenterSlotX.Value, PluginConfig.Instance.CenterSlotY.Value); } } } private DrifterBagController? GetOrRefreshBagController() { if ((Object)(object)_cachedBagController != (Object)null && ((NetworkBehaviour)_cachedBagController).hasAuthority) { return _cachedBagController; } DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { if (((NetworkBehaviour)val).hasAuthority) { _cachedBagController = val; return _cachedBagController; } } _cachedBagController = null; return null; } private int GetAnimationCapacity(DrifterBagController? bagController) { if ((Object)(object)bagController == (Object)null) { return 1; } return BagCapacityCalculator.GetUtilityMaxStock(bagController); } private void Start() { Transform val = ((Component)this).transform.Find("aboveSlot"); Transform val2 = ((Component)this).transform.Find("centerSlot"); Transform val3 = ((Component)this).transform.Find("belowSlot"); if (Object.op_Implicit((Object)(object)val)) { _slots.Add(((Component)val).gameObject); } if (Object.op_Implicit((Object)(object)val2)) { _slots.Add(((Component)val2).gameObject); } if (Object.op_Implicit((Object)(object)val3)) { _slots.Add(((Component)val3).gameObject); } GameObject val4 = (GameObject)(((Object)(object)val2 != (Object)null) ? ((object)((Component)val2).gameObject) : ((object)slotPrefab)); if (Object.op_Implicit((Object)(object)val4)) { for (int i = 0; i < 6; i++) { GameObject val5 = Object.Instantiate(val4, ((Component)this).transform); ((Object)val5).name = $"extraSlot_{i}"; _slots.Add(val5); } } foreach (GameObject slot in _slots) { slot.SetActive(false); if (!Object.op_Implicit((Object)(object)slot.GetComponent())) { slot.AddComponent(); } ApplyWeightIconTransform(slot); } PopulateCarousel(); UpdateToggles(); } public void PopulateCarousel(int direction = 0) { //IL_07a4: Unknown result type (might be due to invalid IL or missing references) //IL_07b0: Unknown result type (might be due to invalid IL or missing references) DrifterBagController orRefreshBagController = GetOrRefreshBagController(); if ((Object)(object)orRefreshBagController == (Object)null && !HudEditorManager.IsEditorActive) { foreach (GameObject slot in _slots) { slot.SetActive(false); } _slotToPassenger.Clear(); _slotToIndex.Clear(); return; } List list = new List(); GameObject val = null; if ((Object)(object)orRefreshBagController != (Object)null) { BottomlessBagNetworkController component = ((Component)orRefreshBagController).GetComponent(); List baggedObjects = BagPatches.GetState(orRefreshBagController).BaggedObjects; if (((NetworkBehaviour)orRefreshBagController).hasAuthority && baggedObjects != null) { baggedObjects.RemoveAll((GameObject obj) => (Object)(object)obj == (Object)null || !Object.op_Implicit((Object)(object)obj)); list = baggedObjects; val = BagPatches.GetMainSeatObject(orRefreshBagController); } else if ((Object)(object)component != (Object)null && (!NetworkServer.active || BagPatches.GetState(orRefreshBagController).BaggedObjects == null)) { list = component.GetBaggedObjects(); int selectedIndex = component.selectedIndex; if (selectedIndex >= 0 && selectedIndex < list.Count) { val = list[selectedIndex]; } } else { List baggedObjects2 = BagPatches.GetState(orRefreshBagController).BaggedObjects; if (baggedObjects2 != null) { baggedObjects2.RemoveAll((GameObject obj) => (Object)(object)obj == (Object)null || !Object.op_Implicit((Object)(object)obj)); list = baggedObjects2; val = BagPatches.GetMainSeatObject(orRefreshBagController); } } } if (list.Count == 0 && (Object)(object)val == (Object)null && !HudEditorManager.IsEditorActive) { foreach (GameObject slot2 in _slots) { slot2.SetActive(false); } _slotToPassenger.Clear(); _slotToIndex.Clear(); return; } if ((Object)(object)val != (Object)null && !list.Contains(val)) { val = null; } int num = -1; for (int i = 0; i < list.Count; i++) { if ((Object)(object)list[i] == (Object)(object)val) { num = i; break; } } Dictionary dictionary = new Dictionary(); int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(orRefreshBagController); bool flag = list.Count >= utilityMaxStock; int animationCapacity = GetAnimationCapacity(orRefreshBagController); if ((Object)(object)val == (Object)null) { dictionary[0] = EmptySlotMarker; dictionary[1] = ((list.Count > 0) ? list[0] : null); dictionary[-1] = ((list.Count > 0) ? list[list.Count - 1] : null); dictionary[2] = ((list.Count > 1) ? list[1] : null); dictionary[-2] = ((list.Count > 1) ? list[list.Count - 2] : null); } else { dictionary[0] = val; int num2 = num + 1; if (num2 < list.Count) { dictionary[1] = list[num2]; } else if (flag && list.Count > 0) { dictionary[1] = list[0]; } else { dictionary[1] = EmptySlotMarker; } int num3 = num - 1; if (num3 >= 0) { dictionary[-1] = list[num3]; } else if (flag && list.Count > 0) { dictionary[-1] = list[list.Count - 1]; } else { dictionary[-1] = EmptySlotMarker; } int num4 = num + 2; if (num4 < list.Count) { dictionary[2] = list[num4]; } else if (num4 == list.Count) { dictionary[2] = EmptySlotMarker; } else if (list.Count > 0) { dictionary[2] = list[0]; } else { dictionary[2] = EmptySlotMarker; } int num5 = num - 2; if (num5 >= 0) { dictionary[-2] = list[num5]; } else if (num5 == -1) { dictionary[-2] = EmptySlotMarker; } else if (list.Count > 0) { dictionary[-2] = list[list.Count - 1]; } else { dictionary[-2] = EmptySlotMarker; } } Dictionary dictionary2 = new Dictionary(); for (int j = 0; j < list.Count; j++) { dictionary2[list[j]] = j + 1; } float value = PluginConfig.Instance.SideSlotScale.Value; float value2 = PluginConfig.Instance.SideSlotOpacity.Value; HashSet hashSet = new HashSet(); HashSet hashSet2 = new HashSet(); List list2 = _slots.ToList(); foreach (GameObject item in list2) { if (!_slotToPassenger.TryGetValue(item, out GameObject value3)) { continue; } int num6 = -99; foreach (KeyValuePair item2 in dictionary) { if ((Object)(object)item2.Value == (Object)(object)value3) { num6 = item2.Key; break; } } if (num6 != -99 && !hashSet2.Contains(value3)) { int value4; int slotIndex = (((Object)(object)value3 != (Object)null && (Object)(object)value3 != (Object)(object)EmptySlotMarker && dictionary2.TryGetValue(value3, out value4)) ? value4 : (-1)); CanvasGroup component2 = item.GetComponent(); float alpha = (((Object)(object)component2 != (Object)null) ? component2.alpha : 1f); SetSlotData(item, value3, orRefreshBagController, num6 == 0, slotIndex, list.Count); if ((Object)(object)component2 != (Object)null) { component2.alpha = alpha; } AnimateToState(item, num6, animationCapacity, orRefreshBagController); hashSet.Add(item); hashSet2.Add(value3); } else { int state = ((direction > 0) ? (-2) : 2); if (direction == 0) { state = -2; } AnimateToState(item, state, animationCapacity, orRefreshBagController, hideAfter: true); } } foreach (KeyValuePair item3 in dictionary) { int key = item3.Key; GameObject value5 = item3.Value; if (((Object)(object)value5 != (Object)null && (Object)(object)value5 != (Object)(object)EmptySlotMarker && hashSet2.Contains(value5)) || ((Object)(object)value5 == (Object)(object)EmptySlotMarker && hashSet2.Contains(EmptySlotMarker))) { continue; } GameObject val2 = null; foreach (GameObject slot3 in _slots) { if (!hashSet.Contains(slot3) && !_slotToPassenger.ContainsKey(slot3)) { val2 = slot3; break; } } if ((Object)(object)val2 == (Object)null) { foreach (GameObject slot4 in _slots) { if (!hashSet.Contains(slot4)) { val2 = slot4; break; } } } if (Object.op_Implicit((Object)(object)val2)) { _slotToPassenger[val2] = value5; int value6; int num7 = (((Object)(object)value5 != (Object)null && (Object)(object)value5 != (Object)(object)EmptySlotMarker && dictionary2.TryGetValue(value5, out value6)) ? value6 : (-1)); _slotToIndex[val2] = num7; SetSlotData(val2, value5, orRefreshBagController, key == 0, num7, list.Count); int state2 = ((direction > 0) ? (key + 1) : (key - 1)); if (direction == 0) { state2 = key; } (Vector2, float, float) stateParams = GetStateParams(state2, animationCapacity); SetSlotInitialState(val2, stateParams.Item1.x, stateParams.Item1.y, stateParams.Item2, 0f); val2.SetActive(true); AnimateToState(val2, key, animationCapacity, orRefreshBagController); hashSet.Add(val2); hashSet2.Add(value5); } } centerInstance = null; foreach (GameObject slot5 in _slots) { if (_slotToPassenger.TryGetValue(slot5, out GameObject value7) && (Object)(object)value7 == (Object)(object)dictionary[0]) { centerInstance = slot5; break; } } aboveInstance = null; foreach (GameObject slot6 in _slots) { if (_slotToPassenger.TryGetValue(slot6, out GameObject value8) && (Object)(object)value8 == (Object)(object)dictionary[1]) { aboveInstance = slot6; break; } } belowInstance = null; foreach (GameObject slot7 in _slots) { if (_slotToPassenger.TryGetValue(slot7, out GameObject value9) && (Object)(object)value9 == (Object)(object)dictionary[-1]) { belowInstance = slot7; break; } } if (Object.op_Implicit((Object)(object)centerInstance)) { centerInstance.transform.SetAsLastSibling(); } foreach (GameObject slot8 in _slots) { if (!_slotToPassenger.TryGetValue(slot8, out GameObject value10) || !slot8.activeSelf) { continue; } bool flag2 = (Object)(object)slot8 == (Object)(object)centerInstance; ToggleSlotElements(slot8, flag2); BaggedCardController componentInChildren = slot8.GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)componentInChildren) || !Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar)) { continue; } bool flag3 = PluginConfig.Instance.EnableDamagePreview.Value && (flag2 || PluginConfig.Instance.AoEDamageDistribution.Value != AoEDamageMode.None); DamagePreviewOverlay damagePreviewOverlay = ((Component)((AllyCardController)componentInChildren).healthBar).GetComponent(); if (flag3) { if (!Object.op_Implicit((Object)(object)damagePreviewOverlay)) { damagePreviewOverlay = ((Component)((AllyCardController)componentInChildren).healthBar).gameObject.AddComponent(); } if ((Object)(object)value10 != (Object)null && (Object)(object)value10 != (Object)(object)EmptySlotMarker && (Object)(object)orRefreshBagController != (Object)null) { damagePreviewOverlay.SetTarget(value10, orRefreshBagController); } } else if (Object.op_Implicit((Object)(object)damagePreviewOverlay)) { Object.Destroy((Object)(object)damagePreviewOverlay); } } foreach (GameObject slot9 in _slots) { if (_slotToPassenger.TryGetValue(slot9, out GameObject value11) && (Object)(object)value11 != (Object)null && (Object)(object)value11 != (Object)(object)EmptySlotMarker) { int value12; int num8 = (dictionary2.TryGetValue(value11, out value12) ? value12 : (-1)); _slotToIndex[slot9] = num8; SetSlotNumberLabel(slot9, num8, list.Count); } else if (_slotToPassenger.ContainsKey(slot9)) { _slotToIndex[slot9] = -1; SetSlotNumberLabel(slot9, -1, list.Count); } } } private void AnimateToState(GameObject slot, int state, int capacity, DrifterBagController? bagController, bool hideAfter = false) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) (Vector2, float, float) stateParams = GetStateParams(state, capacity); float opacity = stateParams.Item3; if (_slotToPassenger.TryGetValue(slot, out GameObject value) && ((Object)(object)value == (Object)null || (Object)(object)value == (Object)(object)EmptySlotMarker)) { opacity = 0f; } bool useFading = capacity > 1; AnimateSlot(slot, stateParams.Item1.x, stateParams.Item1.y, stateParams.Item2, opacity, hideAfter, useFading); } private (Vector2 pos, float scale, float opacity) GetStateParams(int state, int capacity) { //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) float value = PluginConfig.Instance.SideSlotX.Value; float value2 = PluginConfig.Instance.SideSlotY.Value; float value3 = PluginConfig.Instance.CarouselSpacing.Value; float num = ((state == 0) ? PluginConfig.Instance.CenterSlotScale.Value : PluginConfig.Instance.SideSlotScale.Value); float item = ((state == 0) ? PluginConfig.Instance.CenterSlotOpacity.Value : PluginConfig.Instance.SideSlotOpacity.Value); if (Mathf.Abs(state) > 1) { item = 0f; num *= 0.8f; } Vector2 zero = default(Vector2); switch (state) { case 0: zero = Vector2.zero; break; case 1: ((Vector2)(ref zero))..ctor(value, value2 - value3); break; case -1: ((Vector2)(ref zero))..ctor(value, value2 + value3); break; case 2: ((Vector2)(ref zero))..ctor(value, value2 - 2f * value3); break; case -2: ((Vector2)(ref zero))..ctor(value, value2 + 2f * value3); break; case 3: ((Vector2)(ref zero))..ctor(value, value2 - 3f * value3); break; case -3: ((Vector2)(ref zero))..ctor(value, value2 + 3f * value3); break; default: zero = Vector2.zero; break; } return (zero, num, item); } private void AnimateSlot(GameObject slot, float x, float y, float scale, float opacity) { AnimateSlot(slot, x, y, scale, opacity, hideAfter: false, useFading: true); } private void AnimateSlot(GameObject slot, float x, float y, float scale, float opacity, bool hideAfter, bool useFading) { if (_activeCoroutines.TryGetValue(slot, out Coroutine value) && value != null) { ((MonoBehaviour)this).StopCoroutine(value); } if (PluginConfig.Instance.CarouselAnimationDuration.Value <= 0.001f || !useFading) { ApplySlotStateImmediate(slot, x, y, scale, opacity); if (hideAfter) { slot.SetActive(false); _slotToPassenger.Remove(slot); } if (_activeCoroutines.ContainsKey(slot)) { _activeCoroutines.Remove(slot); } } else { _activeCoroutines[slot] = ((MonoBehaviour)this).StartCoroutine(AnimateSlotPosition(slot, x, y, scale, opacity, hideAfter, useFading)); } } private void ApplySlotStateImmediate(GameObject slot, float x, float y, float scale, float opacity) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) RectTransform component = slot.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.anchoredPosition = new Vector2(x, y); } slot.transform.localScale = Vector3.one * scale; CanvasGroup val = slot.GetComponent() ?? slot.AddComponent(); val.alpha = opacity; } private void SetSlotInitialState(GameObject slot, float x, float y, float scale, float opacity) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) RectTransform component = slot.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { component.anchoredPosition = new Vector2(x, y); } slot.transform.localScale = Vector3.one * scale; CanvasGroup val = slot.GetComponent() ?? slot.AddComponent(); val.alpha = opacity; } [IteratorStateMachine(typeof(d__43))] private IEnumerator AnimateSlotPosition(GameObject slot, float targetXOffset, float targetYOffset, float targetScale, float targetOpacity, bool hideAfter, bool useFading) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__43(0) { <>4__this = this, slot = slot, targetXOffset = targetXOffset, targetYOffset = targetYOffset, targetScale = targetScale, targetOpacity = targetOpacity, hideAfter = hideAfter, useFading = useFading }; } private void SetSlotData(GameObject slot, GameObject? passenger, DrifterBagController? bagController, bool isCenter, int slotIndex = -1, int totalCount = 0) { //IL_06f5: Unknown result type (might be due to invalid IL or missing references) //IL_0704: Unknown result type (might be due to invalid IL or missing references) //IL_0713: Unknown result type (might be due to invalid IL or missing references) //IL_0718: Unknown result type (might be due to invalid IL or missing references) //IL_07c0: Unknown result type (might be due to invalid IL or missing references) //IL_07c7: Expected O, but got Unknown //IL_080a: Unknown result type (might be due to invalid IL or missing references) //IL_06b3: Unknown result type (might be due to invalid IL or missing references) //IL_06c2: Unknown result type (might be due to invalid IL or missing references) //IL_06d1: Unknown result type (might be due to invalid IL or missing references) //IL_06d6: Unknown result type (might be due to invalid IL or missing references) //IL_087c: Unknown result type (might be due to invalid IL or missing references) //IL_0892: Unknown result type (might be due to invalid IL or missing references) //IL_08a8: Unknown result type (might be due to invalid IL or missing references) //IL_08be: Unknown result type (might be due to invalid IL or missing references) //IL_08d4: Unknown result type (might be due to invalid IL or missing references) //IL_0854: Unknown result type (might be due to invalid IL or missing references) //IL_099a: Unknown result type (might be due to invalid IL or missing references) //IL_09a1: Expected O, but got Unknown //IL_09df: Unknown result type (might be due to invalid IL or missing references) //IL_0a12: Unknown result type (might be due to invalid IL or missing references) //IL_0a1e: Unknown result type (might be due to invalid IL or missing references) //IL_0a8d: Unknown result type (might be due to invalid IL or missing references) //IL_0acc: Unknown result type (might be due to invalid IL or missing references) //IL_0a45: Unknown result type (might be due to invalid IL or missing references) //IL_0a75: Unknown result type (might be due to invalid IL or missing references) BaggedCardController componentInChildren = slot.GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)componentInChildren)) { return; } CanvasGroup component = slot.GetComponent(); if ((Object)(object)passenger == (Object)(object)EmptySlotMarker || (Object)(object)passenger == (Object)null) { componentInChildren.sourceBody = null; ((AllyCardController)componentInChildren).sourceMaster = null; componentInChildren.sourcePassengerAttributes = null; ((AllyCardController)componentInChildren).ForceUpdate(); if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).nameLabel)) { ((Component)((AllyCardController)componentInChildren).nameLabel).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).portraitIconImage)) { ((Component)((AllyCardController)componentInChildren).portraitIconImage).gameObject.SetActive(false); } if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar)) { ((Component)((AllyCardController)componentInChildren).healthBar).gameObject.SetActive(false); if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar.deadImage)) { ((Behaviour)((AllyCardController)componentInChildren).healthBar.deadImage).enabled = false; } } if (Object.op_Implicit((Object)(object)component)) { component.alpha = (HudEditorManager.IsEditorActive ? 0.3f : 0f); } ChildLocator component2 = slot.GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { Transform val = component2.FindChild("WeightIcon"); if (Object.op_Implicit((Object)(object)val)) { ((Component)val).gameObject.SetActive(false); Transform obj = val.Find("WeightText"); TextMeshProUGUI val2 = ((obj != null) ? ((Component)obj).GetComponent() : null); if (Object.op_Implicit((Object)(object)val2)) { ((Component)val2).gameObject.SetActive(false); } Transform obj2 = val.Find("WeightUnitLabel"); TextMeshProUGUI val3 = ((obj2 != null) ? ((Component)obj2).GetComponent() : null); if (Object.op_Implicit((Object)(object)val3)) { ((Component)val3).gameObject.SetActive(false); } } } } else { if ((Object)(object)passenger == (Object)null || !Object.op_Implicit((Object)(object)passenger)) { if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar)) { ((Component)((AllyCardController)componentInChildren).healthBar).gameObject.SetActive(false); } return; } SpecialObjectAttributes component3 = passenger.GetComponent(); CharacterBody component4 = passenger.GetComponent(); CharacterMaster component5 = passenger.GetComponent(); HealthComponent component6 = passenger.GetComponent(); componentInChildren.sourceBody = component4; ((AllyCardController)componentInChildren).sourceMaster = component5; componentInChildren.sourcePassengerAttributes = component3; ((AllyCardController)componentInChildren).ForceUpdate(); if ((Object)(object)component6 != (Object)null && (Object)(object)component4 != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[BaggedObjectCarousel] Health info for {((Object)passenger).name}: health={component6.health}, fullHealth={component6.fullHealth}, fullCombinedHealth={component6.fullCombinedHealth}, baseMaxHealth={component4.baseMaxHealth}"); } if ((Object)(object)((AllyCardController)componentInChildren).healthBar != (Object)null && (Object)(object)((AllyCardController)componentInChildren).healthBar.source == (Object)(object)component6) { try { ((AllyCardController)componentInChildren).healthBar.Update(); } catch (NullReferenceException) { Log.Warning("[BaggedObjectCarousel] Failed to update health bar for passenger " + ((passenger != null) ? ((Object)passenger).name : null) + " (health bar in invalid state)"); } } } else if ((Object)(object)component3 != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[BaggedObjectCarousel] SpecialObjectAttributes for {((Object)passenger).name}: durability={component3.durability}, maxDurability={component3.maxDurability}"); } if ((Object)(object)((AllyCardController)componentInChildren).healthBar != (Object)null && (Object)(object)((AllyCardController)componentInChildren).healthBar.altSource == (Object)(object)component3) { try { ((AllyCardController)componentInChildren).healthBar.Update(); } catch (NullReferenceException) { Log.Warning("[BaggedObjectCarousel] Failed to update health bar for passenger " + ((passenger != null) ? ((Object)passenger).name : null) + " (health bar in invalid state)"); } } } if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar) && Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar.deadImage)) { ((Behaviour)((AllyCardController)componentInChildren).healthBar.deadImage).enabled = false; } float num = 0f; if ((Object)(object)bagController != (Object)null) { num = (((Object)(object)bagController == (Object)(object)passenger) ? bagController.baggedMass : bagController.CalculateBaggedObjectMass(passenger)); } float num2 = num; bool value = PluginConfig.Instance.ShowTotalMassOnWeightIcon.Value; bool flag = PluginConfig.Instance.StateCalculationMode.Value == StateCalculationMode.All; if (isCenter && value && flag) { num = (Object.op_Implicit((Object)(object)bagController) ? BagCapacityCalculator.GetBaggedObjectMass(bagController) : 0f); } ChildLocator component7 = slot.GetComponent(); if (Object.op_Implicit((Object)(object)component7)) { Transform val4 = component7.FindChild("WeightIcon"); if (Object.op_Implicit((Object)(object)val4)) { Image component8 = ((Component)val4).GetComponent(); if (Object.op_Implicit((Object)(object)component8)) { if (PluginConfig.Instance.UseNewWeightIcon.Value) { if (Object.op_Implicit((Object)(object)NewWeightIconSprite)) { component8.sprite = NewWeightIconSprite; } } else if (Object.op_Implicit((Object)(object)OldWeightIconSprite)) { component8.sprite = OldWeightIconSprite; } ApplyWeightIconTransform(slot); float num3 = 0f; bool flag2 = false; if (PluginConfig.Instance.EnableBalance.Value) { float num4 = (Object.op_Implicit((Object)(object)bagController) ? CapacityScalingSystem.CalculateMassCapacity(bagController) : DrifterBagController.maxMass); if (num4 >= 1000000f) { float num5 = 700f; if (!PluginConfig.Instance.IsMassCapInfinite && float.TryParse(PluginConfig.Instance.MassCap.Value, out var result)) { num5 = result; } num3 = ((num5 > 0f) ? (num / num5) : 0f); flag2 = false; } else { num3 = ((num4 > 0f) ? (num / num4) : 0f); flag2 = isCenter && value && num3 > 1f; } } else if (isCenter && value && flag) { int num6 = (Object.op_Implicit((Object)(object)bagController) ? CapacityScalingSystem.GetTotalCapacity(bagController) : 0); int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(bagController); num3 = ((num6 > 0) ? ((float)currentBaggedCount / (float)num6) : 0f); flag2 = currentBaggedCount > num6; } else { float num7 = 700f; if (!PluginConfig.Instance.IsMassCapInfinite && float.TryParse(PluginConfig.Instance.MassCap.Value, out var result2)) { num7 = result2; } num3 = ((num7 > 0f) ? (num / num7) : 0f); flag2 = false; } if (PluginConfig.Instance.ScaleWeightColor.Value) { if (flag2) { float num8 = 0f; if (PluginConfig.Instance.EnableBalance.Value) { float num9 = PluginConfig.Instance.OverencumbranceMax.Value / 100f; if (num9 <= 0f) { num9 = 0.01f; } num8 = Mathf.Clamp01((num3 - 1f) / num9); } else { int num10 = (Object.op_Implicit((Object)(object)bagController) ? CapacityScalingSystem.GetTotalCapacity(bagController) : 0); int currentBaggedCount2 = BagCapacityCalculator.GetCurrentBaggedCount(bagController); float num11 = Mathf.Max(0, currentBaggedCount2 - num10); num8 = Mathf.Clamp01(num11 / Mathf.Max(1f, (float)num10)); } ((Graphic)component8).color = GetGradientColor(num8, PluginConfig.Instance.OverencumbranceGradientColorStart.Value, PluginConfig.Instance.OverencumbranceGradientColorMid.Value, PluginConfig.Instance.OverencumbranceGradientColorEnd.Value); } else { ((Graphic)component8).color = GetGradientColor(Mathf.Clamp01(num3), PluginConfig.Instance.CapacityGradientColorStart.Value, PluginConfig.Instance.CapacityGradientColorMid.Value, PluginConfig.Instance.CapacityGradientColorEnd.Value); } } WeightDisplayMode value2 = PluginConfig.Instance.WeightDisplayMode.Value; bool flag3 = flag2 && PluginConfig.Instance.UseNewWeightIcon.Value && PluginConfig.Instance.ShowOverencumberIcon.Value && PluginConfig.Instance.ShowTotalMassOnWeightIcon.Value; Transform val5 = val4.Find("OverencumbranceIcon"); if (flag3) { if (!Object.op_Implicit((Object)(object)val5)) { GameObject val6 = new GameObject("OverencumbranceIcon", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val6.transform.SetParent(val4, false); val5 = val6.transform; Image component9 = val6.GetComponent(); component9.sprite = OverencumbranceIconSprite; ((Graphic)component9).color = new Color(0.8f, 0.9f, 1f, 1f); } Image component10 = ((Component)val5).GetComponent(); if (Object.op_Implicit((Object)(object)component10) && Object.op_Implicit((Object)(object)OverencumbranceIconSprite)) { component10.sprite = OverencumbranceIconSprite; ((Graphic)component10).color = new Color(0.8f, 0.9f, 1f, 1f); } RectTransform component11 = ((Component)val5).GetComponent(); if (Object.op_Implicit((Object)(object)component11)) { component11.anchorMin = new Vector2(0.5f, 0.5f); component11.anchorMax = new Vector2(0.5f, 0.5f); component11.pivot = new Vector2(0.5f, 0.5f); component11.anchoredPosition = new Vector2(0f, -4f); component11.sizeDelta = new Vector2(7.5f, 7.5f); } ((Component)val5).gameObject.SetActive(true); Transform val7 = val4.Find("WeightText"); if (Object.op_Implicit((Object)(object)val7)) { ((Component)val7).gameObject.SetActive(false); } Transform val8 = val4.Find("WeightUnitLabel"); if (Object.op_Implicit((Object)(object)val8)) { ((Component)val8).gameObject.SetActive(false); } } else { if (Object.op_Implicit((Object)(object)val5)) { ((Component)val5).gameObject.SetActive(false); } if (value2 != 0) { Transform obj3 = val4.Find("WeightText"); TextMeshProUGUI val9 = ((obj3 != null) ? ((Component)obj3).GetComponent() : null); Transform obj4 = val4.Find("WeightUnitLabel"); TextMeshProUGUI val10 = ((obj4 != null) ? ((Component)obj4).GetComponent() : null); if (!Object.op_Implicit((Object)(object)val9)) { GameObject val11 = new GameObject("WeightText"); val11.transform.SetParent(val4, false); val9 = val11.AddComponent(); ((TMP_Text)val9).font = HGTextMeshProUGUI.defaultLanguageFont; ((TMP_Text)val9).fontSize = 12f; ((TMP_Text)val9).alignment = (TextAlignmentOptions)514; ((Graphic)val9).color = Color.white; ((TMP_Text)val9).richText = true; } RectTransform component12 = ((Component)val9).GetComponent(); if (Object.op_Implicit((Object)(object)component12)) { component12.sizeDelta = new Vector2(50f, 20f); ((Transform)component12).localRotation = Quaternion.identity; if (PluginConfig.Instance.UseNewWeightIcon.Value) { component12.anchoredPosition = new Vector2(0f, 2.4f); ((TMP_Text)val9).verticalAlignment = (VerticalAlignmentOptions)1024; ((TMP_Text)val9).fontSize = 8.5f; ((TMP_Text)val9).characterSpacing = 0f; ((Transform)component12).localRotation = Quaternion.identity; } else { component12.anchoredPosition = new Vector2(0f, 0f); ((TMP_Text)val9).verticalAlignment = (VerticalAlignmentOptions)512; ((TMP_Text)val9).fontSize = 12f; ((TMP_Text)val9).characterSpacing = 0f; ((Transform)component12).localRotation = Quaternion.Euler(0f, 0f, 90f); } } switch (value2) { case WeightDisplayMode.Multiplier: ((TMP_Text)val9).text = Mathf.CeilToInt(num / 100f) + "x"; if (Object.op_Implicit((Object)(object)val10)) { ((Component)val10).gameObject.SetActive(false); } break; case WeightDisplayMode.Pounds: { int num13 = Mathf.FloorToInt(num / 10f); ((TMP_Text)val9).text = $"lb{num13}lb"; if (Object.op_Implicit((Object)(object)val10)) { ((Component)val10).gameObject.SetActive(false); } break; } case WeightDisplayMode.KiloGrams: { int num12 = Mathf.FloorToInt(num / 10f); ((TMP_Text)val9).text = $"kg{num12}kg"; if (Object.op_Implicit((Object)(object)val10)) { ((Component)val10).gameObject.SetActive(false); } break; } } ((Component)val9).gameObject.SetActive(true); } else { Transform obj5 = val4.Find("WeightText"); TextMeshProUGUI val12 = ((obj5 != null) ? ((Component)obj5).GetComponent() : null); if (Object.op_Implicit((Object)(object)val12)) { ((Component)val12).gameObject.SetActive(false); } Transform obj6 = val4.Find("WeightUnitLabel"); TextMeshProUGUI val13 = ((obj6 != null) ? ((Component)obj6).GetComponent() : null); if (Object.op_Implicit((Object)(object)val13)) { ((Component)val13).gameObject.SetActive(false); } } } } } } } bool flag4 = PluginConfig.Instance.EnableDamagePreview.Value && (isCenter || PluginConfig.Instance.AoEDamageDistribution.Value != AoEDamageMode.None); if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar)) { DamagePreviewOverlay damagePreviewOverlay = ((Component)((AllyCardController)componentInChildren).healthBar).GetComponent(); if (flag4) { if (!Object.op_Implicit((Object)(object)damagePreviewOverlay)) { damagePreviewOverlay = ((Component)((AllyCardController)componentInChildren).healthBar).gameObject.AddComponent(); } if ((Object)(object)passenger != (Object)null) { damagePreviewOverlay.SetTarget(passenger, bagController); } } else if (Object.op_Implicit((Object)(object)damagePreviewOverlay)) { Object.Destroy((Object)(object)damagePreviewOverlay); } } ToggleSlotElements(slot, isCenter); SetSlotNumberLabel(slot, slotIndex, totalCount); } private void ToggleSlotElements(GameObject slot, bool isCenter) { BaggedCardController componentInChildren = slot.GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)componentInChildren)) { return; } bool active = (isCenter ? PluginConfig.Instance.CenterSlotShowIcon.Value : PluginConfig.Instance.SideSlotShowIcon.Value); bool active2 = (isCenter ? PluginConfig.Instance.CenterSlotShowWeightIcon.Value : PluginConfig.Instance.SideSlotShowWeightIcon.Value); bool active3 = (isCenter ? PluginConfig.Instance.CenterSlotShowName.Value : PluginConfig.Instance.SideSlotShowName.Value); bool active4 = (isCenter ? PluginConfig.Instance.CenterSlotShowHealthBar.Value : PluginConfig.Instance.SideSlotShowHealthBar.Value); bool active5 = (isCenter ? PluginConfig.Instance.CenterSlotShowSlotNumber.Value : PluginConfig.Instance.SideSlotShowSlotNumber.Value); if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).portraitIconImage)) { ((Component)((AllyCardController)componentInChildren).portraitIconImage).gameObject.SetActive(true); } RawImage portraitIconImage = ((AllyCardController)componentInChildren).portraitIconImage; LayoutElement val = ((portraitIconImage != null) ? ((Component)portraitIconImage).GetComponent() : null); if (Object.op_Implicit((Object)(object)val)) { ((Component)val).gameObject.SetActive(active); } ChildLocator component = slot.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { Transform val2 = component.FindChild("WeightIcon"); if (Object.op_Implicit((Object)(object)val2)) { ((Component)val2).gameObject.SetActive(active2); Transform obj = val2.Find("WeightUnitLabel"); TextMeshProUGUI val3 = ((obj != null) ? ((Component)obj).GetComponent() : null); if (Object.op_Implicit((Object)(object)val3)) { ((Component)val3).gameObject.SetActive(false); } } } if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).nameLabel)) { ((Component)((AllyCardController)componentInChildren).nameLabel).gameObject.SetActive(active3); } if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).healthBar)) { ((Component)((AllyCardController)componentInChildren).healthBar).gameObject.SetActive(active4); } if (Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).portraitIconImage)) { Transform val4 = ((Component)((AllyCardController)componentInChildren).portraitIconImage).transform.Find("SlotNumberBadge"); if (Object.op_Implicit((Object)(object)val4)) { ((Component)val4).gameObject.SetActive(active5); } } } private void SetSlotNumberLabel(GameObject slot, int slotIndex, int totalCount) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Expected O, but got Unknown //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) BaggedCardController componentInChildren = slot.GetComponentInChildren(); if (!Object.op_Implicit((Object)(object)componentInChildren) || !Object.op_Implicit((Object)(object)((AllyCardController)componentInChildren).portraitIconImage)) { return; } Transform transform = ((Component)((AllyCardController)componentInChildren).portraitIconImage).transform; Transform val = transform.Find("SlotNumberBadge"); TextMeshProUGUI val2 = null; if (Object.op_Implicit((Object)(object)val)) { val2 = ((Component)val).GetComponentInChildren(); } else { GameObject val3 = new GameObject("SlotNumberBadge"); val3.transform.SetParent(transform, false); RectTransform val4 = val3.AddComponent(); val4.anchorMin = new Vector2(1f, 1f); val4.anchorMax = new Vector2(1f, 1f); val4.pivot = new Vector2(1f, 1f); val4.sizeDelta = new Vector2(16f, 16f); val4.anchoredPosition = new Vector2(-2f, -2f); Image val5 = val3.AddComponent(); ((Graphic)val5).color = new Color(0f, 0f, 0f, 0.85f); ((Graphic)val5).raycastTarget = false; Texture2D val6 = Addressables.LoadAssetAsync((object)"RoR2/Base/UI/texDetailPanel.png").WaitForCompletion(); if (Object.op_Implicit((Object)(object)val6)) { val5.sprite = Sprite.Create(val6, new Rect(0f, 0f, (float)((Texture)val6).width, (float)((Texture)val6).height), new Vector2(0.5f, 0.5f)); val5.type = (Type)1; } GameObject val7 = new GameObject("Text"); val7.transform.SetParent(val3.transform, false); val2 = val7.AddComponent(); ((TMP_Text)val2).font = HGTextMeshProUGUI.defaultLanguageFont; ((TMP_Text)val2).fontSize = 12f; ((TMP_Text)val2).fontStyle = (FontStyles)1; ((TMP_Text)val2).alignment = (TextAlignmentOptions)514; ((Graphic)val2).color = Color.white; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).enableWordWrapping = false; ((TMP_Text)val2).overflowMode = (TextOverflowModes)0; RectTransform component = ((Component)val2).GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = new Vector2(1f, 0f); component.offsetMax = new Vector2(-1f, 0f); } if ((Object)(object)val == (Object)null) { val = transform.Find("SlotNumberBadge"); } if (Object.op_Implicit((Object)(object)val2) && Object.op_Implicit((Object)(object)val)) { if (slotIndex > 0) { ((TMP_Text)val2).text = $"{slotIndex}"; bool active = (((Object)(object)slot == (Object)(object)centerInstance) ? PluginConfig.Instance.CenterSlotShowSlotNumber.Value : PluginConfig.Instance.SideSlotShowSlotNumber.Value); ((Component)val).gameObject.SetActive(active); } else { ((Component)val).gameObject.SetActive(false); } } } public static void ApplyWeightIconTransform(GameObject slot) { BaggedObjectCarousel componentInParent = slot.GetComponentInParent(); if (Object.op_Implicit((Object)(object)componentInParent)) { ((MonoBehaviour)componentInParent).StartCoroutine(ApplyWeightIconTransformDelayed(slot)); } else { ApplyWeightIconTransformImmediate(slot); } } [IteratorStateMachine(typeof(d__48))] private static IEnumerator ApplyWeightIconTransformDelayed(GameObject slot) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__48(0) { slot = slot }; } private static void ApplyWeightIconTransformImmediate(GameObject slot) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) ChildLocator component = slot.GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return; } Transform val = component.FindChild("WeightIcon"); if (Object.op_Implicit((Object)(object)val)) { LayoutElement component2 = ((Component)val).GetComponent(); if (Object.op_Implicit((Object)(object)component2)) { component2.ignoreLayout = true; } if (PluginConfig.Instance.UseNewWeightIcon.Value) { val.localPosition = new Vector3(-23f, 1.5f, 0f); val.localRotation = Quaternion.identity; } else { val.localPosition = new Vector3(-15.4757f, 0.1f, 0f); val.localRotation = Quaternion.Euler(0f, 0f, 270f); } } } private static Color GetGradientColor(float percentage, Color start, Color mid, Color end) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //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) //IL_0019: Unknown result type (might be due to invalid IL or missing references) percentage = Mathf.Clamp01(percentage); if (percentage <= 0.5f) { return Color.Lerp(start, mid, percentage * 2f); } return Color.Lerp(mid, end, (percentage - 0.5f) * 2f); } } public class BaggedObjectInfoUIController : MonoBehaviour { private GameObject _uiPanel; private HGTextMeshProUGUI _statsText; private CharacterBody _body; private DrifterBagController _bagController; private HUD? _hud; private bool _cachedEnableBaggedObjectInfo; private PropertyInfo? _cachedInputPlayerProperty; private FieldInfo? _cachedInputPlayerField; private MethodInfo? _cachedGetButtonMethod; private bool _reflectionCacheInitialized; private static readonly object[] _getButtonArgs = new object[1] { "info" }; private void Start() { _body = ((Component)this).GetComponent(); _bagController = ((Component)this).GetComponent(); _cachedEnableBaggedObjectInfo = PluginConfig.Instance.EnableBaggedObjectInfo.Value; } private void Update() { if ((Object)(object)_body == (Object)null || (Object)(object)_bagController == (Object)null) { return; } if (_cachedEnableBaggedObjectInfo != PluginConfig.Instance.EnableBaggedObjectInfo.Value) { _cachedEnableBaggedObjectInfo = PluginConfig.Instance.EnableBaggedObjectInfo.Value; SetUIVisible(visible: false); if (!_cachedEnableBaggedObjectInfo) { return; } } if (!_cachedEnableBaggedObjectInfo && !HudEditorManager.IsEditorActive) { SetUIVisible(visible: false); return; } if ((Object)(object)_hud != (Object)null && (Object)(object)_hud.targetBodyObject != (Object)(object)((Component)_body).gameObject) { SetUIVisible(visible: false); _hud = null; } if ((Object)(object)_hud == (Object)null) { foreach (HUD readOnlyInstance in HUD.readOnlyInstanceList) { if (Object.op_Implicit((Object)(object)readOnlyInstance) && (Object)(object)readOnlyInstance.targetBodyObject == (Object)(object)((Component)_body).gameObject) { _hud = readOnlyInstance; InitializeUI(readOnlyInstance.mainContainer); break; } } } if (!((Object)(object)_hud != (Object)null) || !((Object)(object)_uiPanel != (Object)null)) { return; } bool flag = false; if (_hud.localUserViewer != null) { if (!_reflectionCacheInitialized) { Type type = ((object)_hud.localUserViewer).GetType(); _cachedInputPlayerProperty = type.GetProperty("inputPlayer"); if (_cachedInputPlayerProperty == null) { _cachedInputPlayerField = type.GetField("inputPlayer"); } _reflectionCacheInitialized = true; } object obj = _cachedInputPlayerProperty?.GetValue(_hud.localUserViewer) ?? _cachedInputPlayerField?.GetValue(_hud.localUserViewer); if (obj != null) { if ((object)_cachedGetButtonMethod == null) { _cachedGetButtonMethod = obj.GetType().GetMethod("GetButton", new Type[1] { typeof(string) }); } if (_cachedGetButtonMethod != null) { flag = (bool)_cachedGetButtonMethod.Invoke(obj, _getButtonArgs); } } } if (HudEditorManager.IsEditorActive) { flag = true; } if (flag) { UpdateStatsDisplay(); SetUIVisible(visible: true); } else { SetUIVisible(visible: false); } } private void InitializeUI(GameObject parentContainer) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Expected O, but got Unknown //IL_0143: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_uiPanel != (Object)null)) { _uiPanel = new GameObject("BaggedObjectInfoPanel"); _uiPanel.transform.SetParent(parentContainer.transform, false); RectTransform val = _uiPanel.AddComponent(); val.anchorMin = new Vector2(0f, 0.5f); val.anchorMax = new Vector2(0f, 0.5f); val.pivot = new Vector2(0f, 0.5f); VerticalLayoutGroup val2 = _uiPanel.AddComponent(); ((LayoutGroup)val2).padding = new RectOffset(10, 10, 10, 10); ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false; ((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true; ContentSizeFitter val3 = _uiPanel.AddComponent(); val3.horizontalFit = (FitMode)2; val3.verticalFit = (FitMode)2; ApplyConfigValues(val); GameObject val4 = new GameObject("StatsText"); val4.transform.SetParent(_uiPanel.transform, false); RectTransform val5 = val4.AddComponent(); _statsText = val4.AddComponent(); ((TMP_Text)_statsText).fontSize = 20f; ((TMP_Text)_statsText).alignment = (TextAlignmentOptions)257; ((Graphic)_statsText).color = PluginConfig.Instance.BaggedObjectInfoColor.Value; ((TMP_Text)_statsText).enableWordWrapping = true; ((TMP_Text)_statsText).richText = true; HudDraggable hudDraggable = _uiPanel.AddComponent(); hudDraggable.ElementType = HudElementType.StatsPanel; hudDraggable.XConfig = PluginConfig.Instance.BaggedObjectInfoX; hudDraggable.YConfig = PluginConfig.Instance.BaggedObjectInfoY; hudDraggable.ScaleConfig = PluginConfig.Instance.BaggedObjectInfoScale; SetUIVisible(visible: false); } } private void ApplyConfigValues(RectTransform rectTransform) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) rectTransform.anchoredPosition = new Vector2(PluginConfig.Instance.BaggedObjectInfoX.Value, PluginConfig.Instance.BaggedObjectInfoY.Value); ((Transform)rectTransform).localScale = Vector3.one * PluginConfig.Instance.BaggedObjectInfoScale.Value; } private void UpdateStatsDisplay(bool showFullStats = true) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_statsText == (Object)null || (Object)(object)_uiPanel == (Object)null || DrifterBossGrabPlugin._isSwappingPassengers) { return; } Transform transform = _uiPanel.transform; RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val != null) { ApplyConfigValues(val); ((Graphic)_statsText).color = PluginConfig.Instance.BaggedObjectInfoColor.Value; } BaggedObjectStateData aggregateState = StateCalculator.GetAggregateState(_bagController); float baggedMass = aggregateState.baggedMass; float num = aggregateState.movespeedPenalty * 100f; float num2 = CapacityScalingSystem.CalculateMassCapacity(_bagController); float num3 = CapacityScalingSystem.CalculateMassCapacity(_bagController); bool flag = !PluginConfig.Instance.EnableBalance.Value || PluginConfig.Instance.MassCapacityFormula.Value.Trim() == "0"; bool flag2 = PluginConfig.Instance.BottomlessBagEnabled.Value && PluginConfig.Instance.IsAddedCapacityInfinite; string text; if (flag) { int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(_bagController); int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(_bagController); if (flag2) { text = $"{currentBaggedCount}/∞"; } else { int num4 = Math.Max(1, utilityMaxStock); text = $"{currentBaggedCount}/{num4}"; } } else { text = ((num3 >= 100000f) ? "INF" : num3.ToString("F0")); } GameObject mainSeatObject = BagPatches.GetMainSeatObject(_bagController); float num5 = ((num2 > 0f) ? (baggedMass / num2) : 0f); float effectiveCoefficient = SlamDamageCalculator.GetEffectiveCoefficient(_bagController); float num6 = _body.damage * effectiveCoefficient; float itemDamageMultiplier = GetItemDamageMultiplier(); float num7 = num6 * itemDamageMultiplier; float num8 = num7; if (_body.crit >= 100f) { num8 = num7 * _body.critMultiplier; } float num9 = num8; float num10 = 0f; if ((Object)(object)mainSeatObject != (Object)null) { CharacterBody component = mainSeatObject.GetComponent(); JunkCubeController component2 = mainSeatObject.GetComponent(); SpecialObjectAttributes component3 = mainSeatObject.GetComponent(); if ((Object)(object)component2 != (Object)null && component2.ActivationCount > 0) { num9 = 1f; } else if ((Object)(object)component != (Object)null) { num10 = component.armor; float num11 = num6 * GetItemDamageMultiplier(component); if (_body.crit >= 100f) { num11 *= _body.critMultiplier; } float num12 = ((num10 >= 0f) ? (100f / (100f + num10)) : (2f - 100f / (100f - num10))); num9 = num11 * num12; } else if ((Object)(object)component3 != (Object)null && component3.maxDurability > 0) { num9 = 1f; } } string text2 = "Bag Totals\n"; text2 = ((!flag) ? (text2 + $"Total Mass: {baggedMass:F0} / {text}\n") : (text2 + "Capacity: " + text + "\n")); text2 = text2 + $"Speed Penalty: {num:F1}%\n" + $"Damage Coef: {effectiveCoefficient:F2} ({num8:F0})\n" + $"To Bagged Obj: {num9:F0}\n"; if (!showFullStats) { ((TMP_Text)_statsText).text = text2; return; } if ((Object)(object)mainSeatObject == (Object)null) { ((TMP_Text)_statsText).text = "Bagged Object\nEmpty\n\n" + text2; return; } BaggedObjectStateData individualObjectState = StateCalculator.GetIndividualObjectState(_bagController, mainSeatObject); if (individualObjectState == null || (Object)(object)individualObjectState.targetObject == (Object)null) { ((TMP_Text)_statsText).text = "Bagged Object\nLoading stats...\n\n" + text2; return; } string text3 = ((Object)mainSeatObject).name.Replace("(Clone)", ""); if ((Object)(object)individualObjectState.targetBody != (Object)null && !string.IsNullOrEmpty(individualObjectState.targetBody.GetDisplayName())) { text3 = individualObjectState.targetBody.GetDisplayName(); } float baggedMass2 = individualObjectState.baggedMass; int junkSpawnCount = individualObjectState.junkSpawnCount; string text4 = "N/A"; float num13 = individualObjectState.breakoutTime; float num14 = individualObjectState.elapsedBreakoutTime; float breakoutAttempts = individualObjectState.breakoutAttempts; if (!AdditionalSeatBreakoutTimer.CanBreakout(mainSeatObject)) { num13 = 0f; } if (num13 > 0f) { if (num14 >= num13) { num14 %= num13; } float num15 = num13 - num14; text4 = $"{num15:F1} / {num13:F1}s"; if (breakoutAttempts > 0f) { text4 += $" ({breakoutAttempts:F0})"; } } ((TMP_Text)_statsText).text = "" + text3 + "\n" + $"Mass: {baggedMass2:F1}\n" + $"Junk on Drop: {junkSpawnCount} cubes\n" + "Breakout: " + text4 + "\n" + $"AtkSpd: {individualObjectState.attackSpeedStat:F2}\n" + $"Dmg: {individualObjectState.damageStat:F2}\n" + $"Crit: {individualObjectState.critStat:F2}%\n" + $"MvSpd: {individualObjectState.moveSpeedStat:F2}\n" + $"Armor: {individualObjectState.armorStat:F2}\n" + $"Regen: {individualObjectState.regenStat:F2}\n\n" + text2; } private void SetUIVisible(bool visible) { if ((Object)(object)_uiPanel != (Object)null && _uiPanel.activeSelf != visible) { _uiPanel.SetActive(visible); } } private float GetItemDamageMultiplier(CharacterBody? targetBody = null) { if ((Object)(object)_body == (Object)null || (Object)(object)_body.inventory == (Object)null) { return 1f; } float num = 1f; int itemCountEffective = _body.inventory.GetItemCountEffective(Items.FragileDamageBonus); if (itemCountEffective > 0) { num *= 1f + (float)itemCountEffective * 0.2f; } int itemCountEffective2 = _body.inventory.GetItemCountEffective(Items.NearbyDamageBonus); if (itemCountEffective2 > 0) { num *= 1f + (float)itemCountEffective2 * 0.2f; } if ((Object)(object)targetBody != (Object)null && (Object)(object)targetBody.healthComponent != (Object)null) { float num2 = targetBody.healthComponent.combinedHealth / targetBody.healthComponent.fullCombinedHealth; if (num2 >= 0.9f) { int itemCountEffective3 = _body.inventory.GetItemCountEffective(Items.Crowbar); if (itemCountEffective3 > 0) { num *= 1f + 0.75f * (float)itemCountEffective3; } } } return num; } private void OnDestroy() { if ((Object)(object)_uiPanel != (Object)null) { Object.Destroy((Object)(object)_uiPanel); } } } public class BaggedObjectUIController : MonoBehaviour { public GameObject? carouselPrefab; public GameObject? slotPrefab; private GameObject? carouselInstance; private GameObject? aboveInstance; private GameObject? centerInstance; private GameObject? belowInstance; private void Start() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown //IL_0104: 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_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)slotPrefab)) { return; } CharacterBody component = ((Component)this).GetComponent(); if ((Object)(object)component == (Object)null || !((Object)component).name.StartsWith("DrifterBody") || !((NetworkBehaviour)component).hasAuthority) { return; } LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if (firstLocalUser == null) { return; } CameraRigController cameraRigController = firstLocalUser.cameraRigController; HUD val = ((cameraRigController != null) ? cameraRigController.hud : null); if (Object.op_Implicit((Object)(object)val) && Object.op_Implicit((Object)(object)val.mainContainer)) { HUD val2 = val; Transform val3 = FindDeepChild(val2.mainContainer.transform, "DisplayRoot"); if (Object.op_Implicit((Object)(object)val3)) { carouselInstance = new GameObject("BaggedObjectCarousel"); carouselInstance.transform.SetParent(val3, false); RectTransform val4 = carouselInstance.AddComponent(); BaggedObjectCarousel baggedObjectCarousel = carouselInstance.AddComponent(); baggedObjectCarousel.slotPrefab = slotPrefab; HudDraggable hudDraggable = carouselInstance.AddComponent(); hudDraggable.ElementType = HudElementType.MainSlot; hudDraggable.DragSizePadding = new Vector2(75f, 50f); hudDraggable.DragOffset = new Vector2(-40f, -20f); hudDraggable.XConfig = PluginConfig.Instance.CenterSlotX; hudDraggable.YConfig = PluginConfig.Instance.CenterSlotY; hudDraggable.ScaleConfig = PluginConfig.Instance.CenterSlotScale; aboveInstance = Object.Instantiate(slotPrefab, carouselInstance.transform); ((Object)aboveInstance).name = "aboveSlot"; aboveInstance.GetComponent().anchoredPosition = new Vector2(0f, 0f - PluginConfig.Instance.CarouselSpacing.Value); aboveInstance.SetActive(false); centerInstance = Object.Instantiate(slotPrefab, carouselInstance.transform); ((Object)centerInstance).name = "centerSlot"; centerInstance.GetComponent().anchoredPosition = new Vector2(0f, 0f); centerInstance.SetActive(false); belowInstance = Object.Instantiate(slotPrefab, carouselInstance.transform); ((Object)belowInstance).name = "belowSlot"; belowInstance.GetComponent().anchoredPosition = new Vector2(0f, PluginConfig.Instance.CarouselSpacing.Value); belowInstance.SetActive(false); BaggedObjectCarousel.ApplyWeightIconTransform(aboveInstance); BaggedObjectCarousel.ApplyWeightIconTransform(centerInstance); BaggedObjectCarousel.ApplyWeightIconTransform(belowInstance); } } } private void OnDestroy() { if (Object.op_Implicit((Object)(object)carouselInstance)) { Object.Destroy((Object)(object)carouselInstance); } } private 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; } } [HarmonyPatch] internal static class RiskOfOptionsDummyPatches { [HarmonyPatch(typeof(ModOptionPanelController), "OptionChanged")] [HarmonyPatch(typeof(ModOptionPanelController), "CheckIfRestartNeeded")] [HarmonyPatch(typeof(ModOptionPanelController), "ShowRestartWarning")] [HarmonyPatch(typeof(ModOptionPanelController), "HideRestartWarning")] [HarmonyPrefix] internal static bool Prefix(ModOptionPanelController __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)((Component)__instance).gameObject != (Object)null && ((Object)((Component)__instance).gameObject).name == "DrifterHUD_DummyController") { return false; } return true; } } public class HudContextMenu : MonoBehaviour { private static GameObject? _menuInstance; public static void Show(HudDraggable draggable) { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e5: Expected O, but got Unknown //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0382: Unknown result type (might be due to invalid IL or missing references) //IL_038e: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_03cd: Unknown result type (might be due to invalid IL or missing references) //IL_03ed: Unknown result type (might be due to invalid IL or missing references) //IL_03f4: Expected O, but got Unknown //IL_041d: Unknown result type (might be due to invalid IL or missing references) //IL_0433: Unknown result type (might be due to invalid IL or missing references) //IL_0449: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_047a: Unknown result type (might be due to invalid IL or missing references) //IL_0484: Expected O, but got Unknown //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_menuInstance != (Object)null) { Object.Destroy((Object)(object)_menuInstance); } Canvas componentInParent = ((Component)draggable).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { return; } if (PluginConfig.Instance.SelectedHudElement != null) { PluginConfig.Instance.SelectedHudElement.Value = draggable.ElementType; } _menuInstance = new GameObject("HudContextMenu"); _menuInstance.AddComponent(); _menuInstance.transform.SetParent(((Component)componentInParent).transform, false); RectTransform val = _menuInstance.AddComponent(); float num = 0f; float num2 = 1f; if (Input.mousePosition.x > (float)Screen.width * 0.5f) { num = 1f; } if (Input.mousePosition.y < (float)Screen.height * 0.5f) { num2 = 0f; } val.pivot = new Vector2(num, num2); Transform transform = ((Component)componentInParent).transform; Vector2 val2 = default(Vector2); RectTransformUtility.ScreenPointToLocalPointInRectangle((RectTransform)(object)((transform is RectTransform) ? transform : null), Vector2.op_Implicit(Input.mousePosition), componentInParent.worldCamera, ref val2); float num3 = 516f; float num4 = 348f; Transform transform2 = ((Component)componentInParent).transform; RectTransform val3 = (RectTransform)(object)((transform2 is RectTransform) ? transform2 : null); if ((Object)(object)val3 != (Object)null) { Rect rect = val3.rect; float width = ((Rect)(ref rect)).width; rect = val3.rect; float height = ((Rect)(ref rect)).height; float num5; float num6; if (num == 0f) { num5 = (0f - width) * 0.5f; num6 = width * 0.5f - num3; } else { num5 = (0f - width) * 0.5f + num3; num6 = width * 0.5f; } float num7; float num8; if (num2 == 0f) { num7 = (0f - height) * 0.5f; num8 = height * 0.5f - num4; } else { num7 = (0f - height) * 0.5f + num4; num8 = height * 0.5f; } if (num5 > num6) { float num9 = num5; num5 = num6; num6 = num9; } if (num7 > num8) { float num10 = num7; num7 = num8; num8 = num10; } val2.x = Mathf.Clamp(val2.x, num5, num6); val2.y = Mathf.Clamp(val2.y, num7, num8); } val.anchoredPosition = val2; Image val4 = _menuInstance.AddComponent(); ((Graphic)val4).color = new Color(0.1f, 0.1f, 0.1f, 0.98f); VerticalLayoutGroup val5 = _menuInstance.AddComponent(); ((LayoutGroup)val5).padding = new RectOffset(8, 8, 8, 8); ((HorizontalOrVerticalLayoutGroup)val5).spacing = 2f; ((HorizontalOrVerticalLayoutGroup)val5).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val5).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val5).childForceExpandHeight = false; ContentSizeFitter val6 = _menuInstance.AddComponent(); val6.horizontalFit = (FitMode)2; val6.verticalFit = (FitMode)2; string titleText = draggable.ElementType.ToString(); if (draggable.ElementType == HudElementType.MainSlot || draggable.ElementType == HudElementType.SideSlots) { titleText = "Carousel"; } AddHeader(titleText); GameObject val7 = new GameObject("ScrollView"); val7.transform.SetParent(_menuInstance.transform, false); RectTransform val8 = val7.AddComponent(); LayoutElement val9 = val7.AddComponent(); val9.preferredHeight = 300f; val9.preferredWidth = 500f; ScrollRect val10 = val7.AddComponent(); val10.horizontal = false; val10.vertical = true; val10.scrollSensitivity = 20f; GameObject val11 = new GameObject("Viewport"); val11.transform.SetParent(val7.transform, false); RectTransform val12 = val11.AddComponent(); val12.anchorMin = Vector2.zero; val12.anchorMax = Vector2.one; val12.sizeDelta = Vector2.zero; val12.pivot = new Vector2(0f, 1f); Image val13 = val11.AddComponent(); ((Graphic)val13).color = new Color(1f, 1f, 1f, 0.01f); Mask val14 = val11.AddComponent(); val14.showMaskGraphic = false; GameObject val15 = new GameObject("Content"); val15.transform.SetParent(val11.transform, false); RectTransform val16 = val15.AddComponent(); val16.anchorMin = new Vector2(0f, 1f); val16.anchorMax = new Vector2(1f, 1f); val16.pivot = new Vector2(0f, 1f); val16.sizeDelta = new Vector2(0f, 0f); VerticalLayoutGroup val17 = val15.AddComponent(); ((LayoutGroup)val17).padding = new RectOffset(10, 10, 5, 5); ((HorizontalOrVerticalLayoutGroup)val17).spacing = 8f; ((HorizontalOrVerticalLayoutGroup)val17).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val17).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val17).childForceExpandWidth = true; ((HorizontalOrVerticalLayoutGroup)val17).childForceExpandHeight = false; ContentSizeFitter val18 = val15.AddComponent(); val18.horizontalFit = (FitMode)0; val18.verticalFit = (FitMode)2; val10.viewport = val12; val10.content = val16; PopulateOptions(draggable.ElementType, val15.transform); _menuInstance.transform.SetAsLastSibling(); } private static void AddHeader(string titleText) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_menuInstance == (Object)null)) { GameObject val = new GameObject("Header"); val.transform.SetParent(_menuInstance.transform, false); HorizontalLayoutGroup val2 = val.AddComponent(); ((HorizontalOrVerticalLayoutGroup)val2).childControlWidth = true; ((HorizontalOrVerticalLayoutGroup)val2).childControlHeight = true; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandWidth = false; ((HorizontalOrVerticalLayoutGroup)val2).childForceExpandHeight = false; ((LayoutGroup)val2).padding = new RectOffset(20, 5, 5, 5); val.AddComponent().verticalFit = (FitMode)2; GameObject val3 = new GameObject("Title"); val3.transform.SetParent(val.transform, false); HGTextMeshProUGUI val4 = val3.AddComponent(); ((TMP_Text)val4).text = "" + titleText + " Config"; ((TMP_Text)val4).fontSize = 20f; ((Graphic)val4).color = new Color(0.9f, 0.8f, 0.5f); } } private static void PopulateOptions(HudElementType elementType, Transform contentParent) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Expected O, but got Unknown //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Expected O, but got Unknown //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_042c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_menuInstance == (Object)null) { return; } try { FieldInfo field = typeof(ModSettingsManager).GetField("OptionCollection", BindingFlags.Static | BindingFlags.NonPublic); if (field == null) { return; } object value = field.GetValue(null); if (value == null) { return; } MethodInfo method = value.GetType().GetMethod("GetOption", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null); if (method == null) { Debug.LogError((object)"[HudContextMenu] Could not find GetOption method on OptionCollection."); return; } GameObject val = new GameObject("DummyControllerContainer"); val.transform.SetParent(_menuInstance.transform, false); val.SetActive(false); _menuInstance.AddComponent(); ModOptionPanelController val2 = val.AddComponent(); foreach (KeyValuePair item in PluginConfig.HudSettingToSubTab) { bool flag = false; HudElementType[] value2 = item.Value; foreach (HudElementType hudElementType in value2) { if (hudElementType == elementType || elementType == HudElementType.All) { flag = true; break; } bool flag2 = elementType == HudElementType.MainSlot || elementType == HudElementType.SideSlots; bool flag3 = hudElementType == HudElementType.MainSlot || hudElementType == HudElementType.SideSlots || hudElementType == HudElementType.DamagePreview || hudElementType == HudElementType.WeightIcon; if (flag2 && flag3) { flag = true; break; } } if (!flag) { continue; } string key = item.Key; if (key.Contains("ENABLE_HUD_EDITOR") || key.Contains("HUD_FILTER")) { continue; } try { object? obj = method.Invoke(value, new object[1] { key }); BaseOption val3 = (BaseOption)((obj is BaseOption) ? obj : null); if (val3 == null) { continue; } GameObject prefabForIdentifier = GetPrefabForIdentifier(key); if ((Object)(object)prefabForIdentifier != (Object)null) { GameObject val4 = new GameObject("Dummy"); val4.SetActive(false); GameObject val5 = Object.Instantiate(prefabForIdentifier, val4.transform); val5.SetActive(false); GameObject val6 = val3.CreateOptionGameObject(val5, contentParent); Object.Destroy((Object)(object)val4); if (!((Object)(object)val6 != (Object)null)) { continue; } val6.transform.localScale = Vector3.one; val6.transform.localPosition = Vector3.zero; LayoutElement val7 = val6.GetComponent(); if ((Object)(object)val7 == (Object)null) { val7 = val6.AddComponent(); } val7.minHeight = 45f; val7.preferredHeight = 45f; val7.flexibleHeight = 0f; ModSetting componentInChildren = val6.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.optionController = val2; } val6.SetActive(true); if (((Object)((Component)val2).gameObject).name != "DrifterHUD_DummyController") { ((Object)((Component)val2).gameObject).name = "DrifterHUD_DummyController"; } if (!((Object)(object)componentInChildren != (Object)null)) { continue; } ModSettingsBool val8 = (ModSettingsBool)(object)((componentInChildren is ModSettingsBool) ? componentInChildren : null); if (!((Object)(object)val8 != (Object)null)) { continue; } if ((Object)(object)val8.checkBoxTrue == (Object)null || (Object)(object)val8.checkBoxFalse == (Object)null) { ModSettingsBool[] array = Object.FindObjectsByType((FindObjectsSortMode)0); ModSettingsBool[] array2 = array; foreach (ModSettingsBool val9 in array2) { if ((Object)(object)val9 != (Object)(object)val8 && (Object)(object)val9.checkBoxTrue != (Object)null && (Object)(object)val9.checkBoxFalse != (Object)null) { val8.checkBoxTrue = val9.checkBoxTrue; val8.checkBoxFalse = val9.checkBoxFalse; break; } } if ((Object)(object)val8.checkBoxTrue == (Object)null) { GameObject[] array3 = Resources.FindObjectsOfTypeAll(); GameObject[] array4 = array3; foreach (GameObject val10 in array4) { if (((Object)val10).name == "SettingsEntryButton, Bool (Audio Focus)") { CarouselController componentInChildren2 = val10.GetComponentInChildren(); if ((Object)(object)componentInChildren2 != (Object)null && componentInChildren2.choices.Length >= 2) { val8.checkBoxFalse = componentInChildren2.choices[0].customSprite; val8.checkBoxTrue = componentInChildren2.choices[1].customSprite; break; } } } } } if ((Object)(object)val8.checkBox != (Object)null) { val8.checkBox.sprite = (val8.IsChecked ? val8.checkBoxTrue : val8.checkBoxFalse); ((Graphic)val8.checkBox).color = Color.white; } continue; } Debug.LogWarning((object)("[HudContextMenu] Prefab is null for identifier: " + key)); } catch (Exception ex) { Debug.LogWarning((object)("[HudContextMenu] Failed to load option for " + key + ": " + ex.Message)); } } } catch (Exception arg) { Debug.LogError((object)$"[HudContextMenu] Error populating options: {arg}"); } } private static GameObject? GetPrefabForIdentifier(string identifier) { if (identifier.EndsWith(".CHECKBOX")) { return Prefabs.boolButton; } if (identifier.EndsWith(".COLOR")) { return Prefabs.colorPickerButton; } if (identifier.EndsWith(".FLOAT_FIELD")) { return Prefabs.floatFieldButton; } if (identifier.EndsWith(".STEP_SLIDER")) { return Prefabs.stepSliderButton; } if (identifier.EndsWith(".INT_SLIDER")) { return Prefabs.intSliderButton; } if (identifier.EndsWith(".CHOICE")) { return RuntimePrefabManager.Get().ChoiceButton; } return null; } private void Update() { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) if (Input.GetKeyDown((KeyCode)27)) { Object.Destroy((Object)(object)((Component)this).gameObject); } else { if (!Input.GetMouseButtonDown(0) && !Input.GetMouseButtonDown(1)) { return; } RectTransform component = ((Component)this).GetComponent(); if (!((Object)(object)component != (Object)null) || RectTransformUtility.RectangleContainsScreenPoint(component, Vector2.op_Implicit(Input.mousePosition))) { return; } PointerEventData val = new PointerEventData(EventSystem.current) { position = Vector2.op_Implicit(Input.mousePosition) }; List list = new List(); EventSystem.current.RaycastAll(val, list); bool flag = false; foreach (RaycastResult item in list) { RaycastResult current = item; if (((RaycastResult)(ref current)).gameObject.transform.IsChildOf(((Component)this).transform) || ((Object)((RaycastResult)(ref current)).gameObject).name.Contains("Color")) { flag = true; break; } } if (!flag) { Object.Destroy((Object)(object)((Component)this).gameObject); } } } } public class HudDraggable : MonoBehaviour, IBeginDragHandler, IEventSystemHandler, IDragHandler, IEndDragHandler, IPointerEnterHandler, IPointerExitHandler, IScrollHandler, IPointerClickHandler { public ConfigEntry? XConfig; public ConfigEntry? YConfig; public ConfigEntry? ScaleConfig; public Vector2 DragSizePadding = Vector2.zero; public Vector2 DragOffset = Vector2.zero; public HudElementType ElementType; private RectTransform? _rectTransform; private Image? _highlight; private Canvas? _rootCanvas; private static Color NormalHighlightColor = new Color(1f, 1f, 1f, 0.2f); private static Color HoverHighlightColor = new Color(1f, 1f, 1f, 0.5f); private static Color DraggingHighlightColor = new Color(1f, 1f, 0f, 0.4f); private bool _isDragging; private bool _isHovering; public bool IsDragging => _isDragging; private void Awake() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) _rectTransform = ((Component)this).GetComponent(); _rootCanvas = ((Component)this).GetComponentInParent(); GameObject val = new GameObject("DraggableHighlight"); val.transform.SetParent(((Component)this).transform, false); _highlight = val.AddComponent(); ((Graphic)_highlight).color = NormalHighlightColor; ((Graphic)_highlight).raycastTarget = true; LayoutElement val2 = val.AddComponent(); val2.ignoreLayout = true; RectTransform rectTransform = ((Graphic)_highlight).rectTransform; rectTransform.anchorMin = Vector2.zero; rectTransform.anchorMax = Vector2.one; rectTransform.sizeDelta = DragSizePadding; rectTransform.anchoredPosition = DragOffset; val.SetActive(false); } private void Update() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) bool isEditorActive = HudEditorManager.IsEditorActive; if ((Object)(object)_highlight != (Object)null && ((Component)_highlight).gameObject.activeSelf != isEditorActive) { ((Component)_highlight).gameObject.SetActive(isEditorActive); if (isEditorActive) { ((Component)_highlight).transform.SetAsLastSibling(); } ((Graphic)_highlight).rectTransform.sizeDelta = DragSizePadding; ((Graphic)_highlight).rectTransform.anchoredPosition = DragOffset; UpdateHighlightColor(); } if (!_isDragging && (Object)(object)_rectTransform != (Object)null) { if (XConfig != null && YConfig != null) { _rectTransform.anchoredPosition = new Vector2(XConfig.Value, YConfig.Value); } if (ScaleConfig != null) { ((Component)this).transform.localScale = Vector3.one * ScaleConfig.Value; } } if (isEditorActive && _isDragging && ScaleConfig != null) { float y = Input.mouseScrollDelta.y; if (y != 0f) { ApplyScale(y); } } } public void OnPointerClick(PointerEventData eventData) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 if (HudEditorManager.IsEditorActive && (int)eventData.button == 1) { HudContextMenu.Show(this); } } public void OnBeginDrag(PointerEventData eventData) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) if (HudEditorManager.IsEditorActive && (int)eventData.button == 0) { _isDragging = true; UpdateHighlightColor(); } } public void OnDrag(PointerEventData eventData) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) if (HudEditorManager.IsEditorActive && !((Object)(object)_rectTransform == (Object)null) && !((Object)(object)_rootCanvas == (Object)null) && (int)eventData.button == 0) { Vector2 val = eventData.delta / _rootCanvas.scaleFactor; RectTransform? rectTransform = _rectTransform; rectTransform.anchoredPosition += val; if (XConfig != null) { XConfig.Value = _rectTransform.anchoredPosition.x; } if (YConfig != null) { YConfig.Value = _rectTransform.anchoredPosition.y; } } } public void OnEndDrag(PointerEventData eventData) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)eventData.button == 0) { _isDragging = false; UpdateHighlightColor(); DrifterBossGrabPlugin? instance = DrifterBossGrabPlugin.Instance; if (instance != null) { ((BaseUnityPlugin)instance).Config.Save(); } } } public void OnPointerEnter(PointerEventData eventData) { _isHovering = true; UpdateHighlightColor(); } public void OnPointerExit(PointerEventData eventData) { _isHovering = false; UpdateHighlightColor(); } public void OnScroll(PointerEventData eventData) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (HudEditorManager.IsEditorActive && ScaleConfig != null) { ApplyScale(eventData.scrollDelta.y); } } private void ApplyScale(float scrollDelta) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) if (ScaleConfig != null) { float num = scrollDelta * 0.05f; float num2 = Mathf.Clamp(ScaleConfig.Value + num, 0.2f, 3f); ScaleConfig.Value = num2; ((Component)this).transform.localScale = Vector3.one * num2; DrifterBossGrabPlugin? instance = DrifterBossGrabPlugin.Instance; if (instance != null) { ((BaseUnityPlugin)instance).Config.Save(); } } } private void UpdateHighlightColor() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_highlight == (Object)null)) { if (_isDragging) { ((Graphic)_highlight).color = DraggingHighlightColor; } else if (_isHovering) { ((Graphic)_highlight).color = HoverHighlightColor; } else { ((Graphic)_highlight).color = NormalHighlightColor; } } } } public class HudEditorManager : MonoBehaviour { private static HudEditorManager? _instance; public static bool IsEditorActive { get; private set; } private void Awake() { if ((Object)(object)_instance != (Object)null) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } _instance = this; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); PluginConfig.Instance.IsHudEditorEnabled.SettingChanged += OnConfigToggleChanged; } private void OnConfigToggleChanged(object sender, EventArgs e) { SetEditorActive(PluginConfig.Instance.IsHudEditorEnabled.Value); } private void Update() { if (IsEditorActive && Input.GetKeyDown((KeyCode)27)) { SetEditorActive(active: false); } } public static void ToggleEditor() { PluginConfig.Instance.IsHudEditorEnabled.Value = !PluginConfig.Instance.IsHudEditorEnabled.Value; } public static void SetEditorActive(bool active) { if (IsEditorActive == active) { return; } IsEditorActive = active; if (PluginConfig.Instance.IsHudEditorEnabled.Value != active) { PluginConfig.Instance.IsHudEditorEnabled.Value = active; } if (active) { Cursor.visible = true; Cursor.lockState = (CursorLockMode)0; Chat.AddMessage("[HUD Editor] Enabled. Drag elements to move, Scroll to resize. Press ESC to exit."); PauseScreenController val = Object.FindAnyObjectByType(); if ((Object)(object)val != (Object)null) { CanvasGroup val2 = ((Component)val).GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = ((Component)val).gameObject.AddComponent(); } val2.alpha = 0f; val2.blocksRaycasts = false; val2.interactable = false; Canvas componentInChildren = ((Component)val).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { ((Behaviour)componentInChildren).enabled = false; } } return; } PauseScreenController val3 = Object.FindAnyObjectByType(); if ((Object)(object)val3 != (Object)null) { CanvasGroup component = ((Component)val3).GetComponent(); if ((Object)(object)component != (Object)null) { component.alpha = 1f; component.blocksRaycasts = true; component.interactable = true; } Canvas componentInChildren2 = ((Component)val3).GetComponentInChildren(); if ((Object)(object)componentInChildren2 != (Object)null) { ((Behaviour)componentInChildren2).enabled = true; } } Chat.AddMessage("[HUD Editor] Disabled. Changes saved."); } private void OnDestroy() { if (PluginConfig.Instance != null && PluginConfig.Instance.IsHudEditorEnabled != null) { PluginConfig.Instance.IsHudEditorEnabled.SettingChanged -= OnConfigToggleChanged; } } } } namespace DrifterBossGrabMod.Balance { public static class CapacityScalingSystem { private const float MinimumMassPercentage = 0.1f; public static int GetTotalCapacity(DrifterBagController? bagController) { if ((Object)(object)bagController == (Object)null) { return 1; } return BagCapacityCalculator.GetUtilityMaxStock(bagController); } public static float CalculateMassCapacity(DrifterBagController? bagController) { if (!PluginConfig.Instance.EnableBalance.Value) { int totalCapacity = GetTotalCapacity(bagController); if (totalCapacity == int.MaxValue) { return float.MaxValue; } return (float)totalCapacity * 700f; } CharacterBody body = ((bagController != null) ? ((Component)bagController).GetComponent() : null); string value = PluginConfig.Instance.MassCapacityFormula.Value; float num = FormulaParser.Evaluate(value, body); if (float.IsNaN(num)) { Log.Warning("[CalculateMassCapacity] Formula '" + value + "' returned NaN. Returning base mass capacity."); return DrifterBagController.maxMass; } if (num <= 0f && !float.IsPositiveInfinity(num)) { Log.Debug($"[CalculateMassCapacity] Formula returned {num}, mass capacity is disabled (unlimited)"); return float.MaxValue; } return num; } public static float CalculateMaxMassCapacity(DrifterBagController? bagController) { float num = CalculateMassCapacity(bagController); if (num == float.MaxValue) { return float.MaxValue; } float num2 = (PluginConfig.Instance.EnableBalance.Value ? (1f + PluginConfig.Instance.OverencumbranceMax.Value / 100f) : 1f); return num * num2; } public static void RecalculateCapacity(DrifterBagController? bagController) { if (!((Object)(object)bagController == (Object)null)) { int totalCapacity = GetTotalCapacity(bagController); float num = CalculateMassCapacity(bagController); Log.Debug($"[CapacityScaling] Recalculating capacity: Total={totalCapacity}, MassCapacity={num}"); BagPassengerManager.ForceRecalculateMass(bagController); } } public static void RecalculateState(DrifterBagController? bagController) { if (!((Object)(object)bagController == (Object)null)) { Log.Debug("[CapacityScaling] Recalculating state for bag controller"); BagPassengerManager.ForceRecalculateMass(bagController); } } public static void RecalculateMass(DrifterBagController? bagController) { if (!((Object)(object)bagController == (Object)null)) { Log.Debug("[CapacityScaling] Recalculating mass for bag controller"); BagPassengerManager.ForceRecalculateMass(bagController); } } public static void RecalculatePenalty(DrifterBagController? bagController) { if (!((Object)(object)bagController == (Object)null)) { Log.Debug("[CapacityScaling] Recalculating penalty for bag controller"); BagPassengerManager.ForceRecalculateMass(bagController); } } } public static class CharacterFlagMassBonus { public static float ApplyFlagBonus(GameObject baggedObject, float baseMass) { //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Invalid comparison between Unknown and I4 //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Invalid comparison between Unknown and I4 //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Invalid comparison between Unknown and I4 if ((Object)(object)baggedObject == (Object)null) { return baseMass; } CharacterBody characterBody = baggedObject.GetComponent(); if ((Object)(object)characterBody == (Object)null) { return baseMass; } if (!PluginConfig.Instance.EnableBalance.Value) { return baseMass; } float highestMassBonusPercent = 1f; Dictionary localVars = new Dictionary { { "B", baseMass } }; PluginConfig instance = PluginConfig.Instance; CheckFlag(characterBody.isElite, instance.EliteFlagMultiplier.Value); CheckFlag(characterBody.isBoss, instance.BossFlagMultiplier.Value); CheckFlag(characterBody.isChampion, instance.ChampionFlagMultiplier.Value); CheckFlag(characterBody.isPlayerControlled, instance.PlayerFlagMultiplier.Value); CheckFlag((Object)(object)characterBody.master != (Object)null && (Object)(object)characterBody.master.minionOwnership != (Object)null, instance.MinionFlagMultiplier.Value); CheckFlag((characterBody.bodyFlags & 0x400000) > 0, instance.DroneFlagMultiplier.Value); CheckFlag((characterBody.bodyFlags & 2) > 0, instance.MechanicalFlagMultiplier.Value); CheckFlag((characterBody.bodyFlags & 0x400) > 0, instance.VoidFlagMultiplier.Value); float num = baseMass; float num2 = FormulaParser.Evaluate(instance.AllFlagMultiplier.Value, characterBody, localVars); if (highestMassBonusPercent != 1f || num2 != 1f) { num *= num2 * highestMassBonusPercent; } return num; void CheckFlag(bool condition, string flagMultiplierFormula) { if (condition) { float num3 = FormulaParser.Evaluate(flagMultiplierFormula, characterBody, localVars); if (num3 > 0f) { highestMassBonusPercent = Mathf.Max(highestMassBonusPercent, num3); } } } } } public static class FormulaParser { private enum TokenType { Number, Variable, Operator, Function, LeftParen, RightParen, Comma, UnaryMinus } private readonly struct Token { public readonly TokenType Type; public readonly string Value; public readonly double NumericValue; public Token(TokenType type, string value, double numericValue = 0.0) { Type = type; Value = value; NumericValue = numericValue; } public override string ToString() { return $"{Type}({Value})"; } } private static readonly Dictionary> _rpnCache = new Dictionary>(); private static readonly Dictionary Operators = new Dictionary { ["+"] = (2, false), ["-"] = (2, false), ["*"] = (3, false), ["/"] = (3, false), ["%"] = (3, false), ["^"] = (4, true), ["~"] = (5, true) }; private static readonly HashSet Functions = new HashSet(StringComparer.OrdinalIgnoreCase) { "floor", "ceil", "round", "abs", "sqrt", "log", "ln", "min", "max", "clamp", "sin", "cos", "tan", "sign", "pow" }; private static readonly Dictionary Constants = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["pi"] = Math.PI, ["e"] = Math.E, ["inf"] = double.PositiveInfinity, ["infinity"] = double.PositiveInfinity }; public static float Evaluate(string formula, Dictionary variables) { return Evaluate(formula, variables, suppressExceptions: true); } public static float Evaluate(string formula, CharacterBody? body, Dictionary? localVars = null) { Dictionary variables = FormulaRegistry.GetVariables(body, localVars); return Evaluate(formula, variables); } public static float Evaluate(string formula, Dictionary variables, bool suppressExceptions) { if (string.IsNullOrWhiteSpace(formula)) { return 0f; } try { if (!_rpnCache.TryGetValue(formula, out List value)) { List tokens = Tokenize(formula); value = ShuntingYard(tokens); _rpnCache[formula] = value; } double num = EvaluateRPN(value, variables); if (double.IsNaN(num)) { return 0f; } if (double.IsPositiveInfinity(num)) { return float.MaxValue; } if (double.IsNegativeInfinity(num)) { return float.MinValue; } return (float)num; } catch (Exception ex) { if (suppressExceptions) { Log.Warning("[FormulaParser] Failed to evaluate formula '" + formula + "': " + ex.Message); return 0f; } throw; } } public static int EvaluateInt(string formula, Dictionary variables) { float num = Evaluate(formula, variables); if (float.IsPositiveInfinity(num) || num >= 2.1474836E+09f) { return int.MaxValue; } if (float.IsNegativeInfinity(num) || num <= -2.1474836E+09f) { return int.MinValue; } return (int)Math.Floor(num); } public static string? Validate(string formula) { if (string.IsNullOrWhiteSpace(formula)) { return null; } try { List tokens = Tokenize(formula); ShuntingYard(tokens); return null; } catch (Exception ex) { return ex.Message; } } private static List Tokenize(string formula) { List list = new List(); int i = 0; while (i < formula.Length) { char c = formula[i]; if (char.IsWhiteSpace(c)) { i++; continue; } if (char.IsDigit(c) || (c == '.' && i + 1 < formula.Length && char.IsDigit(formula[i + 1]))) { StringBuilder stringBuilder = new StringBuilder(); for (bool flag = false; i < formula.Length && (char.IsDigit(formula[i]) || (formula[i] == '.' && !flag)); i++) { if (formula[i] == '.') { flag = true; } stringBuilder.Append(formula[i]); } string text = stringBuilder.ToString(); if (!double.TryParse(text, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw new FormatException("Invalid number: '" + text + "'"); } list.Add(new Token(TokenType.Number, text, result)); continue; } if (!char.IsLetter(c)) { switch (c) { case '_': break; case '+': list.Add(new Token(TokenType.Operator, "+")); i++; continue; case '-': if (IsUnaryMinus(list)) { list.Add(new Token(TokenType.UnaryMinus, "~")); } else { list.Add(new Token(TokenType.Operator, "-")); } i++; continue; case '*': list.Add(new Token(TokenType.Operator, "*")); i++; continue; case '/': list.Add(new Token(TokenType.Operator, "/")); i++; continue; case '%': list.Add(new Token(TokenType.Operator, "%")); i++; continue; case '^': list.Add(new Token(TokenType.Operator, "^")); i++; continue; case '(': list.Add(new Token(TokenType.LeftParen, "(")); i++; continue; case ')': list.Add(new Token(TokenType.RightParen, ")")); i++; continue; case ',': list.Add(new Token(TokenType.Comma, ",")); i++; continue; default: throw new FormatException($"Unexpected character: '{c}' at position {i}"); } } StringBuilder stringBuilder2 = new StringBuilder(); for (; i < formula.Length && (char.IsLetterOrDigit(formula[i]) || formula[i] == '_'); i++) { stringBuilder2.Append(formula[i]); } string text2 = stringBuilder2.ToString(); int j; for (j = i; j < formula.Length && char.IsWhiteSpace(formula[j]); j++) { } double value; if (j < formula.Length && formula[j] == '(') { if (!Functions.Contains(text2)) { throw new FormatException("Unknown function: '" + text2 + "'"); } list.Add(new Token(TokenType.Function, text2.ToLowerInvariant())); } else if (Constants.TryGetValue(text2, out value)) { list.Add(new Token(TokenType.Number, text2, value)); } else { list.Add(new Token(TokenType.Variable, text2.ToUpperInvariant())); } } return list; } private static bool IsUnaryMinus(List tokens) { if (tokens.Count == 0) { return true; } Token token = tokens[tokens.Count - 1]; if (token.Type != TokenType.Operator && token.Type != TokenType.UnaryMinus && token.Type != TokenType.LeftParen && token.Type != TokenType.Comma) { return token.Type == TokenType.Function; } return true; } private static List ShuntingYard(List tokens) { List list = new List(); Stack stack = new Stack(); foreach (Token token2 in tokens) { switch (token2.Type) { case TokenType.Number: case TokenType.Variable: list.Add(token2); continue; case TokenType.Function: stack.Push(token2); continue; case TokenType.Comma: while (stack.Count > 0 && stack.Peek().Type != TokenType.LeftParen) { list.Add(stack.Pop()); } if (stack.Count != 0) { continue; } throw new FormatException("Misplaced comma or missing parenthesis"); case TokenType.Operator: case TokenType.UnaryMinus: { string value = token2.Value; var (num, flag) = Operators[value]; while (stack.Count > 0) { Token token = stack.Peek(); if (token.Type == TokenType.LeftParen) { break; } if (token.Type == TokenType.Function) { list.Add(stack.Pop()); continue; } if (!Operators.TryGetValue(token.Value, out (int, bool) value2) || ((flag || num > value2.Item1) && (!flag || num >= value2.Item1))) { break; } list.Add(stack.Pop()); } stack.Push(token2); continue; } case TokenType.LeftParen: stack.Push(token2); continue; case TokenType.RightParen: break; default: continue; } while (stack.Count > 0 && stack.Peek().Type != TokenType.LeftParen) { list.Add(stack.Pop()); } if (stack.Count == 0) { throw new FormatException("Mismatched parentheses: missing '('"); } stack.Pop(); if (stack.Count > 0 && stack.Peek().Type == TokenType.Function) { list.Add(stack.Pop()); } } while (stack.Count > 0) { Token item = stack.Pop(); if (item.Type == TokenType.LeftParen) { throw new FormatException("Mismatched parentheses: missing ')'"); } list.Add(item); } return list; } private static double EvaluateRPN(List rpn, Dictionary variables) { Stack stack = new Stack(); foreach (Token item in rpn) { switch (item.Type) { case TokenType.Number: stack.Push(item.NumericValue); break; case TokenType.Variable: { if (variables.TryGetValue(item.Value, out var value)) { stack.Push(value); break; } throw new FormatException("Unknown variable: '" + item.Value + "'"); } case TokenType.UnaryMinus: if (stack.Count < 1) { throw new FormatException("Invalid expression: not enough operands for unary minus"); } stack.Push(0.0 - stack.Pop()); break; case TokenType.Operator: { if (stack.Count < 2) { throw new FormatException("Invalid expression: not enough operands for operator '" + item.Value + "'"); } double b = stack.Pop(); double a = stack.Pop(); stack.Push(ApplyOperator(item.Value, a, b)); break; } case TokenType.Function: ApplyFunction(item.Value, stack); break; default: throw new FormatException($"Unexpected token in RPN: {item}"); } } if (stack.Count != 1) { throw new FormatException($"Invalid expression: expected 1 result but got {stack.Count}"); } return stack.Pop(); } private static double ApplyOperator(string op, double a, double b) { return op switch { "+" => a + b, "-" => a - b, "*" => a * b, "/" => a / b, "%" => (b == 0.0) ? 0.0 : (a % b), "^" => Math.Pow(a, b), _ => throw new FormatException("Unknown operator: '" + op + "'"), }; } private static void ApplyFunction(string name, Stack stack) { switch (name) { case "floor": RequireArgs(stack, 1, name); stack.Push(Math.Floor(stack.Pop())); break; case "ceil": RequireArgs(stack, 1, name); stack.Push(Math.Ceiling(stack.Pop())); break; case "round": RequireArgs(stack, 1, name); stack.Push(Math.Round(stack.Pop())); break; case "abs": RequireArgs(stack, 1, name); stack.Push(Math.Abs(stack.Pop())); break; case "sqrt": { RequireArgs(stack, 1, name); double num = stack.Pop(); if (num < 0.0) { throw new FormatException("Cannot calculate square root of negative number"); } stack.Push(Math.Sqrt(num)); break; } case "log": RequireArgs(stack, 1, name); stack.Push(Math.Log10(stack.Pop())); break; case "ln": RequireArgs(stack, 1, name); stack.Push(Math.Log(stack.Pop())); break; case "sin": RequireArgs(stack, 1, name); stack.Push(Math.Sin(stack.Pop())); break; case "cos": RequireArgs(stack, 1, name); stack.Push(Math.Cos(stack.Pop())); break; case "tan": RequireArgs(stack, 1, name); stack.Push(Math.Tan(stack.Pop())); break; case "sign": RequireArgs(stack, 1, name); stack.Push(Math.Sign(stack.Pop())); break; case "min": { RequireArgs(stack, 2, name); double val3 = stack.Pop(); double val4 = stack.Pop(); stack.Push(Math.Min(val4, val3)); break; } case "max": { RequireArgs(stack, 2, name); double val = stack.Pop(); double val2 = stack.Pop(); stack.Push(Math.Max(val2, val)); break; } case "pow": { RequireArgs(stack, 2, name); double y = stack.Pop(); double x = stack.Pop(); stack.Push(Math.Pow(x, y)); break; } case "clamp": { RequireArgs(stack, 3, name); double max = stack.Pop(); double min = stack.Pop(); double value = stack.Pop(); stack.Push(Math.Clamp(value, min, max)); break; } default: throw new FormatException("Unknown function: '" + name + "'"); } } private static void RequireArgs(Stack stack, int count, string funcName) { if (stack.Count < count) { throw new FormatException($"Function '{funcName}' requires {count} argument(s) but got {stack.Count}"); } } } public static class FormulaRegistry { private static readonly ConcurrentDictionary _staticVariables = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary> _dynamicProviders = new ConcurrentDictionary>(StringComparer.OrdinalIgnoreCase); private static readonly ConcurrentDictionary _variableInfo = new ConcurrentDictionary(StringComparer.OrdinalIgnoreCase); private static readonly object _eventLock = new object(); private static readonly HashSet _reservedKeywords = new HashSet(StringComparer.OrdinalIgnoreCase) { "FLOOR", "CEIL", "ROUND", "ABS", "SQRT", "LOG", "LN", "MIN", "MAX", "CLAMP", "SIN", "COS", "TAN", "SIGN", "POW", "PI", "E", "INF", "INFINITY", "AND", "OR", "NOT", "XOR" }; private const int MaxVariableNameLength = 50; public static event Action? OnVariableRegistered; public static event Action? OnVariableUnregistered; public static void RegisterVariable(string name, float value, string? description = null) { string text = NormalizeVariableName(name); if (_staticVariables.ContainsKey(text) || _dynamicProviders.ContainsKey(text)) { Log.Warning("[FormulaRegistry] Variable '" + text + "' is already registered. Overwriting."); } _staticVariables[text] = value; _dynamicProviders.TryRemove(text, out Func _); _variableInfo[text] = new VariableInfo(text, VariableType.Static, description); Action onVariableRegistered; lock (_eventLock) { onVariableRegistered = FormulaRegistry.OnVariableRegistered; } onVariableRegistered?.Invoke(text); } public static bool RegisterVariableSafe(string name, float value, string? description = null, bool overwrite = false) { string text = NormalizeVariableName(name); bool flag = _staticVariables.ContainsKey(text) || _dynamicProviders.ContainsKey(text); if (flag && !overwrite) { Log.Warning("[FormulaRegistry] Variable '" + text + "' already registered. Use overwrite: true to replace."); return false; } if (flag) { Log.Warning("[FormulaRegistry] Variable '" + text + "' is already registered. Overwriting."); } _staticVariables[text] = value; _dynamicProviders.TryRemove(text, out Func _); _variableInfo[text] = new VariableInfo(text, VariableType.Static, description); Action onVariableRegistered; lock (_eventLock) { onVariableRegistered = FormulaRegistry.OnVariableRegistered; } onVariableRegistered?.Invoke(text); return true; } public static void RegisterVariable(string name, Func provider, string? description = null, float? fallbackValue = null) { string text = NormalizeVariableName(name); if (_staticVariables.ContainsKey(text) || _dynamicProviders.ContainsKey(text)) { Log.Warning("[FormulaRegistry] Variable '" + text + "' is already registered. Overwriting."); } _dynamicProviders[text] = provider; _staticVariables.TryRemove(text, out var _); _variableInfo[text] = new VariableInfo(text, VariableType.Dynamic, description, fallbackValue); Action onVariableRegistered; lock (_eventLock) { onVariableRegistered = FormulaRegistry.OnVariableRegistered; } onVariableRegistered?.Invoke(text); } public static bool RegisterVariableSafe(string name, Func provider, string? description = null, float? fallbackValue = null, bool overwrite = false) { string text = NormalizeVariableName(name); bool flag = _staticVariables.ContainsKey(text) || _dynamicProviders.ContainsKey(text); if (flag && !overwrite) { Log.Warning("[FormulaRegistry] Variable '" + text + "' already registered. Use overwrite: true to replace."); return false; } if (flag) { Log.Warning("[FormulaRegistry] Variable '" + text + "' is already registered. Overwriting."); } _dynamicProviders[text] = provider; _staticVariables.TryRemove(text, out var _); _variableInfo[text] = new VariableInfo(text, VariableType.Dynamic, description, fallbackValue); Action onVariableRegistered; lock (_eventLock) { onVariableRegistered = FormulaRegistry.OnVariableRegistered; } onVariableRegistered?.Invoke(text); return true; } public static bool UnregisterVariable(string name) { string text = NormalizeVariableName(name); float value; Func value2; bool flag = _staticVariables.TryRemove(text, out value) || _dynamicProviders.TryRemove(text, out value2); _variableInfo.TryRemove(text, out VariableInfo _); if (flag) { Action onVariableUnregistered; lock (_eventLock) { onVariableUnregistered = FormulaRegistry.OnVariableUnregistered; } onVariableUnregistered?.Invoke(text); } return flag; } public static bool IsVariableRegistered(string name) { string key = NormalizeVariableName(name); if (!_staticVariables.ContainsKey(key)) { return _dynamicProviders.ContainsKey(key); } return true; } public static VariableInfo? GetVariableInfo(string name) { string key = NormalizeVariableName(name); if (!_variableInfo.TryGetValue(key, out VariableInfo value)) { return null; } return value; } public static IEnumerable GetRegisteredVariableNames() { return _staticVariables.Keys.Concat(_dynamicProviders.Keys).Distinct(); } public static Dictionary GetVariables(CharacterBody? body, Dictionary? localVars = null) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); foreach (KeyValuePair staticVariable in _staticVariables) { dictionary[staticVariable.Key] = staticVariable.Value; } foreach (KeyValuePair> dynamicProvider in _dynamicProviders) { try { dictionary[dynamicProvider.Key] = dynamicProvider.Value(body); } catch (Exception ex) { Log.Error("[FormulaRegistry] Error evaluating dynamic variable '" + dynamicProvider.Key + "': " + ex.Message); float value = 0f; if (_variableInfo.TryGetValue(dynamicProvider.Key, out VariableInfo value2) && value2.FallbackValue.HasValue) { value = value2.FallbackValue.Value; } dictionary[dynamicProvider.Key] = value; } } if (localVars != null) { foreach (KeyValuePair localVar in localVars) { dictionary[localVar.Key] = localVar.Value; } } return dictionary; } private static string NormalizeVariableName(string name) { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentException("Variable name cannot be null or whitespace", "name"); } string text = name.Trim(); string text2 = text.ToUpperInvariant(); if (text2.Length > 50) { throw new ArgumentException($"Variable name cannot exceed {50} characters", "name"); } if (_reservedKeywords.Contains(text2)) { throw new ArgumentException("Variable name '" + name + "' is a reserved keyword and cannot be used", "name"); } string text3 = text2; foreach (char c in text3) { if (!char.IsLetterOrDigit(c) && c != '_') { throw new ArgumentException($"Variable name '{name}' contains invalid character '{c}'. Only letters, numbers, and underscores are allowed.", "name"); } } if (!char.IsLetter(text2[0]) && text2[0] != '_') { throw new ArgumentException("Variable name '" + name + "' must start with a letter or underscore", "name"); } return text2; } } public class VariableInfo { public string Name { get; } public VariableType Type { get; } public string? Description { get; } public float? FallbackValue { get; } public VariableInfo(string name, VariableType type, string? description, float? fallbackValue = null) { Name = name; Type = type; Description = description; FallbackValue = fallbackValue; } } public enum VariableType { Static, Dynamic } public static class OverencumbranceSystem { [CompilerGenerated] private sealed class d__6 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CharacterBody body; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__6(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(1.5f); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)body != (Object)null && body.HasBuff(Buffs.TransferDebuffOnHit)) { RemoveTransferDebuff(body); _overencumbranceTimers.Remove(body); Log.Debug($"[Overencumbrance] Removed debuff after {1.5f:F1}s"); } 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 const float OverencumbranceDebuffRemovalDelay = 1.5f; private static readonly Dictionary _overencumbranceTimers = new Dictionary(); public static float CalculateOverencumbrancePercent(float totalMass, float massCapacity) { if (massCapacity <= 0f) { return 0f; } float num = totalMass / massCapacity; float num2 = (PluginConfig.Instance.EnableBalance.Value ? (PluginConfig.Instance.OverencumbranceMax.Value / 100f) : 0f); return Mathf.Clamp(num - 1f, 0f, num2); } public static void ApplyOverencumbrance(CharacterBody body, DrifterBagController bagController) { if ((Object)(object)body == (Object)null || (Object)(object)bagController == (Object)null) { return; } float totalMass = GetTotalMass(bagController); float massCapacity = CapacityScalingSystem.CalculateMassCapacity(bagController); float num = CalculateOverencumbrancePercent(totalMass, massCapacity); if (num <= 0f) { if (body.HasBuff(Buffs.TransferDebuffOnHit)) { StartRemovalTimer(body); Log.Debug("[Overencumbrance] Started removal timer for debuff"); } return; } StopRemovalTimer(body); if (!body.HasBuff(Buffs.TransferDebuffOnHit)) { ApplyTransferDebuff(body); Log.Debug($"[Overencumbrance] Applied debuff: Overencumbrance%={num:P1}"); } } private static void StartRemovalTimer(CharacterBody body) { if (!((Object)(object)body == (Object)null)) { StopRemovalTimer(body); Coroutine value = ((MonoBehaviour)body).StartCoroutine(RemovalTimerCoroutine(body)); _overencumbranceTimers[body] = value; } } private static void StopRemovalTimer(CharacterBody body) { if (!((Object)(object)body == (Object)null) && _overencumbranceTimers.TryGetValue(body, out Coroutine value) && value != null) { ((MonoBehaviour)body).StopCoroutine(value); _overencumbranceTimers.Remove(body); Log.Debug("[Overencumbrance] Stopped removal timer for " + ((Object)body).name); } } [IteratorStateMachine(typeof(d__6))] private static IEnumerator RemovalTimerCoroutine(CharacterBody body) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__6(0) { body = body }; } private static void ApplyTransferDebuff(CharacterBody body) { if (!((Object)(object)body == (Object)null)) { BuffDef transferDebuffOnHit = Buffs.TransferDebuffOnHit; if ((Object)(object)transferDebuffOnHit != (Object)null) { body.AddBuff(transferDebuffOnHit); } } } private static void RemoveTransferDebuff(CharacterBody body) { if (!((Object)(object)body == (Object)null)) { body.RemoveBuff(Buffs.TransferDebuffOnHit); } } private static float GetTotalMass(DrifterBagController bagController) { if ((Object)(object)bagController == (Object)null) { return 0f; } return bagController.baggedMass; } public static void CleanupCharacterBody(CharacterBody body) { if ((Object)(object)body != (Object)null && _overencumbranceTimers.ContainsKey(body)) { StopRemovalTimer(body); } } } } namespace DrifterBossGrabMod.Patches { [HarmonyPatch(typeof(DrifterBagController), "CmdDamageBaggedObject")] public class CmdDamageBaggedObject_AoE { [HarmonyPrefix] public static void Prefix(DrifterBagController __instance, ref float damageCoef, out float __state) { __state = damageCoef; if (NetworkServer.active && PluginConfig.Instance.EnableBalance.Value && PluginConfig.Instance.AoEDamageDistribution.Value != 0 && PluginConfig.Instance.StateCalculationMode.Value == StateCalculationMode.All) { BagState state = BagPatches.GetState(__instance); List baggedObjects = state.BaggedObjects; Log.Debug($"[AoESlamDamage] Prefix: Coef={damageCoef}, Count={baggedObjects?.Count ?? 0}, DistMode={PluginConfig.Instance.AoEDamageDistribution.Value}"); if (baggedObjects != null && baggedObjects.Count > 1 && PluginConfig.Instance.AoEDamageDistribution.Value == AoEDamageMode.Split) { damageCoef /= baggedObjects.Count; __state = damageCoef; Log.Debug($"[AoESlamDamage] Split mode enabled. Split Coef: {__state} (Original/{baggedObjects.Count})"); } } } [HarmonyPostfix] public static void Postfix(DrifterBagController __instance, float __state) { if (!NetworkServer.active || !PluginConfig.Instance.EnableBalance.Value || PluginConfig.Instance.AoEDamageDistribution.Value == AoEDamageMode.None || PluginConfig.Instance.StateCalculationMode.Value != StateCalculationMode.All) { return; } BagState state = BagPatches.GetState(__instance); List baggedObjects = state.BaggedObjects; if (baggedObjects == null) { return; } GameObject mainSeatObject = BagPatches.GetMainSeatObject(__instance); CharacterBody component = ((Component)__instance).GetComponent(); Log.Debug($"[AoESlamDamage] Postfix: EffectiveCoef={__state}, StateCoef={__state}"); if (__state <= 0f) { return; } int num = 0; List list = new List(baggedObjects); foreach (GameObject item in list) { if ((Object)(object)item == (Object)null || item == mainSeatObject || (Object.op_Implicit((Object)(object)__instance.vehicleSeat) && __instance.vehicleSeat.hasPassenger && item == __instance.vehicleSeat.NetworkpassengerBodyObject)) { continue; } SpecialObjectAttributes component2 = item.GetComponent(); bool flag = (Object)(object)component2 != (Object)null; if (PluginConfig.Instance.AoEDamageDistribution.Value == AoEDamageMode.Split && flag) { float num2 = 1f / (float)baggedObjects.Count; if (Random.value > num2) { Log.Debug($"[AoESlamDamage] Split RNG: {((Object)item).name} SKIPPED (Chance={num2:F2})"); continue; } Log.Debug($"[AoESlamDamage] Split RNG: {((Object)item).name} HIT (Chance={num2:F2})"); } ApplyDamageToObject(__instance, component, item, __state); num++; } if (num > 0) { Log.Debug($"[AoESlamDamage] Applied AoE damage to {num} additional objects with coef {__state}"); } DamagePreviewOverlay.InvalidateAllCaches(); } private static void ApplyDamageToObject(DrifterBagController controller, CharacterBody drifterBody, GameObject targetObject, float damageCoef) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)targetObject)) { return; } CharacterBody component = targetObject.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { if (Object.op_Implicit((Object)(object)drifterBody) && Object.op_Implicit((Object)(object)component.healthComponent)) { DamageInfo val = new DamageInfo { attacker = ((Component)controller).gameObject, crit = drifterBody.RollCrit(), damage = drifterBody.damage * damageCoef, position = component.footPosition, inflictor = ((Component)controller).gameObject, damageType = DamageTypeCombo.op_Implicit((DamageTypeExtended)65536), damageColorIndex = (DamageColorIndex)0 }; component.healthComponent.TakeDamage(val); if (Object.op_Implicit((Object)(object)targetObject.GetComponent())) { Log.Debug("[AoESlamDamage] Dealt force-damage to JunkCube " + ((Object)targetObject).name); } } return; } SpecialObjectAttributes component2 = targetObject.GetComponent(); if (!Object.op_Implicit((Object)(object)component2)) { return; } if (component2.durability <= 1) { JunkController component3 = ((Component)controller).GetComponent(); if (Object.op_Implicit((Object)(object)component3)) { component3.CallCmdGenerateJunkQuantity(((Component)component2).transform.position, 4); } component2.Networkdurability = 0; NetworkServer.Destroy(targetObject); } else { component2.Networkdurability = (byte)(component2.durability - 1); } } } public static class BalancePatches { [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class GenericSkill_maxStock_Setter_Patch { private static void Postfix(GenericSkill __instance) { DrifterBagController component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { CapacityScalingSystem.RecalculateCapacity(component); } } } [HarmonyPatch(typeof(CharacterBody), "RecalculateStats")] public class CharacterBody_RecalculateStats_Patch { [HarmonyPostfix] public static void Postfix(CharacterBody __instance) { if (!PluginConfig.Instance.EnableBalance.Value) { return; } DrifterBagController componentInParent = ((Component)__instance).GetComponentInParent(); if (!((Object)(object)componentInParent != (Object)null)) { return; } if (((NetworkBehaviour)componentInParent).hasAuthority) { string text = PluginConfig.Instance.SlotScalingFormula.Value?.Trim() ?? ""; if (!string.IsNullOrEmpty(text) && text != "0") { UIPatches.UpdateMassCapacityUIOnCapacityChange(componentInParent); } } if (PluginConfig.Instance.OverencumbranceMax.Value > 0f) { OverencumbranceSystem.ApplyOverencumbrance(__instance, componentInParent); } } } [HarmonyPatch(typeof(CharacterBody), "OnDestroy")] public class CharacterBody_OnDestroy_Patch { [HarmonyPrefix] public static void Prefix(CharacterBody __instance) { OverencumbranceSystem.CleanupCharacterBody(__instance); } } [HarmonyPatch(typeof(EmptyBag), "ModifyProjectile")] public class EmptyBag_ModifyProjectile_Patch { [HarmonyPostfix] public static void Postfix(EmptyBag __instance, ref FireProjectileInfo fireProjectileInfo) { if (PluginConfig.Instance.EnableBalance.Value) { float speedOverride = ((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride; if (!PluginConfig.Instance.IsMaxLaunchSpeedInfinite && float.TryParse(PluginConfig.Instance.MaxLaunchSpeed.Value, out var result)) { ((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride = Mathf.Min(((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride, result); } Log.Debug($"[EmptyBag_ModifyProjectile_Patch] Incoming speedOverride={speedOverride:F1} -> Capped={((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride:F1}"); } } } [HarmonyPatch(typeof(EmptyBag), "OnEnter")] public class EmptyBag_OnEnter_Patch { [HarmonyPostfix] public static void Postfix(EmptyBag __instance) { DrifterBagController component = ((EntityState)__instance).GetComponent(); if (!((Object)(object)component != (Object)null)) { return; } float baggedMass = component.baggedMass; float num = 1f - baggedMass * 0.000714f; float num2 = Mathf.Max(num, 0.15f); float num3 = 0f; if (Mathf.Abs(num) > 0.0001f) { float num4 = (float)ReflectionCache.EmptyBag.ProjectileBaseSpeed.GetValue(__instance); num3 = num4 / num; } else { ProjectileSimple val = (((Object)(object)((AimThrowableBase)__instance).projectilePrefab != (Object)null) ? ((AimThrowableBase)__instance).projectilePrefab.GetComponent() : null); if ((Object)(object)val != (Object)null) { num3 = val.desiredForwardSpeed; if (num3 == 0f) { num3 = val.velocity; } } if (num3 == 0f) { num3 = 60f; } } float num5 = 60f; if (Mathf.Abs(num) > 0.0001f) { num5 = ((AimThrowableBase)__instance).maxDistance / num; } float num6 = num3 * num2; float num7 = num5 * num2; ReflectionCache.EmptyBag.ProjectileBaseSpeed.SetValue(__instance, num6); ((AimThrowableBase)__instance).maxDistance = num7; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[EmptyBag_OnEnter_Patch] Mass={baggedMass:F1}, num={num:F4}, clampedNum={num2:F4}"); Log.Debug($"[EmptyBag_OnEnter_Patch] Speed: Original={num3:F1} -> Target={num6:F1}"); Log.Debug($"[EmptyBag_OnEnter_Patch] Distance: Original={num5:F1} -> Target={num7:F1}"); } } } [HarmonyPatch(typeof(EmptyBag), "FireProjectile")] public class EmptyBag_FireProjectile_Patch { private static float _originalAirKnockbackForce; [HarmonyPrefix] public static void Prefix(EmptyBag __instance) { _originalAirKnockbackForce = __instance.airKnockbackForce; if (!PluginConfig.Instance.EnableBalance.Value) { return; } DrifterBagController component = ((EntityState)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { float baggedMass = component.baggedMass; float maxMass = DrifterBagController.maxMass; float num = 100f; if ((Object)(object)((EntityState)__instance).characterBody != (Object)null && (Object)(object)((EntityState)__instance).characterBody.characterMotor != (Object)null) { num = ((EntityState)__instance).characterBody.characterMotor.mass; } if (num <= 0f) { num = 100f; } float num2 = Mathf.Abs(_originalAirKnockbackForce * baggedMass / (maxMass * num)); bool flag = (Object)(object)((EntityState)__instance).characterBody != (Object)null && (Object)(object)((EntityState)__instance).characterBody.characterMotor != (Object)null && ((EntityState)__instance).characterBody.characterMotor.isGrounded; Log.Debug($"[EmptyBag_FireProjectile_Patch] Prefix: Grounded={flag}, Original airKnockbackForce={_originalAirKnockbackForce:F1}, Target Mass={baggedMass:F1}, Drifter Mass={num:F1}, Predicted Recoil Speed={num2:F2} m/s"); if (!PluginConfig.Instance.IsMaxLaunchSpeedInfinite && float.TryParse(PluginConfig.Instance.MaxLaunchSpeed.Value, out var result) && baggedMass > 0f && num2 > result) { float num3 = Mathf.Sign(_originalAirKnockbackForce); __instance.airKnockbackForce = num3 * result * maxMass * num / baggedMass; Log.Debug($"[EmptyBag_FireProjectile_Patch] CLAMPED airKnockbackForce to {__instance.airKnockbackForce:F1} (Recoil speed capped to MaxLaunchSpeed={result:F1} m/s)"); } } } [HarmonyPostfix] public static void Postfix(EmptyBag __instance) { __instance.airKnockbackForce = _originalAirKnockbackForce; } } [HarmonyPatch(typeof(ProjectileManager), "FireProjectile", new Type[] { typeof(FireProjectileInfo) })] public class ProjectileManager_FireProjectile_Patch { [HarmonyPrefix] public static void Prefix(ref FireProjectileInfo fireProjectileInfo) { if (PluginConfig.Instance.EnableBalance.Value) { float speedOverride = ((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride; if (!PluginConfig.Instance.IsMaxLaunchSpeedInfinite && float.TryParse(PluginConfig.Instance.MaxLaunchSpeed.Value, out var result) && ((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride > 0f) { ((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride = Mathf.Min(((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride, result); } Log.Debug($"[ProjectileManager_FireProjectile_Patch] Incoming speedOverride={speedOverride:F1} -> Capped={((FireProjectileInfo)(ref fireProjectileInfo)).speedOverride:F1}"); } } } } public static class CharacterSpawnPatches { [HarmonyPatch(typeof(CharacterMaster), "OnBodyStart")] public class CharacterMaster_OnBodyStart { [HarmonyPostfix] public static void Postfix(CharacterMaster __instance, CharacterBody body) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) Log.Debug("[CharacterMaster_OnBodyStart] Body: " + ((Object)body).name + ", Master: " + ((Object)__instance).name); if (((Object)body).name.StartsWith("DrifterBody")) { DrifterBossGrabPlugin.IsDrifterPresent = true; if (PluginConfig.Instance.EnableCarouselHUD.Value) { BaggedObjectUIController baggedObjectUIController = ((Component)body).gameObject.AddComponent(); baggedObjectUIController.slotPrefab = Addressables.LoadAssetAsync((object)"RoR2/DLC3/Drifter/Bag UI.prefab").WaitForCompletion(); Log.Debug($"[CharacterMaster_OnBodyStart] Added BaggedObjectUIController to DrifterBody, slot prefab loaded: {(Object)(object)baggedObjectUIController.slotPrefab != (Object)null}"); } else { Log.Debug("[CharacterMaster_OnBodyStart] Carousel HUD disabled, skipping BaggedObjectUIController creation"); } } if (PluginConfig.Instance.EnableObjectPersistence.Value && PluginConfig.Instance.EnableAutoGrab.Value && !((Object)(object)body == (Object)null)) { if (((Object)body).name.StartsWith("DrifterBody")) { PersistenceManager.ScheduleAutoGrab(__instance); Log.Debug("[CharacterMaster_OnBodyStart] Scheduled auto-grab for Drifter respawn"); } ZoneDetectionPatches.DetectZoneInversion(body.transform.position); } } } } [HarmonyPatch] public static class CombatDirectorPatches { private static readonly HashSet _restoringTeleporterDirectors = new HashSet(); public static void MarkTeleporterDirectorAsRestoring(CombatDirector director) { if ((Object)(object)director != (Object)null) { _restoringTeleporterDirectors.Add(director); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[CombatDirectorPatches] Marked {((Object)director).name} as restoring (total: {_restoringTeleporterDirectors.Count})"); } } } public static void ClearTeleporterDirectorRestoring(CombatDirector director) { if ((Object)(object)director != (Object)null) { _restoringTeleporterDirectors.Remove(director); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[CombatDirectorPatches] Cleared restoring flag for {((Object)director).name} (total: {_restoringTeleporterDirectors.Count})"); } } } [HarmonyPatch(typeof(CombatDirector), "OnDisable")] [HarmonyPrefix] private static bool OnDisablePrefix(CombatDirector __instance) { if (_restoringTeleporterDirectors.Contains(__instance)) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[CombatDirectorPatches] Blocking vanilla credit transfer for " + ((Object)__instance).name + " (restoring from persistence)"); } CombatDirector.instancesList.Remove(__instance); return false; } return true; } } public class BaggedObjectTracker : MonoBehaviour { public DrifterBagController? controller; public GameObject? obj; public bool isRemovingManual; private int _cachedInstanceId; private void Start() { if ((Object)(object)obj != (Object)null) { _cachedInstanceId = ((Object)obj).GetInstanceID(); } } private void OnDestroy() { if (!isRemovingManual) { if (obj != null) { PersistenceObjectsTracker.UntrackBaggedObject(obj, isDestroying: true); } if (controller != null && obj != null && (Object)(object)controller != (Object)null && (Object)(object)obj != (Object)null) { BagPassengerManager.RemoveBaggedObject(controller, obj, isDestroying: true); } } } } public class DelayedAutoPromote : MonoBehaviour { private DrifterBagController? _controller; private GameObject? _newMain; private float _delayTime; private float _elapsedTime; public static void Schedule(DrifterBagController? controller, GameObject? newMain, float delay = 0f) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected O, but got Unknown if (delay <= 0f) { ExecutePromotionImmediate(controller, newMain); return; } GameObject val = new GameObject("DelayedAutoPromote_" + BagHelpers.GetSafeName((Object?)(object)newMain)); DelayedAutoPromote delayedAutoPromote = val.AddComponent(); delayedAutoPromote._controller = controller; delayedAutoPromote._newMain = newMain; delayedAutoPromote._delayTime = delay; } private static void ExecutePromotionImmediate(DrifterBagController? controller, GameObject? newMain) { //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Expected O, but got Unknown if ((Object)(object)controller == (Object)null || (Object)(object)newMain == (Object)null || ProjectileRecoveryPatches.IsInProjectileState(newMain)) { return; } if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[ExecutePromotionImmediate] START: Promoting " + BagHelpers.GetSafeName((Object?)(object)newMain)); } BagState state = BagPatches.GetState(controller); lock (state.BagLock) { if (!state.BaggedObjects.Contains(newMain)) { return; } } DrifterBossGrabPlugin._isSwappingPassengers = true; try { if (ReflectionCache.DrifterBagController.Smacks != null) { ReflectionCache.DrifterBagController.Smacks.SetValue(controller, 0); } EntityStateMachine bagStateMachine = GetBagStateMachine(controller); if (NetworkServer.active) { EntityStateMachine[] components = ((Component)controller).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Bag") { if (val.state is BaggedObject) { val.SetNextStateToMain(); } break; } } } if (state.AdditionalSeats.TryGetValue(newMain, out VehicleSeat value) && (Object)(object)value != (Object)null) { if (NetworkServer.active) { value.EjectPassenger(newMain); } state.AdditionalSeats.TryRemove(newMain, out VehicleSeat _); } if (NetworkServer.active) { if ((Object)(object)controller.vehicleSeat != (Object)null && controller.vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject = controller.vehicleSeat.NetworkpassengerBodyObject; if (!((Object)(object)networkpassengerBodyObject == (Object)null)) { HealthComponent component = networkpassengerBodyObject.GetComponent(); if (component == null || component.alive) { SpecialObjectAttributes component2 = networkpassengerBodyObject.GetComponent(); if (component2 == null || component2.durability > 0) { goto IL_01b5; } } } controller.vehicleSeat.EjectPassenger(); } goto IL_01b5; } if (((NetworkBehaviour)controller).hasAuthority) { GameObject mainSeatObject = BagPatches.GetMainSeatObject(controller); BagPatches.SetMainSeatObject(controller, newMain); DrifterBagAPI.InvokeOnMainPassengerChanged(controller, mainSeatObject, newMain); } return; IL_01b5: controller.AssignPassenger(newMain); if (!((Object)(object)controller.vehicleSeat != (Object)null)) { return; } if ((Object)(object)controller.vehicleSeat.NetworkpassengerBodyObject != (Object)(object)newMain) { controller.vehicleSeat.AssignPassenger(newMain); } EntityStateMachine[] components2 = ((Component)controller).GetComponents(); EntityStateMachine[] array2 = components2; foreach (EntityStateMachine val2 in array2) { if (val2.customName == "Bag") { BaggedObject val3 = new BaggedObject(); val3.targetObject = newMain; val2.SetNextState((EntityState)(object)val3); break; } } } finally { DrifterBossGrabPlugin._isSwappingPassengers = false; } } private static EntityStateMachine? GetBagStateMachine(DrifterBagController controller) { EntityStateMachine[] components = ((Component)controller).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Bag") { return val; } } return null; } private void Update() { _elapsedTime += Time.deltaTime; if (_elapsedTime >= _delayTime) { ExecutePromotion(); } } private void ExecutePromotion() { //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Expected O, but got Unknown if ((Object)(object)_controller != (Object)null && (Object)(object)_newMain != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(_newMain)) { BagState state = BagPatches.GetState(_controller); bool flag; lock (state.BagLock) { flag = state.BaggedObjects.Contains(_newMain); } if (!flag) { Object.Destroy((Object)(object)((Component)this).gameObject); return; } DrifterBossGrabPlugin._isSwappingPassengers = true; try { if (ReflectionCache.DrifterBagController.Smacks != null) { ReflectionCache.DrifterBagController.Smacks.SetValue(_controller, 0); } if (NetworkServer.active) { EntityStateMachine[] components = ((Component)_controller).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Bag") { if (val.state is BaggedObject) { val.SetNextStateToMain(); } break; } } } if (state.AdditionalSeats.TryGetValue(_newMain, out VehicleSeat value) && (Object)(object)value != (Object)null) { if (NetworkServer.active) { value.EjectPassenger(_newMain); } state.AdditionalSeats.TryRemove(_newMain, out VehicleSeat _); } if (NetworkServer.active) { if ((Object)(object)_controller.vehicleSeat != (Object)null && _controller.vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject = _controller.vehicleSeat.NetworkpassengerBodyObject; if (!((Object)(object)networkpassengerBodyObject == (Object)null)) { HealthComponent component = networkpassengerBodyObject.GetComponent(); if (component == null || component.alive) { SpecialObjectAttributes component2 = networkpassengerBodyObject.GetComponent(); if (component2 == null || component2.durability > 0) { goto IL_01df; } } } _controller.vehicleSeat.EjectPassenger(); } goto IL_01df; } if (((NetworkBehaviour)_controller).hasAuthority) { GameObject mainSeatObject = BagPatches.GetMainSeatObject(_controller); BagPatches.SetMainSeatObject(_controller, _newMain); DrifterBagAPI.InvokeOnMainPassengerChanged(_controller, mainSeatObject, _newMain); } goto end_IL_0084; IL_01df: _controller.AssignPassenger(_newMain); if ((Object)(object)_controller.vehicleSeat != (Object)null) { if ((Object)(object)_controller.vehicleSeat.NetworkpassengerBodyObject != (Object)(object)_newMain) { _controller.vehicleSeat.AssignPassenger(_newMain); } EntityStateMachine[] components2 = ((Component)_controller).GetComponents(); EntityStateMachine[] array2 = components2; foreach (EntityStateMachine val2 in array2) { if (val2.customName == "Bag") { BaggedObject val3 = new BaggedObject(); val3.targetObject = _newMain; val2.SetNextState((EntityState)(object)val3); break; } } } end_IL_0084:; } finally { DrifterBossGrabPlugin._isSwappingPassengers = false; } } Object.Destroy((Object)(object)((Component)this).gameObject); } } public static class BagPatches { [HarmonyPatch(typeof(Run), "Start")] public class Run_Start_Patch { [HarmonyPrefix] public static void Prefix() { ClearCaches(); } } [HarmonyPatch(typeof(DrifterBagController), "AssignPassenger")] public class DrifterBagController_AssignPassenger { private static bool _usingAdditionalSeat; [HarmonyPrefix] public static bool Prefix(DrifterBagController __instance, GameObject passengerObject) { //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Invalid comparison between Unknown and I4 //IL_0142: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)passengerObject != (Object)null) { BagState state = GetState(__instance); Log.Debug("[AssignPassenger.Prefix] START: incoming=" + ((Object)passengerObject).name); } if ((Object)(object)passengerObject != (Object)null) { ModelLocator component = passengerObject.GetComponent(); if ((Object)(object)component != (Object)null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(__instance, passengerObject); if (baggedObjectStateData == null) { baggedObjectStateData = new BaggedObjectStateData(); baggedObjectStateData.CalculateFromObject(passengerObject, __instance); BaggedObjectPatches.SaveObjectState(__instance, passengerObject, baggedObjectStateData); } if (!baggedObjectStateData.hasCapturedModelTransformState) { baggedObjectStateData.hasCapturedModelTransformState = true; } } } _usingAdditionalSeat = false; if (Object.op_Implicit((Object)(object)passengerObject) && PluginConfig.IsBlacklisted(((Object)passengerObject).name)) { return false; } if ((Object)(object)passengerObject == (Object)null) { return true; } if (ProjectileRecoveryPatches.IsInProjectileState(passengerObject)) { ProjectileRecoveryPatches.RemoveFromProjectileState(passengerObject); } ModelLocator component2 = passengerObject.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.dontDetatchFromParent = true; } CharacterBody component3 = passengerObject.GetComponent(); if (Object.op_Implicit((Object)(object)component3)) { if (component3.baseMaxHealth <= 0f || component3.levelMaxHealth < 0f || (Object)(object)component3.teamComponent == (Object)null || (int)component3.teamComponent.teamIndex < 0) { return false; } HealthComponent healthComponent = component3.healthComponent; if ((Object)(object)healthComponent != (Object)null && !healthComponent.alive) { Log.Debug("[AssignPassenger.Prefix] Blocking grab of dead body: " + ((Object)passengerObject).name); return false; } if (((Enum)component3.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288) && (Object)(object)component3.currentVehicle != (Object)null && !((Object)(object)component3.currentVehicle == (Object)(object)__instance.vehicleSeat) && !GetState(__instance).AdditionalSeats.Values.Contains(component3.currentVehicle)) { component3.currentVehicle.EjectPassenger(passengerObject); } } if ((Object)(object)component3 != (Object)null && ((Enum)component3.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288)) { BagState state2 = GetState(__instance); if (!state2.DisabledCollidersByObject.ContainsKey(passengerObject)) { state2.DisabledCollidersByObject[passengerObject] = new Dictionary(); } BodyColliderCache.DisableMovementColliders(passengerObject, state2.DisabledCollidersByObject[passengerObject]); } TeleporterInteraction component4 = passengerObject.GetComponent(); if ((Object)(object)component4 != (Object)null) { ((Behaviour)component4).enabled = false; PersistenceManager.MarkTeleporterAsBagged(passengerObject); MultiTeleporterTracker.UnregisterSecondary(component4); } PersistenceManager.RemovePersistedObject(passengerObject); PersistenceObjectsTracker.TrackBaggedObject(passengerObject); if ((Object)(object)__instance != (Object)null) { GetState(__instance).IncomingObject = passengerObject; } int effectiveCapacity = ((!((Object)(object)__instance != (Object)null)) ? 1 : BagCapacityCalculator.GetUtilityMaxStock(__instance)); List list = (((Object)(object)__instance != (Object)null) ? GetState(__instance).BaggedObjects : null); if (list == null) { return true; } int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(__instance); int instanceID = ((Object)passengerObject).GetInstanceID(); bool isAlreadyTrackedByThisController = GetState(__instance).ContainsInstanceId(instanceID); if ((Object)(object)__instance.vehicleSeat != (Object)null && __instance.vehicleSeat.hasPassenger && __instance.vehicleSeat.NetworkpassengerBodyObject == passengerObject) { Log.Debug("[AssignPassenger.Prefix] Passenger " + ((Object)passengerObject).name + " is already in the main seat. Skipping assignment to avoid vanilla vehicle validation failure."); return false; } bool flag = PluginConfig.Instance.PrioritizeMainSeat.Value; if (NetworkServer.active && (Object)(object)__instance != (Object)null) { BottomlessBagNetworkController component5 = ((Component)__instance).GetComponent(); if ((Object)(object)component5 != (Object)null && !((NetworkBehaviour)__instance).hasAuthority) { flag = component5.prioritizeMainSeat; } } bool flag2 = (Object)(object)__instance != (Object)null && (Object)(object)__instance.vehicleSeat != (Object)null && __instance.vehicleSeat.hasPassenger; if ((!flag || flag2) && TryAssignToAdditionalSeat(__instance, passengerObject, effectiveCapacity, isAlreadyTrackedByThisController)) { Log.Debug($"[AssignPassenger.Prefix] Redirected {((Object)passengerObject).name} to AdditionalSeat. _usingAdditionalSeat={_usingAdditionalSeat}, skipping original method."); return false; } Log.Debug($"[AssignPassenger.Prefix] Proceeding to Main Seat for {((Object)passengerObject).name}. _usingAdditionalSeat={_usingAdditionalSeat}"); return true; } [HarmonyPostfix] public static void Postfix(DrifterBagController __instance, GameObject passengerObject) { //IL_0137: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)passengerObject == (Object)null || ProjectileRecoveryPatches.IsInProjectileState(passengerObject)) { return; } Log.Debug($"[AssignPassenger.Postfix] START: passengerObject={((Object)passengerObject).name}, _usingAdditionalSeat={_usingAdditionalSeat}."); BagHelpers.AddTracker(__instance, passengerObject); if (!_usingAdditionalSeat && (Object)(object)__instance.vehicleSeat != (Object)null && NetworkServer.active) { if ((Object)(object)__instance.vehicleSeat.NetworkpassengerBodyObject != (Object)(object)passengerObject) { __instance.vehicleSeat.AssignPassenger(passengerObject); } if (NetworkUtils.IsNetworkIdentityInactive(passengerObject)) { NetworkUtils.TryEnsureNetworkIdentityActive(passengerObject); } } BagState state = GetState(__instance); state.AdditionalSeats.TryRemove(passengerObject, out VehicleSeat _); if (!_usingAdditionalSeat) { Log.Debug("[AssignPassenger.Postfix] Assigning to main seat: " + ((Object)passengerObject).name); GameObject mainSeatObject = GetMainSeatObject(__instance); SetMainSeatObject(__instance, passengerObject); DrifterBagAPI.InvokeOnMainPassengerChanged(__instance, mainSeatObject, passengerObject); } else { Log.Debug("[AssignPassenger.Postfix] Skipping main seat assignment for " + ((Object)passengerObject).name + " (assigned to additional seat)"); } List baggedObjects = state.BaggedObjects; if (!state.ContainsInstanceId(((Object)passengerObject).GetInstanceID())) { baggedObjects.Add(passengerObject); state.AddInstanceId(((Object)passengerObject).GetInstanceID()); BottomlessBagNetworkController component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { NetworkIdentity component2 = passengerObject.GetComponent(); if ((Object)(object)component2 != (Object)null) { component.TryAddBaggedObjectId(component2.netId); } } int slotIndex = (_usingAdditionalSeat ? (-1) : (baggedObjects.Count - 1)); DrifterBagAPI.InvokeOnObjectGrabbed(__instance, passengerObject, slotIndex); } if (BaggedObjectPatches.LoadObjectState(__instance, passengerObject) == null) { BaggedObjectStateData baggedObjectStateData = new BaggedObjectStateData(); baggedObjectStateData.CalculateFromObject(passengerObject, __instance); BaggedObjectPatches.SaveObjectState(__instance, passengerObject, baggedObjectStateData); } if (NetworkServer.active) { PersistenceNetworkHandler.SendBaggedObjectsPersistenceMessage(baggedObjects, __instance); } BagPassengerManager.ForceRecalculateMass(__instance); state.IncomingObject = null; BagCarouselUpdater.UpdateCarousel(__instance); if (!DrifterBossGrabPlugin.IsSwappingPassengers) { int num = state.IntendedSelectedIndex; GameObject mainSeatObject2 = GetMainSeatObject(__instance); if (num < 0) { if ((Object)(object)mainSeatObject2 != (Object)null) { num = baggedObjects.IndexOf(mainSeatObject2); } if (num < 0) { num = baggedObjects.Count - 1; } } Log.Debug($"[AssignPassenger.Postfix] Updating selection to {num} (Intent was {state.IntendedSelectedIndex}) for {((Object)passengerObject).name}"); BagCarouselUpdater.UpdateNetworkBagState(__instance, num); state.IntendedSelectedIndex = -1; } DamagePreviewOverlay.InvalidateAllCaches(); } private static bool TryAssignToAdditionalSeat(DrifterBagController __instance, GameObject passengerObject, int effectiveCapacity, bool isAlreadyTrackedByThisController) { if (isAlreadyTrackedByThisController || effectiveCapacity <= 1) { return false; } BagState state = GetState(__instance); int intendedSelectedIndex = state.IntendedSelectedIndex; ConcurrentDictionary seatDict = state.AdditionalSeats; Log.Debug($"[TryAssignToAdditionalSeat] Searching for seat for {((Object)passengerObject).name}. Capacity={effectiveCapacity}, Intent={intendedSelectedIndex}."); VehicleSeat val = AdditionalSeatManager.FindOrCreateEmptySeat(__instance, ref seatDict); List baggedObjects = state.BaggedObjects; int instanceID = ((Object)passengerObject).GetInstanceID(); if ((Object)(object)val != (Object)null) { _usingAdditionalSeat = true; Log.Debug("[TryAssignToAdditionalSeat] Found additional seat, setting _usingAdditionalSeat=true for " + ((Object)passengerObject).name); BagHelpers.AddTracker(__instance, passengerObject); if ((Object)(object)GetMainSeatObject(__instance) == (Object)(object)passengerObject) { SetMainSeatObject(__instance, null); } if (NetworkServer.active && AdditionalSeatBreakoutTimer.CanBreakout(passengerObject) && !Object.op_Implicit((Object)(object)passengerObject.GetComponent())) { AdditionalSeatBreakoutTimer additionalSeatBreakoutTimer = passengerObject.AddComponent(); additionalSeatBreakoutTimer.controller = __instance; float num = __instance.CalculateBaggedObjectMass(passengerObject); float num2 = Mathf.Max(10f - 0.005f * num, 1f) * PluginConfig.Instance.BreakoutTimeMultiplier.Value; CharacterBody component = passengerObject.GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.isElite) { num2 *= 0.8f; } additionalSeatBreakoutTimer.breakoutTime = num2; BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(__instance, passengerObject); if (baggedObjectStateData != null) { if (baggedObjectStateData.breakoutTime > 0f) { additionalSeatBreakoutTimer.breakoutTime = baggedObjectStateData.breakoutTime; } additionalSeatBreakoutTimer.SetElapsedBreakoutTime(baggedObjectStateData.elapsedBreakoutTime); additionalSeatBreakoutTimer.breakoutAttempts = baggedObjectStateData.breakoutAttempts; } } seatDict[passengerObject] = val; if (NetworkServer.active) { val.AssignPassenger(passengerObject); if (NetworkUtils.IsNetworkIdentityInactive(passengerObject)) { NetworkUtils.TryEnsureNetworkIdentityActive(passengerObject); } CharacterBody component2 = passengerObject.GetComponent(); if ((Object)(object)component2 != (Object)null) { if (!state.DisabledCollidersByObject.ContainsKey(passengerObject)) { state.DisabledCollidersByObject[passengerObject] = new Dictionary(); } BodyColliderCache.DisableMovementColliders(passengerObject, state.DisabledCollidersByObject[passengerObject]); } } if (!state.ContainsInstanceId(instanceID)) { baggedObjects.Add(passengerObject); state.AddInstanceId(instanceID); DrifterBagAPI.InvokeOnObjectGrabbed(__instance, passengerObject, baggedObjects.Count - 1); } BaggedObjectStateData baggedObjectStateData2 = BaggedObjectPatches.LoadObjectState(__instance, passengerObject); if (baggedObjectStateData2 == null) { BaggedObjectStateData baggedObjectStateData3 = new BaggedObjectStateData(); baggedObjectStateData3.CalculateFromObject(passengerObject, __instance); BaggedObjectPatches.SaveObjectState(__instance, passengerObject, baggedObjectStateData3); } if (NetworkServer.active) { PersistenceNetworkHandler.SendBaggedObjectsPersistenceMessage(baggedObjects, __instance); } state.IncomingObject = null; BagCarouselUpdater.UpdateCarousel(__instance); if (!DrifterBossGrabPlugin.IsSwappingPassengers) { BagCarouselUpdater.UpdateNetworkBagState(__instance); } BagPassengerManager.ForceRecalculateMass(__instance); GameObject mainSeatObject = GetMainSeatObject(__instance); Log.Debug("[TryAssignToAdditionalSeat] Successfully assigned " + ((Object)passengerObject).name + " to additional seat. Main seat object=" + (((mainSeatObject != null) ? ((Object)mainSeatObject).name : null) ?? "null")); return true; } if (!NetworkServer.active) { _usingAdditionalSeat = true; Log.Debug("[TryAssignToAdditionalSeat] Client mode, setting _usingAdditionalSeat=true for " + ((Object)passengerObject).name); BagHelpers.AddTracker(__instance, passengerObject); if (!state.ContainsInstanceId(instanceID)) { baggedObjects.Add(passengerObject); state.AddInstanceId(instanceID); DrifterBagAPI.InvokeOnObjectGrabbed(__instance, passengerObject, baggedObjects.Count - 1); } BaggedObjectStateData baggedObjectStateData4 = BaggedObjectPatches.LoadObjectState(__instance, passengerObject); if (baggedObjectStateData4 == null || baggedObjectStateData4.baseMaxHealth <= 0f) { BaggedObjectStateData baggedObjectStateData5 = new BaggedObjectStateData(); baggedObjectStateData5.CalculateFromObject(passengerObject, __instance); BaggedObjectPatches.SaveObjectState(__instance, passengerObject, baggedObjectStateData5); } state.IncomingObject = null; BagCarouselUpdater.UpdateCarousel(__instance); if (!DrifterBossGrabPlugin.IsSwappingPassengers) { BagCarouselUpdater.UpdateNetworkBagState(__instance); } BagPassengerManager.ForceRecalculateMass(__instance); GameObject mainSeatObject2 = GetMainSeatObject(__instance); Log.Debug("[TryAssignToAdditionalSeat] Successfully assigned " + ((Object)passengerObject).name + " to additional seat (client). Main seat object=" + (((mainSeatObject2 != null) ? ((Object)mainSeatObject2).name : null) ?? "null")); return true; } return false; } } private static readonly ConcurrentDictionary _states = new ConcurrentDictionary(); public static BagState GetState(DrifterBagController? controller) { if (controller == null) { return null; } return _states.GetOrAdd(controller, (DrifterBagController _) => new BagState()); } public static ICollection GetAllControllers() { return _states.Keys; } public static void ClearCaches() { _states.Clear(); } public static void SetMainSeatObject(DrifterBagController? controller, GameObject? obj) { if (!((Object)(object)controller == (Object)null)) { GameObject mainSeatObject = GetState(controller).MainSeatObject; GetState(controller).MainSeatObject = obj; Log.Debug("[SetMainSeatObject] " + ((Object)controller).name + ": " + (((mainSeatObject != null) ? ((Object)mainSeatObject).name : null) ?? "null") + " -> " + (((obj != null) ? ((Object)obj).name : null) ?? "null")); } } public static GameObject? GetMainSeatObject(DrifterBagController? controller) { if ((Object)(object)controller == (Object)null) { return null; } GameObject mainSeatObject = GetState(controller).MainSeatObject; if (!((Object)(object)mainSeatObject == (Object)null)) { Object val = (Object)(object)mainSeatObject; if (val == null || Object.op_Implicit(val)) { Log.Debug("[GetMainSeatObject] " + ((Object)controller).name + ": returning " + (((mainSeatObject != null) ? ((Object)mainSeatObject).name : null) ?? "null")); return mainSeatObject; } } GetState(controller).MainSeatObject = null; return null; } } [HarmonyPatch(typeof(VehicleSeat), "AssignPassenger")] public static class VehicleSeat_AssignPassenger_Postfix { [HarmonyPrefix] public static bool Prefix(VehicleSeat __instance, GameObject bodyObject) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active && (Object)(object)bodyObject != (Object)null) { DrifterBagController componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { bodyObject.transform.SetParent(((Component)__instance).transform); bodyObject.transform.localPosition = Vector3.zero; bodyObject.transform.localRotation = Quaternion.identity; if (__instance.disableAllCollidersAndHurtboxes) { Collider[] componentsInChildren = bodyObject.GetComponentsInChildren(); Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } CharacterBody component = bodyObject.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.modelLocator != (Object)null) { Transform modelTransform = component.modelLocator.modelTransform; if ((Object)(object)modelTransform != (Object)null) { HurtBoxGroup component2 = ((Component)modelTransform).GetComponent(); if ((Object)(object)component2 != (Object)null) { int hurtBoxesDeactivatorCounter = component2.hurtBoxesDeactivatorCounter; component2.hurtBoxesDeactivatorCounter = hurtBoxesDeactivatorCounter + 1; } } } } return false; } } return true; } [HarmonyPostfix] public static void Postfix(VehicleSeat __instance, GameObject bodyObject) { if ((Object)(object)bodyObject == (Object)null || !NetworkServer.active) { return; } DrifterBagController componentInParent = ((Component)__instance).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null || (Object)(object)__instance == (Object)(object)componentInParent.vehicleSeat) { return; } ConcurrentDictionary additionalSeats = BagPatches.GetState(componentInParent).AdditionalSeats; foreach (KeyValuePair item in additionalSeats) { if ((Object)(object)item.Value == (Object)(object)__instance && (Object)(object)item.Key != (Object)(object)bodyObject) { additionalSeats.TryRemove(item.Key, out var _); } } additionalSeats[bodyObject] = __instance; } } [HarmonyPatch(typeof(VehicleSeat), "OnPassengerEnter")] public static class VehicleSeat_OnPassengerEnter_Patch { [HarmonyPrefix] public static void Prefix(VehicleSeat __instance, GameObject passenger) { VehicleSeat_OnPassengerExit_Patch.SanitizePassengerSpecialAttributes(passenger); } } [HarmonyPatch(typeof(VehicleSeat), "OnPassengerExit")] public static class VehicleSeat_OnPassengerExit_Patch { [HarmonyPrefix] public static void Prefix(VehicleSeat __instance, GameObject passenger) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)passenger == (Object)null) { return; } SanitizePassengerSpecialAttributes(passenger); try { CharacterBody component = passenger.GetComponent(); if (!((Object)(object)component != (Object)null) || !((Object)(object)component.modelLocator != (Object)null)) { return; } Transform modelTransform = component.modelLocator.modelTransform; if (!((Object)(object)modelTransform != (Object)null)) { return; } CharacterModel component2 = ((Component)modelTransform).GetComponent(); if (!((Object)(object)component2 != (Object)null) || component2.baseRendererInfos == null) { return; } List list = new List(); RendererInfo[] baseRendererInfos = component2.baseRendererInfos; foreach (RendererInfo val in baseRendererInfos) { if ((Object)(object)val.renderer != (Object)null) { list.Add(val); } } if (list.Count != component2.baseRendererInfos.Length) { Log.Debug($"[OnPassengerExit.Prefix] Sanitized baseRendererInfos for {((Object)passenger).name}: removed {component2.baseRendererInfos.Length - list.Count} null renderers"); component2.baseRendererInfos = list.ToArray(); } } catch (Exception arg) { Log.Error($"[OnPassengerExit.Prefix] Exception during sanitization: {arg}"); } } public static void SanitizePassengerSpecialAttributes(GameObject passenger) { if ((Object)(object)passenger == (Object)null) { return; } try { SpecialObjectAttributes component = passenger.GetComponent(); if ((Object)(object)component != (Object)null) { component.renderersToDisable?.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); component.lightsToDisable?.RemoveAll((Light l) => (Object)(object)l == (Object)null); component.pickupDisplaysToDisable?.RemoveAll((PickupDisplay p) => (Object)(object)p == (Object)null); component.behavioursToDisable?.RemoveAll((MonoBehaviour b) => (Object)(object)b == (Object)null); component.childObjectsToDisable?.RemoveAll((GameObject c) => (Object)(object)c == (Object)null); component.soundEventsToStop?.RemoveAll((AkEvent s) => (Object)(object)s == (Object)null); component.soundEventsToPlay?.RemoveAll((AkEvent s) => (Object)(object)s == (Object)null); component.childSpecialObjectAttributes?.RemoveAll((SpecialObjectAttributes c) => (Object)(object)c == (Object)null); component.skillHighlightRenderers?.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); } } catch (Exception arg) { Log.Error($"[SanitizePassengerSpecialAttributes] Exception during sanitization for {((Object)passenger).name}: {arg}"); } } } [HarmonyPatch(typeof(GlobalEventManager), "OnCharacterDeath")] public static class GlobalEventManager_OnCharacterDeath { [HarmonyPostfix] public static void Postfix(DamageReport damageReport) { if (damageReport == null || (Object)(object)damageReport.victimBody == (Object)null) { return; } GameObject gameObject = ((Component)damageReport.victimBody).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } foreach (DrifterBagController allController in BagPatches.GetAllControllers()) { List baggedObjects = BagPatches.GetState(allController).BaggedObjects; if (baggedObjects != null && baggedObjects.Contains(gameObject)) { BagPassengerManager.RemoveBaggedObject(allController, gameObject); } } if (PersistenceObjectManager.IsObjectPersisted(gameObject)) { PersistenceObjectManager.RemovePersistedObject(gameObject, isDestroying: true); } } } public static class BagCapacityCalculator { private static readonly Dictionary _capacityVarsBuffer = new Dictionary(); private static readonly HashSet _countedInstanceIdsBuffer = new HashSet(); public static int GetUtilityMaxStock(DrifterBagController? drifterBagController, GameObject? incomingObject = null) { if ((Object)(object)drifterBagController == (Object)null || !PluginConfig.Instance.BottomlessBagEnabled.Value) { return 1; } Dictionary capacityVarsBuffer = _capacityVarsBuffer; capacityVarsBuffer.Clear(); CharacterBody component = ((Component)drifterBagController).GetComponent(); if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component.skillLocator) && Object.op_Implicit((Object)(object)component.skillLocator.utility)) { capacityVarsBuffer["H"] = component.maxHealth; capacityVarsBuffer["L"] = component.level; capacityVarsBuffer["C"] = component.skillLocator.utility.maxStock; capacityVarsBuffer["S"] = ((!Object.op_Implicit((Object)(object)Run.instance)) ? 1 : (Run.instance.stageClearCount + 1)); } else { capacityVarsBuffer["H"] = 0f; capacityVarsBuffer["L"] = 0f; capacityVarsBuffer["C"] = 0f; capacityVarsBuffer["S"] = ((!Object.op_Implicit((Object)(object)Run.instance)) ? 1 : (Run.instance.stageClearCount + 1)); } int result = FormulaParser.EvaluateInt(PluginConfig.Instance.SlotScalingFormula.Value, capacityVarsBuffer); if (PluginConfig.Instance.OverencumbranceMax.Value > 0f && PluginConfig.Instance.EnableBalance.Value) { int currentBaggedCount = GetCurrentBaggedCount(drifterBagController); float num = CalculateTotalBagMass(drifterBagController, incomingObject); float num2 = CapacityScalingSystem.CalculateMaxMassCapacity(drifterBagController); if (num >= num2) { result = Math.Max(1, currentBaggedCount); } } return result; } public static float CalculateTotalBagMass(DrifterBagController drifterBagController, GameObject? incomingObject = null) { if ((Object)(object)drifterBagController == (Object)null) { return 0f; } float num = drifterBagController.baggedMass; GameObject val = incomingObject; if ((Object)(object)val == (Object)null) { val = BagPatches.GetState(drifterBagController).IncomingObject; } if ((Object)(object)val != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(val)) { num += drifterBagController.CalculateBaggedObjectMass(val); } return num; } public static int GetCurrentBaggedCount(DrifterBagController? controller) { if ((Object)(object)controller == (Object)null) { return 0; } BottomlessBagNetworkController component = ((Component)controller).GetComponent(); if ((Object)(object)component != (Object)null) { return component.GetTotalObjectCount(); } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return 0; } int num = 0; HashSet countedInstanceIdsBuffer = _countedInstanceIdsBuffer; countedInstanceIdsBuffer.Clear(); foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(item)) { int instanceID = ((Object)item).GetInstanceID(); if (!countedInstanceIdsBuffer.Contains(instanceID)) { countedInstanceIdsBuffer.Add(instanceID); num++; } } } return num; } public static bool HasRoomForGrab(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return false; } int utilityMaxStock = GetUtilityMaxStock(controller); int currentBaggedCount = GetCurrentBaggedCount(controller); bool flag = currentBaggedCount < utilityMaxStock; if (!flag) { DrifterBagAPI.InvokeOnBagFull(controller); } return flag; } public static float GetBaggedObjectMass(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 0f; } return controller.baggedMass; } } public static class BagCarouselUpdater { internal static readonly List ActiveCarousels = new List(); private static bool IsValidBaggedObject(GameObject obj) { if ((Object)(object)obj == (Object)null || !Object.op_Implicit((Object)(object)obj)) { return false; } HealthComponent component = obj.GetComponent(); if ((Object)(object)component != (Object)null && !component.alive) { return false; } SpecialObjectAttributes component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null && component2.durability <= 0) { return false; } return true; } public static void UpdateCarousel(DrifterBagController controller, int direction = 0) { Log.Debug(string.Format("[UpdateCarousel] Controller: {0} Dir: {1}.", Object.op_Implicit((Object)(object)controller) ? ((Object)controller).name : "null", direction)); for (int num = ActiveCarousels.Count - 1; num >= 0; num--) { BaggedObjectCarousel baggedObjectCarousel = ActiveCarousels[num]; if ((Object)(object)baggedObjectCarousel == (Object)null) { ActiveCarousels.RemoveAt(num); } else { baggedObjectCarousel.PopulateCarousel(direction); } } } public static void UpdateNetworkBagState(DrifterBagController? controller, int direction = 0) { if (controller == null) { return; } if ((controller != null && !Object.op_Implicit((Object)(object)controller)) || (!NetworkServer.active && !((NetworkBehaviour)controller).hasAuthority)) { return; } BottomlessBagNetworkController component = ((Component)controller).GetComponent(); if (!((Object)(object)component != (Object)null)) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; baggedObjects.RemoveAll(delegate(GameObject obj) { if (obj != null) { if (obj == null || Object.op_Implicit((Object)(object)obj)) { return !IsValidBaggedObject(obj); } } return true; }); List list = new List(); ConcurrentDictionary additionalSeats = BagPatches.GetState(controller).AdditionalSeats; if (additionalSeats != null) { foreach (VehicleSeat value in additionalSeats.Values) { if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null && Object.op_Implicit((Object)(object)((Component)value).gameObject) && IsValidBaggedObject(((Component)value).gameObject)) { list.Add(((Component)value).gameObject); } } } int index = -1; GameObject val = BagPatches.GetMainSeatObject(controller); if ((Object)(object)val != (Object)null && !IsValidBaggedObject(val)) { BagPatches.SetMainSeatObject(controller, null); val = null; } bool flag = false; if ((Object)(object)val != (Object)null && (Object)(object)controller.vehicleSeat != (Object)null && controller.vehicleSeat.hasPassenger && controller.vehicleSeat.NetworkpassengerBodyObject == val) { flag = true; } bool flag2 = !NetworkServer.active && ((NetworkBehaviour)controller).hasAuthority && (Object)(object)val != (Object)null && !flag; if (flag || flag2) { for (int i = 0; i < baggedObjects.Count; i++) { GameObject val2 = baggedObjects[i]; if ((Object)(object)val2 != (Object)null && (Object)(object)val != (Object)null && ((Object)val2).GetInstanceID() == ((Object)val).GetInstanceID()) { index = i; if (PluginConfig.Instance.EnableDebugLogs.Value) { string arg = (flag ? "physically in main seat" : "tracked as main (client)"); Log.Debug($"[UpdateNetworkBagState] Setting selectedIndex to {i} for {((Object)val2).name} ({arg})."); } break; } } } else if ((Object)(object)val != (Object)null) { string[] obj2 = new string[7] { "[UpdateNetworkBagState] Skipping selectedIndex calculation - ", ((Object)val).name, " is tracked as main but not physically in main seat. ", $"isActuallyInMainSeat={flag}, useTrackedMainSeat={flag2}. ", "Physical passenger: ", null, null }; VehicleSeat vehicleSeat = controller.vehicleSeat; object obj3; if (vehicleSeat == null) { obj3 = null; } else { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; obj3 = ((networkpassengerBodyObject != null) ? ((Object)networkpassengerBodyObject).name : null); } if (obj3 == null) { obj3 = "null"; } obj2[5] = (string)obj3; obj2[6] = "."; Log.Debug(string.Concat(obj2)); } component.SetBagState(index, baggedObjects, list, direction); } } public static class BagHelpers { public static string GetSafeName(Object? obj) { if (!Object.op_Implicit(obj)) { return "null"; } return obj.name; } public static void AddTracker(DrifterBagController? controller, GameObject obj) { if ((Object)(object)obj == (Object)null || (Object)(object)controller == (Object)null) { return; } BaggedObjectTracker baggedObjectTracker = obj.GetComponent(); if ((Object)(object)baggedObjectTracker == (Object)null) { baggedObjectTracker = obj.AddComponent(); baggedObjectTracker.obj = obj; } if ((Object)(object)baggedObjectTracker != (Object)null && (Object)(object)baggedObjectTracker.controller != (Object)(object)controller) { baggedObjectTracker.controller = controller; } if (!((Object)(object)baggedObjectTracker != (Object)null)) { return; } EntityStateMachine[] components = obj.GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Body") { BaggedObjectStatePatches.RegisterTrackedESM(val, baggedObjectTracker); break; } } } public static void CleanupEmptyAdditionalSeats(DrifterBagController? controller) { if ((Object)(object)controller == (Object)null) { return; } ConcurrentDictionary additionalSeats = BagPatches.GetState(controller).AdditionalSeats; List list = new List(); if (additionalSeats != null) { foreach (KeyValuePair item in additionalSeats) { VehicleSeat value = item.Value; if ((Object)(object)value == (Object)null || (Object)(object)((Component)value).gameObject == (Object)null) { if ((Object)(object)value != (Object)null && NetworkServer.active) { NetworkServer.Destroy(((Component)value).gameObject); } if ((Object)(object)value != (Object)null && (Object)(object)((Component)value).gameObject != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } list.Add(item.Key); } } foreach (GameObject item2 in list) { additionalSeats.TryRemove(item2, out var _); } } VehicleSeat[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val in array) { if (!((Object)(object)val == (Object)(object)controller.vehicleSeat) && (additionalSeats == null || !additionalSeats.Values.Contains(val)) && !val.hasPassenger) { if (NetworkServer.active) { NetworkServer.Destroy(((Component)val).gameObject); } Object.Destroy((Object)(object)((Component)val).gameObject); } } } public static VehicleSeat? GetAdditionalSeat(DrifterBagController? controller, GameObject obj) { if ((Object)(object)obj == (Object)null || (Object)(object)controller == (Object)null) { return null; } ConcurrentDictionary additionalSeats = BagPatches.GetState(controller).AdditionalSeats; if (additionalSeats != null && additionalSeats.TryGetValue(obj, out var value)) { return value; } return null; } public static bool IsBaggedObject(DrifterBagController? controller, GameObject? obj) { if ((Object)(object)obj == (Object)null || (Object)(object)controller == (Object)null) { return false; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects != null) { int instanceID = ((Object)obj).GetInstanceID(); foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && ((Object)item).GetInstanceID() == instanceID) { return true; } } } return false; } } public static class BagPassengerManager { private static readonly FieldInfo _baggedMassField = ReflectionCache.DrifterBagController.BaggedMass; private static readonly FieldInfo _walkSpeedModifierField = ReflectionCache.BaggedObject.WalkSpeedModifier; private static readonly Dictionary _modWalkSpeedModifiers = new Dictionary(); private static readonly List _removeKeysBuffer = new List(); private static readonly Dictionary _penaltyVarsBuffer = new Dictionary(); public static volatile bool IsProcessingThrowRemoval = false; public static void MarkMassDirty(DrifterBagController controller) { if (!((Object)(object)controller == (Object)null)) { BagPatches.GetState(controller).MarkMassDirty(); } } public static void RemoveBaggedObject(DrifterBagController? controller, GameObject obj, bool isDestroying = false, bool skipStateReset = false, bool preserveStateDuringThrow = false) { //IL_048d: Unknown result type (might be due to invalid IL or missing references) //IL_0494: Expected O, but got Unknown if ((Object)(object)controller == (Object)null || obj == null) { return; } int targetInstanceId; try { targetInstanceId = ((Object)obj).GetInstanceID(); } catch { targetInstanceId = -1; } if (DrifterBossGrabPlugin.IsSwappingPassengers) { return; } GameObject mainSeatObject = BagPatches.GetMainSeatObject(controller); bool flag = (Object)(object)mainSeatObject != (Object)null && (Object)(object)mainSeatObject == (Object)(object)obj; if ((Object)(object)mainSeatObject != (Object)null && ((Object)mainSeatObject).GetInstanceID() == ((Object)obj).GetInstanceID()) { BagPatches.SetMainSeatObject(controller, null); flag = true; } ConcurrentDictionary additionalSeats = BagPatches.GetState(controller).AdditionalSeats; VehicleSeat value = null; if (additionalSeats != null) { additionalSeats.TryRemove(obj, out value); _removeKeysBuffer.Clear(); foreach (KeyValuePair item in additionalSeats) { if ((Object)(object)item.Value != (Object)null && (Object)(object)item.Value.NetworkpassengerBodyObject == (Object)(object)obj) { _removeKeysBuffer.Add(item.Key); } } foreach (GameObject item2 in _removeKeysBuffer) { additionalSeats.TryRemove(item2, out var _); } } bool flag2 = ProjectileRecoveryPatches.IsInProjectileState(obj); List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } if (baggedObjects != null) { try { BaggedObjectTracker component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { component.isRemovingManual = true; EntityStateMachine[] components = obj.GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Body") { BaggedObjectStatePatches.UnregisterTrackedESM(val); break; } } Object.Destroy((Object)(object)component); } } catch (Exception ex) { Log.Error("[RemoveBaggedObject] Error destroying tracker: " + ex.Message); } PersistenceObjectsTracker.UntrackBaggedObject(obj, isDestroying); baggedObjects.RemoveAll(delegate(GameObject x) { if (x != null) { if (x == null || Object.op_Implicit((Object)(object)x)) { if (targetInstanceId != -1) { return ((Object)x).GetInstanceID() == targetInstanceId; } return false; } } return true; }); if (targetInstanceId != -1) { BagPatches.GetState(controller).RemoveInstanceId(targetInstanceId); } if (flag) { if (PluginConfig.Instance.EnableDebugLogs.Value) { string bagStateMachineState = GetBagStateMachineState(controller); Log.Debug("[RemoveBaggedObject] Was main passenger destroyed. Current Bag state: " + bagStateMachineState); } if (ReflectionCache.DrifterBagController.Smacks != null) { int smacks = (int)ReflectionCache.DrifterBagController.Smacks.GetValue(controller); BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(controller, obj); if (baggedObjectStateData != null) { baggedObjectStateData.smacks = smacks; BaggedObjectPatches.SaveObjectState(controller, obj, baggedObjectStateData); } ReflectionCache.DrifterBagController.Smacks.SetValue(controller, 0); } DrifterBagAPI.InvokeOnMainPassengerChanged(controller, mainSeatObject, null); EjectMainPassengerIfServer(controller, obj, isDestroying); BagPatches.SetMainSeatObject(controller, null); if (AuthorityGuard.ShouldAutoPromote(controller) && baggedObjects.Count > 0) { GameObject val2 = baggedObjects[0]; if ((Object)(object)val2 != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(val2)) { Log.Debug("[RemoveBaggedObject] Triggering autopromote for: " + ((Object)val2).name); DelayedAutoPromote.Schedule(controller, val2, 0.05f); } } } } if (flag2) { BagHelpers.CleanupEmptyAdditionalSeats(controller); } if ((Object)(object)value != (Object)null && NetworkServer.active && !isDestroying) { try { value.EjectPassenger(obj); Log.Debug("[RemoveBaggedObject] Ejected " + ((Object)obj).name + " from additional seat"); } catch (Exception ex2) { Log.Warning("[RemoveBaggedObject] Error ejecting from additional seat: " + ex2.Message); } } if (preserveStateDuringThrow) { if ((Object)(object)controller != (Object)null && (Object)(object)obj != (Object)null) { BaggedObjectStateStorage.PreserveStateForThrow(controller, obj); } } else if (isDestroying || (!flag2 && !DrifterBossGrabPlugin.IsSwappingPassengers)) { if ((Object)(object)controller != (Object)null && (Object)(object)obj != (Object)null) { BaggedObjectPatches.CleanupObjectState(controller, obj); } if ((Object)(object)obj != (Object)null) { BaggedObjectStatePatches.BaggedObject_OnExit.ClearObjectSuccessfullyInitialized(obj); } } if (flag && (Object)(object)controller != (Object)null && (Object)(object)obj != (Object)null) { BaggedObjectStatePatches.ForceCleanupOverrides(controller, obj); } if ((Object)(object)obj != (Object)null) { AdditionalSeatBreakoutTimer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { Object.Destroy((Object)(object)component2); } } if (AuthorityGuard.ShouldSendPersistence(controller) && baggedObjects != null) { PersistenceNetworkHandler.SendBaggedObjectsPersistenceMessage(baggedObjects, controller); } int direction = (flag ? 1 : 0); if ((Object)(object)controller != (Object)null) { IsProcessingThrowRemoval = flag2; BagCarouselUpdater.UpdateCarousel(controller, direction); } if ((Object)(object)controller != (Object)null) { BagCarouselUpdater.UpdateNetworkBagState(controller, direction); } if (flag2 && (Object)(object)controller != (Object)null) { IsProcessingThrowRemoval = false; } if ((Object)(object)controller != (Object)null && !skipStateReset) { EntityStateMachine[] components2 = ((Component)controller).GetComponents(); EntityStateMachine[] array2 = components2; foreach (EntityStateMachine val3 in array2) { if (val3.customName == "Bag") { GameObject val4 = (((Object)(object)controller != (Object)null) ? BagPatches.GetMainSeatObject(controller) : null); if ((Object)(object)val4 != (Object)null) { BaggedObject val5 = new BaggedObject(); val5.targetObject = val4; val3.SetNextState((EntityState)(object)val5); } else { val3.SetNextStateToMain(); } break; } } } if ((Object)(object)controller != (Object)null) { MarkMassDirty(controller); } if ((Object)(object)obj != (Object)null && !isDestroying && !flag2 && (Object)(object)controller != (Object)null) { BagState state = BagPatches.GetState(controller); if (state != null && state.DisabledCollidersByObject.TryGetValue(obj, out Dictionary value3)) { BodyColliderCache.RestoreMovementColliders(value3); state.DisabledCollidersByObject.TryRemove(obj, out Dictionary _); Log.Debug("[RemoveBaggedObject] Restored movement colliders for ungrabbable enemy " + ((Object)obj).name); } } if (PluginConfig.Instance.EnableObjectPersistence.Value) { TeleporterInteraction val6 = (((Object)(object)obj != (Object)null) ? obj.GetComponent() : null); if ((Object)(object)val6 != (Object)null && (Object)(object)obj != (Object)null) { PersistenceManager.UnmarkTeleporterAsBagged(obj); ((Behaviour)val6).enabled = true; MultiTeleporterTracker.RegisterSecondary(val6); TeleporterInteraction primary = MultiTeleporterTracker.GetPrimary(); if ((Object)(object)primary != (Object)null) { TeleporterInteraction.instance = primary; } } } if ((Object)(object)obj != (Object)null && (Object)(object)controller != (Object)null) { DrifterBagAPI.InvokeOnObjectReleased(controller, obj, isDestroying); } } public static void ForceRecalculateMass(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return; } BagState state = BagPatches.GetState(controller); float previousTotalMass = 0f; if (_baggedMassField != null) { previousTotalMass = (float)_baggedMassField.GetValue(controller); } float num; if (PluginConfig.Instance.EnableBalance.Value && PluginConfig.Instance.StateCalculationMode.Value == StateCalculationMode.All) { num = 0f; List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects != null) { foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(item)) { num += controller.CalculateBaggedObjectMass(item); } } } } else { GameObject mainSeatObject = BagPatches.GetMainSeatObject(controller); if ((Object)(object)mainSeatObject != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(mainSeatObject)) { num = controller.CalculateBaggedObjectMass(mainSeatObject); } else { num = 0f; List baggedObjects2 = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects2 != null) { foreach (GameObject item2 in baggedObjects2) { if ((Object)(object)item2 != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(item2)) { num += controller.CalculateBaggedObjectMass(item2); } } } } } num = Mathf.Max(num, 0f); if (_baggedMassField != null) { _baggedMassField.SetValue(controller, num); CharacterBody component = ((Component)controller).GetComponent(); if (component != null) { component.RecalculateStats(); } EntityStateMachine[] components = ((Component)controller).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Bag") { EntityState state2 = val.state; BaggedObject val2 = (BaggedObject)(object)((state2 is BaggedObject) ? state2 : null); if (val2 != null) { BaggedObjectPatches.UpdateBagScale(val2, num); ReflectionCache.BaggedObject.BaggedMass?.SetValue(val2, num); break; } } } UpdateModWalkSpeedPenalty(controller, num); } UIPatches.UpdateMassCapacityUIOnCapacityChange(controller); if (PluginConfig.Instance.EnableBalance.Value && (PluginConfig.Instance.IsBagScaleCapInfinite || PluginConfig.Instance.ParsedBagScaleCap > 1f)) { UpdateUncappedBagScale(controller, num); } state.ClearMassDirty(); DrifterBagAPI.InvokeOnMassRecalculated(controller, num, previousTotalMass); if (!PluginConfig.Instance.EnableBalance.Value) { return; } float num2 = CapacityScalingSystem.CalculateMassCapacity(controller); if (num2 > 0f) { float num3 = num / num2; if (num3 > 1f) { DrifterBagAPI.InvokeOnOverencumbered(controller, num3); } } } public static void UpdateModWalkSpeedPenalty(DrifterBagController controller, float totalMass) { //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Expected O, but got Unknown if ((Object)(object)controller == (Object)null) { return; } CharacterMotor component = ((Component)controller).GetComponent(); if (!((Object)(object)component == (Object)null)) { float num = 0f; if (PluginConfig.Instance.EnableBalance.Value || PluginConfig.Instance.BottomlessBagEnabled.Value) { CharacterBody component2 = ((Component)controller).GetComponent(); float value = (((Object)(object)component2 != (Object)null) ? component2.maxHealth : 0f); float value2 = (((Object)(object)component2 != (Object)null) ? component2.level : 1f); float num2 = (((Object)(object)component2 != (Object)null && (Object)(object)component2.skillLocator != (Object)null && (Object)(object)component2.skillLocator.utility != (Object)null) ? ((float)component2.skillLocator.utility.maxStock) : 1f); float value3 = CapacityScalingSystem.CalculateMassCapacity(controller); float value4 = CapacityScalingSystem.GetTotalCapacity(controller); Dictionary penaltyVarsBuffer = _penaltyVarsBuffer; penaltyVarsBuffer.Clear(); penaltyVarsBuffer["T"] = totalMass; penaltyVarsBuffer["M"] = value3; penaltyVarsBuffer["C"] = value4; penaltyVarsBuffer["H"] = value; penaltyVarsBuffer["L"] = value2; penaltyVarsBuffer["MC"] = PluginConfig.Instance.ParsedMassCap; penaltyVarsBuffer["S"] = ((!Object.op_Implicit((Object)(object)Run.instance)) ? 1 : (Run.instance.stageClearCount + 1)); num = FormulaParser.Evaluate(PluginConfig.Instance.MovespeedPenaltyFormula.Value, penaltyVarsBuffer); } if (totalMass <= 0f || num <= 0f) { RemoveModWalkSpeedPenalty(controller); return; } if (_modWalkSpeedModifiers.TryGetValue(controller, out WalkSpeedPenaltyModifier value5)) { value5.penalty = num; component.RecalculateWalkSpeedPenalty(); return; } WalkSpeedPenaltyModifier val = new WalkSpeedPenaltyModifier { penalty = num }; component.AddWalkSpeedPenalty(val); _modWalkSpeedModifiers[controller] = val; } } public static void RemoveModWalkSpeedPenalty(DrifterBagController controller) { if (!((Object)(object)controller == (Object)null) && _modWalkSpeedModifiers.TryGetValue(controller, out WalkSpeedPenaltyModifier value)) { CharacterMotor component = ((Component)controller).GetComponent(); if (component != null) { component.RemoveWalkSpeedPenalty(value); } _modWalkSpeedModifiers.Remove(controller); } } public static void SuppressVanillaWalkSpeedModifier(BaggedObject instance) { if (instance == null || (!PluginConfig.Instance.EnableBalance.Value && !PluginConfig.Instance.BottomlessBagEnabled.Value)) { return; } try { object? obj = _walkSpeedModifierField?.GetValue(instance); WalkSpeedPenaltyModifier val = (WalkSpeedPenaltyModifier)((obj is WalkSpeedPenaltyModifier) ? obj : null); if (val != null) { EntityStateMachine outer = ((EntityState)instance).outer; CharacterMotor val2 = ((outer != null) ? ((Component)outer).GetComponent() : null); if (val2 != null) { val2.RemoveWalkSpeedPenalty(val); } _walkSpeedModifierField?.SetValue(instance, null); } } catch (Exception ex) { Log.Error("[SuppressVanillaWalkSpeedModifier] Error: " + ex.Message); } } public static void UpdateUncappedBagScale(DrifterBagController controller, float mass) { if ((Object)(object)controller == (Object)null) { return; } UncappedBagScaleComponent uncappedBagScaleComponent = BagPatches.GetState(controller).UncappedBagScale; if ((Object)(object)uncappedBagScaleComponent == (Object)null) { uncappedBagScaleComponent = ((Component)controller).gameObject.GetComponent(); if ((Object)(object)uncappedBagScaleComponent == (Object)null) { uncappedBagScaleComponent = ((Component)controller).gameObject.AddComponent(); uncappedBagScaleComponent.Initialize(controller); if (!((Object)(object)uncappedBagScaleComponent != (Object)null) || !uncappedBagScaleComponent.IsInitialized) { Log.Warning("[BagPatch] Failed to initialize UncappedBagScaleComponent for " + ((Object)controller).name); return; } BagPatches.GetState(controller).UncappedBagScale = uncappedBagScaleComponent; } else { BagPatches.GetState(controller).UncappedBagScale = uncappedBagScaleComponent; } } if ((Object)(object)uncappedBagScaleComponent != (Object)null && uncappedBagScaleComponent.IsInitialized) { uncappedBagScaleComponent.UpdateScaleFromMass(mass); } } private static string GetBagStateMachineState(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return "null"; } EntityStateMachine[] components = ((Component)controller).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Bag") { return ((object)val.state)?.GetType().Name ?? "null"; } } return "not found"; } private static void EjectMainPassengerIfServer(DrifterBagController controller, GameObject obj, bool isDestroying) { if (!AuthorityGuard.IsServerWithPassenger(controller, obj)) { return; } if (isDestroying) { try { Log.Debug("[RemoveBaggedObject] About to eject passenger from main seat: " + BagHelpers.GetSafeName((Object?)(object)obj)); controller.vehicleSeat.EjectPassenger(obj); Log.Debug("[RemoveBaggedObject] Successfully ejected passenger from main seat"); return; } catch (Exception ex) { Log.Error("[RemoveBaggedObject] Error ejecting passenger: " + ex.GetType().Name + " - " + ex.Message); try { Log.Debug("[RemoveBaggedObject] Forcibly clearing passenger state due to exception."); FieldInfo field = typeof(VehicleSeat).GetField("passengerBodyObject", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { field.SetValue(controller.vehicleSeat, null); } controller.vehicleSeat.NetworkpassengerBodyObject = null; return; } catch (Exception ex2) { Log.Error("[RemoveBaggedObject] Failed to forcefully clear passenger state: " + ex2.Message); return; } } } controller.vehicleSeat.EjectPassenger(obj); } } public static class BottomlessBagPatches { public static void HandleInput() { CyclingInputHandler.HandleInput(); } public static void CyclePassengers(DrifterBagController bagController, int amount) { PassengerCycler.CyclePassengers(bagController, amount); } public static void ServerCyclePassengers(DrifterBagController bagController, int amount) { PassengerCycler.ServerCyclePassengers(bagController, amount); } } public class AdditionalSeatBreakoutTimer : MonoBehaviour { public DrifterBagController? controller; public float breakoutTime; public float breakoutAttempts; private bool _hasPlayedRustle; private CharacterBody? _cachedBody; private SfxLocator? _cachedSfxLocator; private static Dictionary _wiggleLoopsActive = new Dictionary(); private static readonly MethodInfo _cachedPlayCrossfadeMethod = typeof(EntityState).GetMethod("PlayCrossfade", BindingFlags.Instance | BindingFlags.NonPublic, null, new Type[5] { typeof(string), typeof(string), typeof(string), typeof(float), typeof(float) }, null); private float _breakoutTimer; private int _baseBreakoutChance1inX = 3; private static GameObject? _cachedProjectilePrefab; public static bool CanBreakout(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } CharacterBody component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return false; } if (component.isPlayerControlled) { return false; } if ((Object)(object)component.master == (Object)null) { return false; } if ((Object)(object)component.healthComponent == (Object)null || !component.healthComponent.alive) { return false; } return true; } private void Start() { _cachedBody = ((Component)this).gameObject.GetComponent(); _cachedSfxLocator = ((Component)this).gameObject.GetComponent(); } public float GetElapsedBreakoutTime() { return _breakoutTimer; } public void SetElapsedBreakoutTime(float time) { _breakoutTimer = time; } public void ManualSave() { if (!((Object)(object)controller == (Object)null) && !((Object)(object)((Component)this).gameObject == (Object)null)) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(controller, ((Component)this).gameObject); if (baggedObjectStateData == null) { baggedObjectStateData = new BaggedObjectStateData(); baggedObjectStateData.CalculateFromObject(((Component)this).gameObject, controller); } baggedObjectStateData.elapsedBreakoutTime = _breakoutTimer; baggedObjectStateData.breakoutAttempts = (int)breakoutAttempts; baggedObjectStateData.breakoutTime = breakoutTime; BaggedObjectPatches.SaveObjectState(controller, ((Component)this).gameObject, baggedObjectStateData); } } private void FixedUpdate() { DrifterBagController val = controller; if (!_hasPlayedRustle && (Object)(object)val != (Object)null && NetworkServer.active) { _hasPlayedRustle = true; PlayBagAnimation("Bag, Rumble", "Rustle", "Rumble.playbackRate", 1f, 0.1f); AddWiggleLoop(((Component)val).gameObject); } if ((Object)(object)val == (Object)null) { Log.Debug("[DEBUG] [AdditionalSeatBreakoutTimer] Destroying timer on " + ((Object)((Component)this).gameObject).name + ": controller is null"); Object.Destroy((Object)(object)this); } else { if (!NetworkServer.active) { return; } try { CharacterBody val2 = _cachedBody ?? ((Component)this).gameObject.GetComponent(); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.healthComponent == (Object)null || !val2.healthComponent.alive) { Object.Destroy((Object)(object)this); return; } if ((Object)(object)BagHelpers.GetAdditionalSeat(val, ((Component)this).gameObject) == (Object)null) { if (!DrifterBossGrabPlugin._isSwappingPassengers) { Log.Debug("[DEBUG] [AdditionalSeatBreakoutTimer] Destroying timer on " + ((Object)((Component)this).gameObject).name + ": no longer in an additional seat"); ManualSave(); Object.Destroy((Object)(object)this); } return; } } catch (Exception arg) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning($"[AdditionalSeatBreakoutTimer] Error validating object state: {arg}"); } Object.Destroy((Object)(object)this); return; } if ((Object)(object)val == (Object)null || (Object)(object)((Component)this).gameObject == (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { GameObject gameObject = ((Component)this).gameObject; Log.Warning("[AdditionalSeatBreakoutTimer] Cleaning up due to null controller or object for " + (((gameObject != null) ? ((Object)gameObject).name : null) ?? "unknown")); } ManualSave(); Object.Destroy((Object)(object)this); return; } _breakoutTimer += Time.fixedDeltaTime; if (breakoutTime <= 0f) { float num = val.CalculateBaggedObjectMass(((Component)this).gameObject); breakoutTime = Mathf.Max(10f - 0.005f * num, 1f) * PluginConfig.Instance.BreakoutTimeMultiplier.Value; Log.Debug($"[AdditionalSeatBreakoutTimer] Initialized breakoutTime for {((Object)((Component)this).gameObject).name} to {breakoutTime:F2}s"); } if (_breakoutTimer >= breakoutTime * 0.5f) { SpecialObjectAttributes.ForceBreakout(((Component)this).gameObject); } if (_breakoutTimer >= breakoutTime) { _breakoutTimer -= breakoutTime; breakoutTime *= 0.65f; breakoutAttempts += 1f; Log.Debug($"[DEBUG] [AdditionalSeatBreakoutTimer] {((Object)((Component)this).gameObject).name} breakout attempt #{breakoutAttempts}. Breakout time adjusted to {breakoutTime:F2}"); if ((Object)(object)_cachedSfxLocator != (Object)null && _cachedSfxLocator.barkSound != null) { Util.PlaySound(_cachedSfxLocator.barkSound, ((Component)this).gameObject); } if (!DrifterBagController.bagDisableBreakout && Random.Range(0, _baseBreakoutChance1inX) == 0) { Log.Debug("[DEBUG] [AdditionalSeatBreakoutTimer] " + ((Object)((Component)this).gameObject).name + " successfully broke out from the additional seat!"); Breakout(); BagPassengerManager.RemoveBaggedObject(val, ((Component)this).gameObject); } else { PlayBagAnimation("Bag, Rumble", "BagBurst", "Rumble.playbackRate", 0.5f, 0.1f); } } } } private void OnDestroy() { DrifterBagController val = controller; if (_hasPlayedRustle && (Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { RemoveWiggleLoop(((Component)val).gameObject); PlayBagAnimation("Bag, Rumble", "Empty", "Rumble.playbackRate", 1f, 0.1f); } } private static void AddWiggleLoop(GameObject drifterObject) { if (!((Object)(object)drifterObject == (Object)null)) { if (!_wiggleLoopsActive.TryGetValue(drifterObject, out var value)) { value = 0; } if (value == 0) { Util.PlaySound("Play_drifter_repossess_bagWiggle_Loop", drifterObject); } _wiggleLoopsActive[drifterObject] = value + 1; } } private static void RemoveWiggleLoop(GameObject drifterObject) { if (!((Object)(object)drifterObject == (Object)null) && _wiggleLoopsActive.TryGetValue(drifterObject, out var value)) { value--; if (value <= 0) { Util.PlaySound("Stop_drifter_repossess_bagWiggle_Loop", drifterObject); value = 0; } _wiggleLoopsActive[drifterObject] = value; } } private void PlayBagAnimation(string layerName, string animationStateName, string playbackRateParam, float duration, float crossfadeDuration) { DrifterBagController val = controller; if (!((Object)(object)val == (Object)null)) { EntityStateMachine val2 = EntityStateMachine.FindByCustomName(((Component)val).gameObject, "Bag"); if ((Object)(object)val2 != (Object)null && val2.state != null && _cachedPlayCrossfadeMethod != null) { _cachedPlayCrossfadeMethod.Invoke(val2.state, new object[5] { layerName, animationStateName, playbackRateParam, duration, crossfadeDuration }); } } } private void Breakout() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) //IL_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_027e: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_0218: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)((Component)this).gameObject == (Object)null) { return; } CharacterBody val = _cachedBody ?? ((Component)this).gameObject.GetComponent(); if ((Object)(object)val != (Object)null && (Object)(object)val.healthComponent != (Object)null && !val.healthComponent.alive) { return; } DrifterBagController val2 = controller; if ((Object)(object)val2 == (Object)null) { return; } Vector3 val3 = Vector3.up; if ((Object)(object)val != (Object)null && (Object)(object)val.characterDirection != (Object)null) { val3 = Quaternion.AngleAxis((Random.value < 0.5f) ? 45f : (-45f), -val.characterDirection.forward) * Vector3.up; } float num = val2.CalculateBaggedObjectMass(((Component)this).gameObject); float num2 = Mathf.Max(10f, 30f * num / CapacityScalingSystem.CalculateMassCapacity(val2)); if (!PluginConfig.Instance.IsMaxLaunchSpeedInfinite) { num2 = Mathf.Min(num2, PluginConfig.Instance.ParsedMaxLaunchSpeed); } if ((Object)(object)_cachedProjectilePrefab == (Object)null) { _cachedProjectilePrefab = Addressables.LoadAssetAsync((object)"RoR2/DLC3/Drifter/ThrownObjectProjectileNoStun.prefab").WaitForCompletion(); } Transform val4 = null; if ((Object)(object)val != (Object)null && (Object)(object)val.modelLocator != (Object)null && (Object)(object)val.modelLocator.modelTransform != (Object)null) { Animator component = ((Component)val.modelLocator.modelTransform).GetComponent(); if ((Object)(object)component != (Object)null) { Transform[] componentsInChildren = ((Component)val.modelLocator.modelTransform).GetComponentsInChildren(); Transform[] array = componentsInChildren; foreach (Transform val5 in array) { if (((Object)val5).name.Contains("Exit") || ((Object)val5).name.Contains("Muzzle") || ((Object)val5).name.Contains("Throw")) { val4 = val5; break; } } } } FireProjectileInfo val6 = default(FireProjectileInfo); val6.projectilePrefab = _cachedProjectilePrefab; val6.position = (((Object)(object)val4 != (Object)null) ? val4.position : (((Object)(object)val != (Object)null) ? val.transform.position : ((Component)val2).transform.position)); val6.rotation = Util.QuaternionSafeLookRotation(val3); val6.owner = ((Component)val2).gameObject; val6.damage = 0f; ((FireProjectileInfo)(ref val6)).speedOverride = num2; val6.force = 20f; val6.crit = false; val6.damageColorIndex = (DamageColorIndex)0; val6.target = null; FireProjectileInfo val7 = val6; GameObject val8 = ProjectileManager.instance.FireProjectileImmediateServer(val7, (NetworkConnection)null, (ushort)0, 0.0); if ((Object)(object)val8 != (Object)null) { ThrownObjectProjectileController component2 = val8.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.SetPassengerServer(((Component)this).gameObject); } } } } public static class AdditionalSeatManager { public static void CopySeatProperties(VehicleSeat source, VehicleSeat target) { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null) && !((Object)(object)target == (Object)null)) { target.seatPosition = source.seatPosition; target.exitPosition = source.exitPosition; target.ejectOnCollision = source.ejectOnCollision; target.hidePassenger = source.hidePassenger; target.exitVelocityFraction = source.exitVelocityFraction; target.disablePassengerMotor = source.disablePassengerMotor; target.isEquipmentActivationAllowed = source.isEquipmentActivationAllowed; target.shouldProximityHighlight = source.shouldProximityHighlight; target.disableInteraction = source.disableInteraction; target.shouldSetIdle = source.shouldSetIdle; target.additionalExitVelocity = source.additionalExitVelocity; target.disableAllCollidersAndHurtboxes = source.disableAllCollidersAndHurtboxes; target.disableColliders = source.disableColliders; target.disableCharacterNetworkTransform = source.disableCharacterNetworkTransform; target.ejectFromSeatOnMapEvent = source.ejectFromSeatOnMapEvent; target.inheritRotation = source.inheritRotation; target.holdPassengerAfterDeath = source.holdPassengerAfterDeath; target.ejectPassengerToGround = source.ejectPassengerToGround; target.ejectRayDistance = source.ejectRayDistance; target.handleExitTeleport = source.handleExitTeleport; target.setCharacterMotorPositionToCurrentPosition = source.setCharacterMotorPositionToCurrentPosition; target.passengerState = source.passengerState; } } public static VehicleSeat FindOrCreateEmptySeat(DrifterBagController bagController, ref ConcurrentDictionary seatDict, bool ignoreCapacity = false) { //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) VehicleSeat vehicleSeat = bagController.vehicleSeat; foreach (KeyValuePair item in seatDict) { if ((Object)(object)item.Value != (Object)null && !item.Value.hasPassenger) { return item.Value; } } VehicleSeat[] componentsInChildren = ((Component)bagController).GetComponentsInChildren(true); VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val in array) { if (!((Object)(object)val == (Object)(object)vehicleSeat) && !seatDict.Values.Contains(val) && !val.hasPassenger) { return val; } } int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(bagController); int count = seatDict.Count; if (!ignoreCapacity && count >= utilityMaxStock - 1) { return null; } if (!NetworkServer.active) { return null; } GameObject val2 = (GameObject)(((Object)(object)BagStateSync.AdditionalSeatPrefab != (Object)null) ? ((object)Object.Instantiate(BagStateSync.AdditionalSeatPrefab)) : ((object)new GameObject($"AdditionalSeat_Empty_{DateTime.Now.Ticks}"))); val2.SetActive(true); val2.transform.SetParent(((Component)bagController).transform); val2.transform.localPosition = Vector3.zero; val2.transform.localRotation = Quaternion.identity; VehicleSeat val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } NetworkServer.Spawn(val2); CopySeatProperties(vehicleSeat, val3); return val3; } public static VehicleSeat FindOrCreateEmptySeat(DrifterBagController bagController) { ConcurrentDictionary seatDict = BagPatches.GetState(bagController).AdditionalSeats; return FindOrCreateEmptySeat(bagController, ref seatDict); } internal static VehicleSeat? GetAdditionalSeatForObject(DrifterBagController bagController, GameObject? obj, ConcurrentDictionary seatDict) { if ((Object)(object)obj == (Object)null) { return null; } if (seatDict.TryGetValue(obj, out VehicleSeat value)) { return value; } return null; } internal static VehicleSeat? GetAdditionalSeatForObject(DrifterBagController bagController, GameObject? obj) { if ((Object)(object)obj == (Object)null) { return null; } ConcurrentDictionary additionalSeats = BagPatches.GetState(bagController).AdditionalSeats; if (additionalSeats != null) { return GetAdditionalSeatForObject(bagController, obj, additionalSeats); } return null; } } [HarmonyPatch] public static class AnimationPatches { [HarmonyPatch(typeof(EntityState), "PlayCrossfade", new Type[] { typeof(string), typeof(string), typeof(string), typeof(float), typeof(float) })] [HarmonyPrefix] public static bool PlayCrossfade_Prefix(EntityState __instance, string layerName, string animationStateName, string playbackRateParam, float duration, float crossfadeDuration) { bool flag = DrifterBossGrabPlugin.IsSwappingPassengers; if (!NetworkServer.active && Time.time - DrifterBossGrabPlugin.LastCycleClientTime < 0.3f) { flag = true; } if (flag && !PluginConfig.Instance.PlayAnimationOnCycle.Value && __instance is BaggedObject) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[AnimationPatches] Suppressing PlayCrossfade({layerName}, {animationStateName}, {playbackRateParam}, {duration}, {crossfadeDuration}) during cycle."); } return false; } return true; } [HarmonyPatch(typeof(EntityState), "PlayCrossfade", new Type[] { typeof(string), typeof(string), typeof(float) })] [HarmonyPrefix] public static bool PlayCrossfadeShort_Prefix(EntityState __instance, string layerName, string animationStateName, float crossfadeDuration) { bool flag = DrifterBossGrabPlugin.IsSwappingPassengers; if (!NetworkServer.active && Time.time - DrifterBossGrabPlugin.LastCycleClientTime < 0.3f) { flag = true; } if (flag && !PluginConfig.Instance.PlayAnimationOnCycle.Value && __instance is BaggedObject) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[AnimationPatches] Suppressing PlayCrossfade({layerName}, {animationStateName}, {crossfadeDuration}) during cycle."); } return false; } return true; } } public static class CyclingInputHandler { private static float _lastCycleTime; private static float _scrollAccumulator; private const float SCROLL_THRESHOLD = 0.1f; private static DrifterBagController? _cachedLocalController; public static void HandleInput() { if (!PluginConfig.Instance.BottomlessBagEnabled.Value) { return; } if (!CanProcessInput()) { _scrollAccumulator = 0f; return; } int num = 0; if (PluginConfig.Instance.EnableMouseWheelScrolling.Value) { float axis = Input.GetAxis("Mouse ScrollWheel"); if (axis != 0f) { if (_scrollAccumulator != 0f && Mathf.Sign(axis) != Mathf.Sign(_scrollAccumulator)) { _scrollAccumulator = 0f; } _scrollAccumulator += axis; } else { _scrollAccumulator = Mathf.MoveTowards(_scrollAccumulator, 0f, Time.deltaTime * 0.5f); } if (Mathf.Abs(_scrollAccumulator) >= 0.1f && Time.time >= _lastCycleTime + PluginConfig.Instance.CycleCooldown.Value) { bool flag = ((_scrollAccumulator > 0f) ? (PluginConfig.Instance.InverseMouseWheelScrolling.Value ? true : false) : ((!PluginConfig.Instance.InverseMouseWheelScrolling.Value) ? true : false)); num = (flag ? 1 : (-1)); _scrollAccumulator -= Mathf.Sign(_scrollAccumulator) * 0.1f; _lastCycleTime = Time.time; } } if (Time.time >= _lastCycleTime + PluginConfig.Instance.CycleCooldown.Value) { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if (((firstLocalUser != null) ? firstLocalUser.inputPlayer : null) != null) { if (firstLocalUser.inputPlayer.GetButtonDown(RewiredActions.ScrollBagUp.ActionId)) { num--; _lastCycleTime = Time.time; } if (firstLocalUser.inputPlayer.GetButtonDown(RewiredActions.ScrollBagDown.ActionId)) { num++; _lastCycleTime = Time.time; } } } if (num != 0) { CyclePassengers(num); } } private static bool CanProcessInput() { if (PauseScreenController.instancesList.Count > 0) { return false; } LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if (firstLocalUser != null && Object.op_Implicit((Object)(object)firstLocalUser.eventSystem) && firstLocalUser.eventSystem.isCursorVisible) { return false; } if ((Object)(object)Run.instance == (Object)null) { return false; } return true; } private static DrifterBagController? FindLocalPlayerBagController() { LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); if ((Object)(object)((firstLocalUser != null) ? firstLocalUser.cachedBody : null) == (Object)null) { return null; } CharacterBody cachedBody = firstLocalUser.cachedBody; DrifterBagController component = ((Component)cachedBody).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = ((Component)cachedBody).GetComponentInChildren(); if ((Object)(object)component != (Object)null) { return component; } return null; } private static void CyclePassengers(int amount) { if (amount == 0) { return; } if ((Object)(object)_cachedLocalController != (Object)null && _cachedLocalController.isAuthority) { PassengerCycler.CyclePassengers(_cachedLocalController, amount); return; } DrifterBagController val = FindLocalPlayerBagController(); if ((Object)(object)val != (Object)null && val.isAuthority) { _cachedLocalController = val; PassengerCycler.CyclePassengers(val, amount); } } } public static class PassengerCycler { private static readonly HashSet _seenInstanceIdsBuffer = new HashSet(); private static readonly List _validObjectsBuffer = new List(); private static readonly List _potentialRegrabObjectsBuffer = new List(); public static void CyclePassengers(DrifterBagController bagController, int amount) { if (PluginConfig.Instance.BottomlessBagEnabled.Value && !((Object)(object)bagController == (Object)null) && amount != 0 && BagCapacityCalculator.GetUtilityMaxStock(bagController) > 1) { if (!NetworkServer.active && ((NetworkBehaviour)bagController).hasAuthority) { CycleNetworkHandler.SendCycleRequest(bagController, amount); } else if (NetworkServer.active) { ServerCyclePassengers(bagController, amount); } } } public static void ServerCyclePassengers(DrifterBagController bagController, int amount) { if (!PluginConfig.Instance.BottomlessBagEnabled.Value || !NetworkServer.active || amount == 0) { return; } if ((Object)(object)bagController.vehicleSeat == (Object)null) { Log.Debug(" [BottomlessBag] ERROR: vehicleSeat is null!"); return; } List baggedObjects = BagPatches.GetState(bagController).BaggedObjects; if (baggedObjects == null || baggedObjects.Count == 0) { return; } HashSet seenInstanceIdsBuffer = _seenInstanceIdsBuffer; seenInstanceIdsBuffer.Clear(); List validObjectsBuffer = _validObjectsBuffer; validObjectsBuffer.Clear(); List potentialRegrabObjectsBuffer = _potentialRegrabObjectsBuffer; potentialRegrabObjectsBuffer.Clear(); foreach (GameObject registeredObject in SpecialObjectAttributesPatches.RegisteredObjects) { if (!((Object)(object)registeredObject != (Object)null) || !PluginConfig.IsGrabbable(registeredObject)) { continue; } bool flag = false; foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && ((Object)item).GetInstanceID() == ((Object)registeredObject).GetInstanceID()) { flag = true; break; } } if (flag && !ProjectileRecoveryPatches.IsInProjectileState(registeredObject)) { potentialRegrabObjectsBuffer.Add(registeredObject); } } foreach (GameObject item2 in baggedObjects) { if (!((Object)(object)item2 == (Object)null) && !ProjectileRecoveryPatches.IsInProjectileState(item2)) { int instanceID = ((Object)item2).GetInstanceID(); if (!seenInstanceIdsBuffer.Contains(instanceID)) { seenInstanceIdsBuffer.Add(instanceID); validObjectsBuffer.Add(item2); } } } foreach (GameObject item3 in potentialRegrabObjectsBuffer) { int instanceID2 = ((Object)item3).GetInstanceID(); if (!seenInstanceIdsBuffer.Contains(instanceID2)) { seenInstanceIdsBuffer.Add(instanceID2); validObjectsBuffer.Add(item3); } } if (validObjectsBuffer.Count != 0) { CycleToNextObject(bagController, validObjectsBuffer, amount); } } private static void CycleToNextObject(DrifterBagController bagController, List validObjects, int amount) { ConcurrentDictionary additionalSeats = BagPatches.GetState(bagController).AdditionalSeats; ConcurrentDictionary concurrentDictionary = new ConcurrentDictionary(additionalSeats); VehicleSeat vehicleSeat = bagController.vehicleSeat; GameObject val = BagPatches.GetMainSeatObject(bagController); if ((Object)(object)val == (Object)null && vehicleSeat.hasPassenger) { GameObject val2 = null; if (vehicleSeat.hasPassenger) { val2 = vehicleSeat.NetworkpassengerBodyObject; } if ((Object)(object)val2 != (Object)null) { bool flag = false; foreach (GameObject validObject in validObjects) { if ((Object)(object)validObject != (Object)null && ((Object)validObject).GetInstanceID() == ((Object)val2).GetInstanceID()) { flag = true; break; } } if (flag) { BagState state = BagPatches.GetState(bagController); List baggedObjects = state.BaggedObjects; int instanceID = ((Object)val2).GetInstanceID(); if (!state.ContainsInstanceId(instanceID)) { baggedObjects.Add(val2); state.AddInstanceId(instanceID); } BagPatches.SetMainSeatObject(bagController, val2); BagCarouselUpdater.UpdateCarousel(bagController); val = val2; } } } if ((Object)(object)val == (Object)null && vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; bool flag2 = false; foreach (GameObject validObject2 in validObjects) { if ((Object)(object)validObject2 != (Object)null && ((Object)validObject2).GetInstanceID() == ((Object)networkpassengerBodyObject).GetInstanceID()) { flag2 = true; break; } } if (flag2) { BagPatches.SetMainSeatObject(bagController, networkpassengerBodyObject); BagCarouselUpdater.UpdateCarousel(bagController); val = networkpassengerBodyObject; } } if ((Object)(object)val != (Object)null) { bool flag3 = false; bool flag4 = false; if (vehicleSeat.hasPassenger && vehicleSeat.hasPassenger && ((Object)vehicleSeat.NetworkpassengerBodyObject).GetInstanceID() == ((Object)val).GetInstanceID()) { flag3 = true; } if (concurrentDictionary.Count > 0) { foreach (KeyValuePair item in concurrentDictionary) { if ((Object)(object)item.Value != (Object)null && item.Value.hasPassenger && ((Object)item.Value.NetworkpassengerBodyObject).GetInstanceID() == ((Object)val).GetInstanceID()) { flag4 = true; break; } } } if (!flag3 && flag4) { BagPatches.SetMainSeatObject(bagController, null); val = null; } } if ((Object)(object)val != (Object)null) { bool flag5 = false; int instanceID2 = ((Object)val).GetInstanceID(); foreach (GameObject validObject3 in validObjects) { if ((Object)(object)validObject3 != (Object)null && ((Object)validObject3).GetInstanceID() == instanceID2) { flag5 = true; break; } } if (!flag5 && ProjectileRecoveryPatches.IsInProjectileState(val)) { flag5 = false; } if (!flag5) { BagPatches.SetMainSeatObject(bagController, null); BagCarouselUpdater.UpdateCarousel(bagController); val = null; } } GameObject val3 = null; int num = ((val != null) ? ((Object)val).GetInstanceID() : 0); foreach (GameObject validObject4 in validObjects) { if ((Object)(object)validObject4 != (Object)null && ((Object)validObject4).GetInstanceID() == num && num != 0) { val3 = validObject4; break; } } if ((Object)(object)val3 == (Object)null && (Object)(object)val != (Object)null) { if (vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject2 = vehicleSeat.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject2 != (Object)null && ((Object)networkpassengerBodyObject2).GetInstanceID() == num) { val3 = val; } } if ((Object)(object)val3 == (Object)null) { bool flag6 = false; int instanceID3 = ((Object)val).GetInstanceID(); foreach (GameObject validObject5 in validObjects) { if ((Object)(object)validObject5 != (Object)null && ((Object)validObject5).GetInstanceID() == instanceID3) { flag6 = true; val3 = validObject5; break; } } if (!flag6) { Log.Debug("[CycleToNextObject] mainPassenger " + ((Object)val).name + " not in validObjects and not in seat, returning early"); return; } Log.Debug("[CycleToNextObject] Trusting mainSeatDict for " + ((Object)val).name + " (client-grabbed object)"); } } bool flag7 = (Object)(object)val3 == (Object)null && validObjects.Count > 0; int num2 = validObjects.Count + 1; if ((Object)(object)val3 == (Object)null && validObjects.Count == 0) { return; } if ((Object)(object)val3 == (Object)null && !flag7 && vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject3 = vehicleSeat.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject3 != (Object)null) { bool flag8 = false; foreach (GameObject validObject6 in validObjects) { if ((Object)(object)validObject6 != (Object)null && ((Object)validObject6).GetInstanceID() == ((Object)networkpassengerBodyObject3).GetInstanceID()) { flag8 = true; break; } } if (flag8) { BagState state2 = BagPatches.GetState(bagController); List baggedObjects2 = state2.BaggedObjects; int instanceID4 = ((Object)networkpassengerBodyObject3).GetInstanceID(); if (!state2.ContainsInstanceId(instanceID4)) { baggedObjects2.Add(networkpassengerBodyObject3); state2.AddInstanceId(instanceID4); } BagPatches.SetMainSeatObject(bagController, networkpassengerBodyObject3); BagCarouselUpdater.UpdateCarousel(bagController); val3 = networkpassengerBodyObject3; } } } int num3 = -1; bool flag9 = false; if (flag7) { num3 = validObjects.Count; flag9 = true; } else { for (int i = 0; i < validObjects.Count; i++) { if ((Object)(object)validObjects[i] != (Object)null && (Object)(object)val3 != (Object)null && ((Object)validObjects[i]).GetInstanceID() == ((Object)val3).GetInstanceID()) { num3 = i; break; } } } if (num3 < 0 && !flag9) { num3 = validObjects.Count; flag9 = true; } int num4 = (num3 + amount) % num2; if (num4 < 0) { num4 += num2; } if (PluginConfig.Instance.EnableDebugLogs.Value) { GameObject val4 = ((num4 >= 0 && num4 < validObjects.Count) ? validObjects[num4] : null); Log.Debug(string.Format("[PassengerCycler] User scrolled to index {0}. Target={1}", num4, ((Object)(object)val4 != (Object)null) ? ((Object)val4).name : "null")); } bool flag10 = num4 == validObjects.Count; int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(bagController); bool flag11 = validObjects.Count >= utilityMaxStock; int num5 = Math.Sign(amount); Log.Debug($"[CycleToNextObject] Index Calc: Current={num3} (IsNull={flag9}), Amount={amount}, Next={num4} (IsNull={flag10}), TotalPos={num2}, IsBagFull={flag11}"); if (flag11 && flag10) { Log.Debug("[CycleToNextObject] Bag is full, skipping null state and wrapping around"); num4 = ((num5 <= 0) ? (validObjects.Count - 1) : 0); flag10 = false; } BagPatches.GetState(bagController).IntendedSelectedIndex = num4; if (!SeatValidator.ValidateSeatConfiguration(bagController, validObjects, val3, flag7, concurrentDictionary)) { Log.Debug("[CycleToNextObject] Invalid Seat Conf, Aborting."); return; } DrifterBossGrabPlugin._isSwappingPassengers = true; try { if (flag10) { if (!flag9 && (Object)(object)val3 != (Object)null) { SeatTransitionHandler.HandleNullStateTransition(bagController, vehicleSeat, val3, concurrentDictionary, validObjects.Count); } else { flag10 = false; num4 = 0; } } else if (!flag10 && flag9) { GameObject targetObject = validObjects[num4]; SeatTransitionHandler.HandleNullToObjectTransition(bagController, vehicleSeat, targetObject, concurrentDictionary); } else { GameObject currentObject = validObjects[num3]; GameObject targetObject2 = validObjects[num4]; SeatTransitionHandler.HandleObjectSwap(bagController, vehicleSeat, currentObject, targetObject2, concurrentDictionary, num5); } BagPatches.GetState(bagController).AdditionalSeats = concurrentDictionary; BagCarouselUpdater.UpdateCarousel(bagController, num5); BagCarouselUpdater.UpdateNetworkBagState(bagController, num5); } finally { DrifterBossGrabPlugin._isSwappingPassengers = false; } if (!flag10) { GameObject val5 = ((num4 < validObjects.Count) ? validObjects[num4] : null); if ((Object)(object)val5 != (Object)null) { BaggedObjectPatches.RefreshUIOverlayForMainSeat(bagController, val5); } } BagPassengerManager.ForceRecalculateMass(bagController); } } public static class SeatTransitionHandler { internal static void HandleNullStateTransition(DrifterBagController bagController, VehicleSeat vehicleSeat, GameObject actualMainPassenger, ConcurrentDictionary localSeatDict, int validObjectCount) { if (!SeatValidator.HasSpaceForNullStateTransition(bagController, validObjectCount, localSeatDict)) { Log.Debug("[HandleNullStateTransition] No space for null transition, aborting."); return; } if (!SeatValidator.ValidateNullStateTransition(bagController, actualMainPassenger, localSeatDict)) { Log.Debug("[HandleNullStateTransition] ValidateNullStateTransition failed, aborting."); return; } VehicleSeat val = AdditionalSeatManager.FindOrCreateEmptySeat(bagController, ref localSeatDict, ignoreCapacity: true); if ((Object)(object)actualMainPassenger != (Object)null) { BaggedObject val2 = BaggedObjectPatches.FindOrCreateBaggedObjectState(bagController, actualMainPassenger); if (val2 != null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(bagController, actualMainPassenger) ?? new BaggedObjectStateData(); if ((Object)(object)baggedObjectStateData.targetObject == (Object)null) { baggedObjectStateData.CalculateFromObject(actualMainPassenger, bagController); } baggedObjectStateData.CaptureBreakoutStateFromBaggedObject(val2); BaggedObjectPatches.SaveObjectState(bagController, actualMainPassenger, baggedObjectStateData); } } if ((Object)(object)actualMainPassenger != (Object)null) { BaggedObjectStatePatches.BaggedObject_OnExit.MarkPreserveOverridesDuringCycling(actualMainPassenger); } vehicleSeat.EjectPassenger(actualMainPassenger); if ((Object)(object)actualMainPassenger != (Object)null) { BaggedObjectPatches.RemoveUIOverlay(actualMainPassenger, bagController); } BagPatches.SetMainSeatObject(bagController, null); if ((Object)(object)val != (Object)null && (Object)(object)actualMainPassenger != (Object)null) { localSeatDict[actualMainPassenger] = val; BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; val.AssignPassenger(actualMainPassenger); if (NetworkServer.active && AdditionalSeatBreakoutTimer.CanBreakout(actualMainPassenger) && !Object.op_Implicit((Object)(object)actualMainPassenger.GetComponent())) { AdditionalSeatBreakoutTimer additionalSeatBreakoutTimer = actualMainPassenger.AddComponent(); additionalSeatBreakoutTimer.controller = bagController; float num = bagController.CalculateBaggedObjectMass(actualMainPassenger); float num2 = 10f; float value = PluginConfig.Instance.BreakoutTimeMultiplier.Value; float num3 = Mathf.Max(num2 - 0.005f * num, 1f); CharacterBody component = actualMainPassenger.GetComponent(); if (Object.op_Implicit((Object)(object)component) && component.isElite) { num3 *= 0.8f; } additionalSeatBreakoutTimer.breakoutTime = num3 * value; BaggedObjectStateData baggedObjectStateData2 = BaggedObjectPatches.LoadObjectState(bagController, actualMainPassenger); if (baggedObjectStateData2 != null) { if (baggedObjectStateData2.breakoutTime > 0f) { additionalSeatBreakoutTimer.breakoutTime = baggedObjectStateData2.breakoutTime; } additionalSeatBreakoutTimer.SetElapsedBreakoutTime(baggedObjectStateData2.elapsedBreakoutTime); additionalSeatBreakoutTimer.breakoutAttempts = baggedObjectStateData2.breakoutAttempts; } } } BaggedObjectPatches.RemoveUIOverlayForNullState(bagController); } internal static void HandleNullToObjectTransition(DrifterBagController bagController, VehicleSeat vehicleSeat, GameObject targetObject, ConcurrentDictionary localSeatDict) { if ((Object)(object)targetObject == (Object)null) { return; } VehicleSeat additionalSeatForObject = AdditionalSeatManager.GetAdditionalSeatForObject(bagController, targetObject, localSeatDict); if ((Object)(object)additionalSeatForObject != (Object)null) { AdditionalSeatBreakoutTimer component = targetObject.GetComponent(); if ((Object)(object)component != (Object)null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(bagController, targetObject) ?? new BaggedObjectStateData(); if ((Object)(object)baggedObjectStateData.targetObject == (Object)null) { baggedObjectStateData.CalculateFromObject(targetObject, bagController); } baggedObjectStateData.CaptureFromAdditionalTimer(component); BaggedObjectPatches.SaveObjectState(bagController, targetObject, baggedObjectStateData); } additionalSeatForObject.EjectPassenger(targetObject); localSeatDict.TryRemove(targetObject, out VehicleSeat _); } int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(bagController); int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(bagController); if (currentBaggedCount >= utilityMaxStock && NetworkServer.active && (Object)(object)additionalSeatForObject == (Object)null) { Log.Debug("[HandleNullToObjectTransition] Bag is full, keeping " + ((Object)targetObject).name + " in additional seat instead of main seat"); VehicleSeat val = AdditionalSeatManager.FindOrCreateEmptySeat(bagController, ref localSeatDict, ignoreCapacity: true); if ((Object)(object)val != (Object)null) { localSeatDict[targetObject] = val; BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; val.AssignPassenger(targetObject); return; } } Log.Debug("[HandleNullToObjectTransition] Saving state before AssignPassenger (null -> " + ((Object)targetObject).name + ")"); BagPatches.SetMainSeatObject(bagController, targetObject); BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; bool isSwappingPassengers = DrifterBossGrabPlugin._isSwappingPassengers; DrifterBossGrabPlugin._isSwappingPassengers = true; try { bagController.AssignPassenger(targetObject); } finally { DrifterBossGrabPlugin._isSwappingPassengers = isSwappingPassengers; } } internal static void HandleObjectSwap(DrifterBagController bagController, VehicleSeat vehicleSeat, GameObject currentObject, GameObject targetObject, ConcurrentDictionary localSeatDict, int direction) { if ((Object)(object)targetObject == (Object)null || !SeatValidator.ValidateSeatStateForSwap(bagController, currentObject, targetObject, localSeatDict)) { return; } bool flag = vehicleSeat.hasPassenger && (Object)(object)vehicleSeat.NetworkpassengerBodyObject != (Object)null && ((Object)vehicleSeat.NetworkpassengerBodyObject).GetInstanceID() == ((Object)currentObject).GetInstanceID(); VehicleSeat additionalSeatForObject = AdditionalSeatManager.GetAdditionalSeatForObject(bagController, targetObject); VehicleSeat value; if (flag) { if ((Object)(object)currentObject != (Object)null) { BaggedObject val = BaggedObjectPatches.FindOrCreateBaggedObjectState(bagController, currentObject); if (val != null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(bagController, currentObject) ?? new BaggedObjectStateData(); if ((Object)(object)baggedObjectStateData.targetObject == (Object)null) { baggedObjectStateData.CalculateFromObject(currentObject, bagController); } baggedObjectStateData.CaptureBreakoutStateFromBaggedObject(val); BaggedObjectPatches.SaveObjectState(bagController, currentObject, baggedObjectStateData); } } if ((Object)(object)currentObject != (Object)null) { BaggedObjectStatePatches.BaggedObject_OnExit.MarkPreserveOverridesDuringCycling(currentObject); } vehicleSeat.EjectPassenger(currentObject); if ((Object)(object)currentObject != (Object)null) { BaggedObjectPatches.RemoveUIOverlay(currentObject, bagController); } if ((Object)(object)additionalSeatForObject != (Object)null) { AdditionalSeatBreakoutTimer component = targetObject.GetComponent(); if ((Object)(object)component != (Object)null) { BaggedObjectStateData baggedObjectStateData2 = BaggedObjectPatches.LoadObjectState(bagController, targetObject) ?? new BaggedObjectStateData(); if ((Object)(object)baggedObjectStateData2.targetObject == (Object)null) { baggedObjectStateData2.CalculateFromObject(targetObject, bagController); } baggedObjectStateData2.CaptureFromAdditionalTimer(component); BaggedObjectPatches.SaveObjectState(bagController, targetObject, baggedObjectStateData2); } additionalSeatForObject.EjectPassenger(targetObject); localSeatDict.TryRemove(targetObject, out value); if ((Object)(object)currentObject != (Object)null) { BaggedObjectPatches.RemoveUIOverlay(currentObject, bagController); localSeatDict[currentObject] = additionalSeatForObject; } BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; additionalSeatForObject.AssignPassenger(currentObject); if ((Object)(object)currentObject != (Object)null && NetworkServer.active && AdditionalSeatBreakoutTimer.CanBreakout(currentObject) && !Object.op_Implicit((Object)(object)currentObject.GetComponent())) { AdditionalSeatBreakoutTimer additionalSeatBreakoutTimer = currentObject.AddComponent(); additionalSeatBreakoutTimer.controller = bagController; float num = bagController.CalculateBaggedObjectMass(currentObject); float num2 = 10f; float value2 = PluginConfig.Instance.BreakoutTimeMultiplier.Value; float num3 = Mathf.Max(num2 - 0.005f * num, 1f); CharacterBody component2 = currentObject.GetComponent(); if (Object.op_Implicit((Object)(object)component2) && component2.isElite) { num3 *= 0.8f; } additionalSeatBreakoutTimer.breakoutTime = num3 * value2; BaggedObjectStateData baggedObjectStateData3 = BaggedObjectPatches.LoadObjectState(bagController, currentObject); if (baggedObjectStateData3 != null) { if (baggedObjectStateData3.breakoutTime > 0f) { additionalSeatBreakoutTimer.breakoutTime = baggedObjectStateData3.breakoutTime; } additionalSeatBreakoutTimer.SetElapsedBreakoutTime(baggedObjectStateData3.elapsedBreakoutTime); additionalSeatBreakoutTimer.breakoutAttempts = baggedObjectStateData3.breakoutAttempts; } } } if ((Object)(object)additionalSeatForObject == (Object)null) { VehicleSeat val2 = AdditionalSeatManager.FindOrCreateEmptySeat(bagController, ref localSeatDict, ignoreCapacity: true); if ((Object)(object)val2 != (Object)null && (Object)(object)currentObject != (Object)null) { localSeatDict[currentObject] = val2; BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; val2.AssignPassenger(currentObject); } } BagPatches.SetMainSeatObject(bagController, targetObject); BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; vehicleSeat.AssignPassenger(targetObject); if ((Object)(object)targetObject != (Object)null) { BaggedObjectStateData baggedObjectStateData4 = BaggedObjectPatches.LoadObjectState(bagController, targetObject); if (baggedObjectStateData4 != null) { BaggedObject val3 = BaggedObjectPatches.FindOrCreateBaggedObjectState(bagController, targetObject); if (val3 != null) { baggedObjectStateData4.ApplyToBaggedObject(val3); } } } BaggedObjectPatches.RefreshUIOverlayForMainSeat(bagController, targetObject); BaggedObjectPatches.SynchronizeBaggedObjectState(bagController, targetObject); BagCarouselUpdater.UpdateCarousel(bagController, direction); return; } if ((Object)(object)additionalSeatForObject != (Object)null) { AdditionalSeatBreakoutTimer component3 = targetObject.GetComponent(); if ((Object)(object)component3 != (Object)null) { BaggedObjectStateData baggedObjectStateData5 = BaggedObjectPatches.LoadObjectState(bagController, targetObject) ?? new BaggedObjectStateData(); if ((Object)(object)baggedObjectStateData5.targetObject == (Object)null) { baggedObjectStateData5.CalculateFromObject(targetObject, bagController); } baggedObjectStateData5.CaptureFromAdditionalTimer(component3); BaggedObjectPatches.SaveObjectState(bagController, targetObject, baggedObjectStateData5); } additionalSeatForObject.EjectPassenger(targetObject); localSeatDict.TryRemove(targetObject, out value); if ((Object)(object)currentObject != (Object)null) { localSeatDict[currentObject] = additionalSeatForObject; BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; additionalSeatForObject.AssignPassenger(currentObject); if (NetworkServer.active && AdditionalSeatBreakoutTimer.CanBreakout(currentObject) && !Object.op_Implicit((Object)(object)currentObject.GetComponent())) { AdditionalSeatBreakoutTimer additionalSeatBreakoutTimer2 = currentObject.AddComponent(); additionalSeatBreakoutTimer2.controller = bagController; float num4 = bagController.CalculateBaggedObjectMass(currentObject); float num5 = 10f; float value3 = PluginConfig.Instance.BreakoutTimeMultiplier.Value; float num6 = Mathf.Max(num5 - 0.005f * num4, 1f); CharacterBody component4 = currentObject.GetComponent(); if (Object.op_Implicit((Object)(object)component4) && component4.isElite) { num6 *= 0.8f; } additionalSeatBreakoutTimer2.breakoutTime = num6 * value3; BaggedObjectStateData baggedObjectStateData6 = BaggedObjectPatches.LoadObjectState(bagController, currentObject); if (baggedObjectStateData6 != null) { if (baggedObjectStateData6.breakoutTime > 0f) { additionalSeatBreakoutTimer2.breakoutTime = baggedObjectStateData6.breakoutTime; } additionalSeatBreakoutTimer2.SetElapsedBreakoutTime(baggedObjectStateData6.elapsedBreakoutTime); additionalSeatBreakoutTimer2.breakoutAttempts = baggedObjectStateData6.breakoutAttempts; } } } } BagPatches.SetMainSeatObject(bagController, targetObject); if ((Object)(object)targetObject != (Object)null) { localSeatDict.TryRemove(targetObject, out value); BagPatches.GetState(bagController).AdditionalSeats = localSeatDict; vehicleSeat.AssignPassenger(targetObject); BaggedObjectPatches.RefreshUIOverlayForMainSeat(bagController, targetObject); BaggedObjectPatches.SynchronizeBaggedObjectState(bagController, targetObject); } BagCarouselUpdater.UpdateCarousel(bagController, direction); } } public static class SeatValidator { internal static bool ValidateSeatConfiguration(DrifterBagController bagController, List validObjects, GameObject? actualMainPassenger, bool isInNullState, ConcurrentDictionary seatDict) { if (!isInNullState && (Object)(object)actualMainPassenger == (Object)null) { return false; } if (isInNullState && validObjects.Count == 0) { return false; } if (seatDict.Count > 0) { foreach (KeyValuePair item in seatDict) { GameObject key = item.Key; VehicleSeat value = item.Value; if ((Object)(object)value == (Object)null) { return false; } if (value.hasPassenger) { GameObject networkpassengerBodyObject = value.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject == (Object)null || ((Object)networkpassengerBodyObject).GetInstanceID() != ((Object)key).GetInstanceID()) { return false; } } else if (!value.hasPassenger) { return false; } } } return true; } internal static bool ValidateSeatStateForSwap(DrifterBagController bagController, GameObject? currentObject, GameObject? targetObject, ConcurrentDictionary seatDict) { if ((Object)(object)targetObject == (Object)null) { return false; } VehicleSeat vehicleSeat = bagController.vehicleSeat; if ((Object)(object)vehicleSeat == (Object)null) { return false; } bool flag = false; if (vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; flag = (Object)(object)networkpassengerBodyObject != (Object)null && ((Object)networkpassengerBodyObject).GetInstanceID() == ((Object)currentObject).GetInstanceID(); } if (!flag && (Object)(object)currentObject != (Object)null) { GameObject mainSeatObject = BagPatches.GetMainSeatObject(bagController); if ((Object)(object)mainSeatObject != (Object)null && ((Object)mainSeatObject).GetInstanceID() == ((Object)currentObject).GetInstanceID()) { flag = true; } } if (!flag) { return false; } VehicleSeat additionalSeatForObject = AdditionalSeatManager.GetAdditionalSeatForObject(bagController, targetObject, seatDict); if ((Object)(object)additionalSeatForObject != (Object)null) { if (additionalSeatForObject.hasPassenger) { GameObject networkpassengerBodyObject2 = additionalSeatForObject.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject2 != (Object)null && ((Object)networkpassengerBodyObject2).GetInstanceID() != ((Object)targetObject).GetInstanceID()) { } } if (seatDict.Count > 0) { foreach (KeyValuePair item in seatDict) { VehicleSeat value = item.Value; if ((Object)(object)value != (Object)null && value.hasPassenger) { GameObject networkpassengerBodyObject3 = value.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject3 != (Object)null && (Object)(object)currentObject != (Object)null && ((Object)networkpassengerBodyObject3).GetInstanceID() == ((Object)currentObject).GetInstanceID() && (Object)(object)value != (Object)(object)vehicleSeat) { return false; } if ((Object)(object)networkpassengerBodyObject3 != (Object)null && ((Object)networkpassengerBodyObject3).GetInstanceID() == ((Object)targetObject).GetInstanceID() && (Object)(object)value == (Object)(object)vehicleSeat) { return false; } } } } return true; } return true; } internal static bool ValidateNullStateTransition(DrifterBagController bagController, GameObject? currentObject, ConcurrentDictionary seatDict) { if ((Object)(object)currentObject == (Object)null) { return false; } VehicleSeat vehicleSeat = bagController.vehicleSeat; if ((Object)(object)vehicleSeat == (Object)null) { return false; } bool flag = false; if (vehicleSeat.hasPassenger) { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; flag = (Object)(object)networkpassengerBodyObject != (Object)null && ((Object)networkpassengerBodyObject).GetInstanceID() == ((Object)currentObject).GetInstanceID(); } if (!flag) { return false; } VehicleSeat val = AdditionalSeatManager.FindOrCreateEmptySeat(bagController, ref seatDict); if ((Object)(object)val == (Object)null) { return false; } if (seatDict.Count > 0) { foreach (KeyValuePair item in seatDict) { VehicleSeat value = item.Value; if ((Object)(object)value != (Object)null && value.hasPassenger) { GameObject networkpassengerBodyObject2 = value.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject2 != (Object)null && (Object)(object)currentObject != (Object)null && ((Object)networkpassengerBodyObject2).GetInstanceID() == ((Object)currentObject).GetInstanceID() && (Object)(object)value != (Object)(object)vehicleSeat) { return false; } } } } return true; } internal static bool HasSpaceForNullStateTransition(DrifterBagController bagController, int currentObjectCount, ConcurrentDictionary seatDict) { int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(bagController); if (currentObjectCount >= utilityMaxStock) { return false; } return true; } } public static class MiscPatches { [HarmonyPatch(typeof(HackingMainState), "ScanForTarget")] public class HackingMainState_ScanForTarget_Patch { [HarmonyPrefix] public static void Prefix(HackingMainState __instance) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (_sphereSearchField != null) { SphereSearch val = (SphereSearch)_sphereSearchField.GetValue(__instance); if (val != null && (Object)(object)((EntityState)__instance).transform != (Object)null) { val.origin = ((EntityState)__instance).transform.position; } } } } [HarmonyPatch(typeof(ThrownObjectProjectileController), "EjectPassengerToFinalPosition")] public class ThrownObjectProjectileController_EjectPassengerToFinalPosition_Patch { [HarmonyPrefix] public static bool Prefix(ThrownObjectProjectileController __instance) { Log.Debug(string.Format("[EjectPassenger] CALLED for {0} | Passenger: {1} | Server: {2}", ((Object)__instance).name, ((Object)(object)__instance.Networkpassenger != (Object)null) ? ((Object)__instance.Networkpassenger).name : "null", NetworkServer.active)); return true; } } [HarmonyPatch(typeof(ThrownObjectProjectileController), "CheckForDeadPassenger")] public class ThrownObjectProjectileController_CheckForDeadPassenger_Patch { [HarmonyPrefix] public static bool Prefix(ThrownObjectProjectileController __instance) { try { GameObject networkpassenger = __instance.Networkpassenger; if ((Object)(object)networkpassenger == (Object)null) { return false; } } catch (Exception ex) { Log.Error("[PassengerPatch] Failed to check passenger: " + ex.Message); return false; } return true; } } private static readonly FieldInfo _sphereSearchField = ReflectionCache.HackingMainState.SphereSearch; } public static class BaggedObjectPatches { [HarmonyPatch(typeof(BaggedObject), "TryOverrideUtility")] public class BaggedObject_TryOverrideUtility { [HarmonyPrefix] public static bool Prefix(BaggedObject __instance, GenericSkill skill) { //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown if (__instance == null || !Object.op_Implicit((Object)(object)((EntityState)__instance).outer)) { return true; } DrifterBagController component = ((Component)((EntityState)__instance).outer).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } GameObject targetObject = __instance.targetObject; if ((Object)(object)targetObject == (Object)null) { return false; } bool flag = IsInMainSeat(component, targetObject); GameObject mainSeatObject = BagPatches.GetMainSeatObject(component); bool flag2 = (Object)(object)mainSeatObject != (Object)null && mainSeatObject == targetObject; bool flag3 = flag || flag2; Log.Debug("[BaggedObject_TryOverrideUtility.Prefix] targetObject=" + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name) + ", " + $"isMainSeatOccupant={flag}, " + $"isBeingCycledToMain={flag2}, " + "trackedMain=" + ((!Object.op_Implicit((Object)(object)mainSeatObject)) ? "null" : ((Object)mainSeatObject).name) + ", " + $"shouldAllowOverride={flag3}."); if (flag3) { Log.Debug("[BaggedObject_TryOverrideUtility.Prefix] ALLOWING override for " + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name)); return true; } Log.Debug("[BaggedObject_TryOverrideUtility.Prefix] SKIPPING override for " + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name) + " (not in main seat, not being cycled)"); if ((Object)(object)mainSeatObject != (Object)null && (Object)(object)skill != (Object)null && !skill.HasSkillOverrideOfPriority((SkillOverridePriority)4)) { SkillDef val = (SkillDef)(ReflectionCache.BaggedObject.UtilityOverride?.GetValue(__instance)); if ((Object)(object)val != (Object)null) { Log.Debug("[BaggedObject_TryOverrideUtility.Prefix] RE-APPLYING utility override for main seat object " + ((Object)mainSeatObject).name + " (override was cleaned up by vanilla OnExit)"); ReflectionCache.BaggedObject.OverriddenUtility?.SetValue(__instance, skill); skill.SetSkillOverride((object)__instance, val, (SkillOverridePriority)4); SkillLocator component2 = ((Component)((EntityState)__instance).outer).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.utility != (Object)null) { skill.stock = component2.utility.stock; } } } return false; } [HarmonyPostfix] public static void Postfix(BaggedObject __instance, GenericSkill skill) { //IL_014a: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.Instance.EnableDebugLogs.Value || __instance == null) { return; } try { GameObject val = __instance?.targetObject; object obj = ReflectionCache.BaggedObject.IsBody?.GetValue(__instance); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0; object obj2 = ReflectionCache.BaggedObject.OverriddenUtility?.GetValue(__instance); object obj3 = ReflectionCache.BaggedObject.UtilityOverride?.GetValue(__instance); object obj4 = ReflectionCache.BaggedObject.VehiclePassengerAttributes?.GetValue(__instance); object obj5 = ReflectionCache.BaggedObject.DrifterBagController?.GetValue(__instance); Log.Debug("[BaggedObject_TryOverrideUtility.Postfix] targetObject=" + ((!Object.op_Implicit((Object)(object)val)) ? "null" : ((Object)val).name) + ", " + $"isBody={flag2}, " + "vehiclePassengerAttributes=" + ((obj4 != null) ? "SET" : "NULL") + ", drifterBagController=" + ((obj5 != null) ? "SET" : "NULL") + ", overriddenUtility=" + ((obj2 != null) ? "SET" : "NULL") + ", utilityOverride=" + ((obj3 != null) ? ((Object)(ScriptableObject)obj3).name : "NULL") + ", skill=" + (((Object)(object)skill != (Object)null) ? skill.skillName : "null")); } catch (Exception ex) { Log.Warning("[BaggedObject_TryOverrideUtility.Postfix] Diagnostic error: " + ex.Message); } } } [HarmonyPatch(typeof(BaggedObject), "TryOverridePrimary")] public class BaggedObject_TryOverridePrimary { [HarmonyPrefix] public static bool Prefix(BaggedObject __instance, GenericSkill skill) { //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Expected O, but got Unknown if (__instance == null || !Object.op_Implicit((Object)(object)((EntityState)__instance).outer)) { return true; } DrifterBagController component = ((Component)((EntityState)__instance).outer).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } GameObject targetObject = __instance.targetObject; if ((Object)(object)targetObject == (Object)null) { return false; } bool flag = IsInMainSeat(component, targetObject); GameObject mainSeatObject = BagPatches.GetMainSeatObject(component); bool flag2 = (Object)(object)mainSeatObject != (Object)null && mainSeatObject == targetObject; bool flag3 = flag || flag2; Log.Debug("[BaggedObject_TryOverridePrimary.Prefix] targetObject=" + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name) + ", " + $"isMainSeatOccupant={flag}, " + $"isBeingCycledToMain={flag2}, " + "trackedMain=" + ((!Object.op_Implicit((Object)(object)mainSeatObject)) ? "null" : ((Object)mainSeatObject).name) + ", " + $"shouldAllowOverride={flag3}."); if (flag3) { Log.Debug("[BaggedObject_TryOverridePrimary.Prefix] ALLOWING override for " + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name)); return true; } Log.Debug("[BaggedObject_TryOverridePrimary.Prefix] SKIPPING override for " + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name) + " (not in main seat, not being cycled)"); if ((Object)(object)mainSeatObject != (Object)null && (Object)(object)skill != (Object)null && !skill.HasSkillOverrideOfPriority((SkillOverridePriority)4)) { SkillDef val = (SkillDef)(ReflectionCache.BaggedObject.PrimaryOverride?.GetValue(__instance)); if ((Object)(object)val != (Object)null) { Log.Debug("[BaggedObject_TryOverridePrimary.Prefix] RE-APPLYING primary override for main seat object " + ((Object)mainSeatObject).name + " (override was cleaned up by vanilla OnExit)"); ReflectionCache.BaggedObject.OverriddenPrimary?.SetValue(__instance, skill); skill.SetSkillOverride((object)__instance, val, (SkillOverridePriority)4); SkillLocator component2 = ((Component)((EntityState)__instance).outer).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.primary != (Object)null) { skill.stock = component2.primary.stock; } } } return false; } [HarmonyPostfix] public static void Postfix(BaggedObject __instance, GenericSkill skill) { //IL_0119: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.Instance.EnableDebugLogs.Value || __instance == null) { return; } try { GameObject val = __instance?.targetObject; object obj = ReflectionCache.BaggedObject.IsBody?.GetValue(__instance); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0; object obj2 = ReflectionCache.BaggedObject.OverriddenPrimary?.GetValue(__instance); object obj3 = ReflectionCache.BaggedObject.PrimaryOverride?.GetValue(__instance); object obj4 = ReflectionCache.BaggedObject.VehiclePassengerAttributes?.GetValue(__instance); Log.Debug("[BaggedObject_TryOverridePrimary.Postfix] targetObject=" + ((!Object.op_Implicit((Object)(object)val)) ? "null" : ((Object)val).name) + ", " + $"isBody={flag2}, " + "vehiclePassengerAttributes=" + ((obj4 != null) ? "SET" : "NULL") + ", overriddenPrimary=" + ((obj2 != null) ? "SET" : "NULL") + ", primaryOverride=" + ((obj3 != null) ? ((Object)(ScriptableObject)obj3).name : "NULL") + ", skill=" + (((Object)(object)skill != (Object)null) ? skill.skillName : "null")); } catch (Exception ex) { Log.Warning("[BaggedObject_TryOverridePrimary.Postfix] Diagnostic error: " + ex.Message); } } } private static readonly MethodInfo _onSyncBaggedObjectMethod = ReflectionCache.DrifterBagController.OnSyncBaggedObject; private static readonly MethodInfo _tryOverrideUtilityMethod = ReflectionCache.BaggedObject.TryOverrideUtility; private static readonly MethodInfo _tryOverridePrimaryMethod = ReflectionCache.BaggedObject.TryOverridePrimary; private static readonly FieldInfo _bagScale01Field = ReflectionCache.BaggedObject.BagScale01; private static readonly MethodInfo _setScaleMethod = ReflectionCache.BaggedObject.SetScale; public static BaggedObject? FindExistingBaggedObjectState(DrifterBagController bagController, GameObject? targetObject) { if ((Object)(object)bagController == (Object)null || (Object)(object)targetObject == (Object)null) { return null; } EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)bagController).gameObject, "Bag"); if ((Object)(object)val != (Object)null) { EntityState state = val.state; BaggedObject val2 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val2 != null) { return val2; } } return null; } public static void SynchronizeBaggedObjectState(DrifterBagController bagController, GameObject? targetObject) { if ((Object)(object)bagController == (Object)null) { return; } Log.Debug(string.Format("[SynchronizeBaggedObjectState] Called with targetObject={0}, EnableBalance={1}, NetworkServer.active={2}, hasAuthority={3}", (!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name, PluginConfig.Instance.EnableBalance.Value, NetworkServer.active, ((NetworkBehaviour)bagController).hasAuthority)); BaggedObject val = null; if ((Object)(object)targetObject != (Object)null) { val = FindOrCreateBaggedObjectState(bagController, targetObject); if (val == null) { Log.Debug("[SynchronizeBaggedObjectState] FindOrCreateBaggedObjectState returned null for " + ((Object)targetObject).name); } if (val != null) { val.targetObject = targetObject; UpdateTargetFields(val); Log.Debug("[SynchronizeBaggedObjectState] Set targetObject and called UpdateTargetFields for " + ((Object)targetObject).name); } } if (NetworkServer.active) { if ((Object)(object)bagController.NetworkbaggedObject != (Object)(object)targetObject) { bagController.NetworkbaggedObject = targetObject; } if (!DrifterBossGrabPlugin.IsSwappingPassengers) { GameObject baggedObject = bagController.baggedObject; if ((Object)(object)baggedObject != (Object)(object)targetObject) { Log.Debug("[SynchronizeBaggedObjectState] Calling OnSyncBaggedObject for " + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name)); _onSyncBaggedObjectMethod?.Invoke(bagController, new object[1] { targetObject }); } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SynchronizeBaggedObjectState] SKIPPED OnSyncBaggedObject - during passenger swap"); } } else if (((NetworkBehaviour)bagController).hasAuthority) { if (!DrifterBossGrabPlugin.IsSwappingPassengers) { GameObject baggedObject2 = bagController.baggedObject; if ((Object)(object)baggedObject2 != (Object)(object)targetObject) { Log.Debug("[SynchronizeBaggedObjectState] Calling OnSyncBaggedObject for " + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name)); _onSyncBaggedObjectMethod?.Invoke(bagController, new object[1] { targetObject }); } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SynchronizeBaggedObjectState] SKIPPED OnSyncBaggedObject - during passenger swap"); } } if (val != null && (Object)(object)targetObject != (Object)null) { bool flag = BagPatches.GetState(bagController).BaggedObjects?.Contains(targetObject) ?? false; bool flag2 = ProjectileRecoveryPatches.IsInProjectileState(targetObject); Log.Debug($"[SynchronizeBaggedObjectState] Override check for {((Object)targetObject).name}: isInBag={flag}, isProjectile={flag2}"); if (flag && !flag2) { SkillLocator component = ((Component)((EntityState)val).outer).GetComponent(); if ((Object)(object)component != (Object)null) { Log.Debug("[SynchronizeBaggedObjectState] Applying skill overrides for " + ((Object)targetObject).name); if ((Object)(object)component.utility != (Object)null) { _tryOverrideUtilityMethod?.Invoke(val, new object[1] { component.utility }); } if ((Object)(object)component.primary != (Object)null) { _tryOverridePrimaryMethod?.Invoke(val, new object[1] { component.primary }); } } else { Log.Debug("[SynchronizeBaggedObjectState] SkillLocator is null for " + ((Object)targetObject).name); } } } if (PluginConfig.Instance.EnableBalance.Value && (Object)(object)targetObject != (Object)null) { BaggedObjectStateData baggedObjectStateData = StateCalculator.CalculateState(bagController, targetObject, PluginConfig.Instance.StateCalculationMode.Value); if (baggedObjectStateData != null && val != null) { baggedObjectStateData.ApplyToBaggedObject(val); } } } public static void UpdateTargetFields(BaggedObject? instance) { if (instance != null && !((Object)(object)instance.targetObject == (Object)null)) { Log.Debug("[UpdateTargetFields] ENTRY: instance.targetObject=" + ((Object)instance.targetObject).name); CharacterBody val = default(CharacterBody); bool flag = instance.targetObject.TryGetComponent(ref val); if (ReflectionCache.BaggedObject.IsBody != null) { ReflectionCache.BaggedObject.IsBody.SetValue(instance, flag); Log.Debug($"[UpdateTargetFields] Set isBody={flag}"); } if (flag && ReflectionCache.BaggedObject.TargetBody != null) { ReflectionCache.BaggedObject.TargetBody.SetValue(instance, val); Log.Debug("[UpdateTargetFields] Set targetBody=" + ((!Object.op_Implicit((Object)(object)val)) ? "null" : ((Object)val).name)); } if (ReflectionCache.BaggedObject.VehiclePassengerAttributes != null) { SpecialObjectAttributes val2 = default(SpecialObjectAttributes); instance.targetObject.TryGetComponent(ref val2); ReflectionCache.BaggedObject.VehiclePassengerAttributes.SetValue(instance, val2); Log.Debug("[UpdateTargetFields] Set vehiclePassengerAttributes=" + (((Object)(object)val2 != (Object)null) ? "not null" : "null")); } } } public static void UpdateBagScale(BaggedObject baggedObject, float mass) { if (baggedObject == null) { return; } float num = DrifterBagController.maxMass; DrifterBagController component = ((Component)((EntityState)baggedObject).outer).GetComponent(); if ((Object)(object)component != (Object)null) { num = CapacityScalingSystem.CalculateMassCapacity(component); } float num2 = mass; num2 = ((PluginConfig.Instance.EnableBalance.Value && PluginConfig.Instance.IsBagScaleCapInfinite) ? Mathf.Max(mass, 1f) : Mathf.Clamp(mass, 1f, num)); float num3 = (num2 - 1f) / (num - 1f); float num4 = 0.5f + 0.5f * num3; if (_bagScale01Field != null) { _bagScale01Field.SetValue(baggedObject, num4); } if (PluginConfig.Instance.EnableBalance.Value) { if (PluginConfig.Instance.IsBagScaleCapInfinite || PluginConfig.Instance.ParsedBagScaleCap > 1f) { if ((Object)(object)component != (Object)null) { BagPassengerManager.UpdateUncappedBagScale(component, mass); } if (!(mass > num) && _setScaleMethod != null) { _setScaleMethod.Invoke(baggedObject, new object[1] { num4 }); } } else if (_setScaleMethod != null) { _setScaleMethod.Invoke(baggedObject, new object[1] { num4 }); } } else if (_setScaleMethod != null) { _setScaleMethod.Invoke(baggedObject, new object[1] { num4 }); } } public static void SaveObjectState(DrifterBagController controller, GameObject obj, BaggedObjectStateData state) { BaggedObjectStateStorage.SaveObjectState(controller, obj, state); } public static BaggedObjectStateData? LoadObjectState(DrifterBagController controller, GameObject obj) { return BaggedObjectStateStorage.LoadObjectState(controller, obj); } public static BaggedObjectStateData? FindStateForObject(GameObject obj) { return BaggedObjectStateStorage.FindStateForObject(obj); } public static void CleanupObjectState(DrifterBagController controller, GameObject obj, bool preserveForThrow = false) { BaggedObjectStateStorage.CleanupObjectState(controller, obj, preserveForThrow); } public static void PreserveStateForThrow(DrifterBagController controller, GameObject obj) { BaggedObjectStateStorage.PreserveStateForThrow(controller, obj); } public static void RestorePreservedState(DrifterBagController controller, GameObject obj) { BaggedObjectStateStorage.RestorePreservedState(controller, obj); } public static void ClearTemporaryPreservation(DrifterBagController controller, GameObject obj) { BaggedObjectStateStorage.ClearTemporaryPreservation(controller, obj); } public static void ClearAllTemporaryPreservation(DrifterBagController controller) { BaggedObjectStateStorage.ClearAllTemporaryPreservation(controller); } public static void RemoveUIOverlay(GameObject targetObject, DrifterBagController? bagController = null) { BaggedObjectUIPatches.RemoveUIOverlay(targetObject, bagController); } public static void RemoveUIOverlayForNullState(DrifterBagController bagController) { BaggedObjectUIPatches.RemoveUIOverlayForNullState(bagController); } public static void RefreshUIOverlayForMainSeat(DrifterBagController? bagController, GameObject? targetObject) { BaggedObjectUIPatches.RefreshUIOverlayForMainSeat(bagController, targetObject); } private static bool IsInMainSeat(DrifterBagController bagController, GameObject targetObject) { if ((Object)(object)bagController == (Object)null || (Object)(object)targetObject == (Object)null) { return false; } GameObject mainSeatObject = BagPatches.GetMainSeatObject(bagController); bool flag = false; string text = ""; if ((Object)(object)mainSeatObject != (Object)null) { flag = targetObject == mainSeatObject; text = $"tracked main seat match: {flag}"; } else { VehicleSeat vehicleSeat = bagController.vehicleSeat; if ((Object)(object)vehicleSeat == (Object)null) { text = "vehicle seat is null"; } else { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; flag = (Object)(object)networkpassengerBodyObject != (Object)null && targetObject == networkpassengerBodyObject; text = $"physical seat match: {flag}"; if (flag && (Object)(object)BagHelpers.GetAdditionalSeat(bagController, targetObject) != (Object)null) { flag = false; text += " (but in additional seat)"; } } } Log.Debug(string.Format("[IsInMainSeat] {0}: result={1}, reason={2}", Object.op_Implicit((Object)(object)targetObject) ? ((Object)targetObject).name : "null", flag, text)); return flag; } public static GameObject? GetMainSeatOccupant(DrifterBagController controller) { if ((Object)(object)controller == (Object)null || (Object)(object)controller.vehicleSeat == (Object)null) { return null; } if (!controller.vehicleSeat.hasPassenger) { return null; } if (!((Object)(object)controller.vehicleSeat.currentPassengerBody != (Object)null)) { return null; } return ((Component)controller.vehicleSeat.currentPassengerBody).gameObject; } public static BaggedObject? FindOrCreateBaggedObjectState(DrifterBagController bagController, GameObject? targetObject) { //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Expected O, but got Unknown if ((Object)(object)bagController == (Object)null || (Object)(object)targetObject == (Object)null) { return null; } Log.Debug(string.Format("[FindOrCreateBaggedObjectState] Called with targetObject={0}, NetworkServer.active={1}", (!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name, NetworkServer.active)); EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)bagController).gameObject, "Bag"); if ((Object)(object)val != (Object)null) { EntityState state = val.state; BaggedObject val2 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val2 != null && (Object)(object)val2.targetObject == (Object)(object)targetObject) { Log.Debug("[FindOrCreateBaggedObjectState] Found existing BaggedObject state for " + (Object.op_Implicit((Object)(object)targetObject) ? ((Object)targetObject).name : "null")); return val2; } } try { EntityStateMachine val3 = val; if ((Object)(object)val3 == (Object)null) { val3 = ((Component)bagController).gameObject.AddComponent(); val3.customName = "Bag"; } if ((Object)(object)val3 != (Object)null) { List baggedObjects = BagPatches.GetState(bagController).BaggedObjects; if (baggedObjects == null || !((Object)(object)targetObject != (Object)null) || !baggedObjects.Contains(targetObject)) { int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(bagController, targetObject); int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(bagController); if (currentBaggedCount >= utilityMaxStock) { Log.Debug(string.Format("[FindOrCreateBaggedObjectState] Skipping - bag full ({0}/{1}) for {2}", currentBaggedCount, utilityMaxStock, (!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name)); return null; } } ConstructorInfo constructor = typeof(BaggedObject).GetConstructor(Type.EmptyTypes); if (constructor != null) { BaggedObject val4 = (BaggedObject)constructor.Invoke(null); val4.targetObject = targetObject; DrifterBagController val5 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent() : ((Component)bagController).gameObject.GetComponent()); if ((Object)(object)val5 != (Object)null) { ReflectionCache.BaggedObject.DrifterBagController?.SetValue(val4, val5); } Log.Debug("[FindOrCreateBaggedObjectState] Creating NEW BaggedObject with targetObject=" + ((!Object.op_Implicit((Object)(object)targetObject)) ? "null" : ((Object)targetObject).name) + ", drifterBagController=" + ((!Object.op_Implicit((Object)(object)val5)) ? "null" : ((Object)val5).name)); val3.SetState((EntityState)(object)val4); return val4; } } } catch (Exception arg) { Log.Error($"[FindOrCreateBaggedObjectState] Error: {arg}"); } return null; } public static void HandlePassengerExit(VehicleSeat seat, GameObject passenger) { if ((Object)(object)seat == (Object)null || (Object)(object)passenger == (Object)null || !NetworkServer.active) { return; } if (NetworkUtils.IsNetworkIdentityInactive(passenger)) { Log.Warning("[HandlePassengerExit] Suppressing spurious exit for " + ((Object)passenger).name + " - NetworkIdentity is inactive (likely deactivation bug)"); NetworkUtils.TryEnsureNetworkIdentityActive(passenger); return; } DrifterBagController componentInParent = ((Component)seat).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null || DrifterBossGrabPlugin.IsSwappingPassengers) { return; } GameObject incomingObject = BagPatches.GetState(componentInParent).IncomingObject; if ((Object)(object)incomingObject != (Object)null && passenger == incomingObject) { Log.Debug("[HandlePassengerExit] Skipping RemoveBaggedObject for " + ((Object)passenger).name + " - same as IncomingObject (reassignment, not true exit)"); return; } List baggedObjects = BagPatches.GetState(componentInParent).BaggedObjects; if (baggedObjects != null && baggedObjects.Contains(passenger)) { Log.Debug("[HandlePassengerExit] Passenger " + ((Object)passenger).name + " exited seat " + ((Object)seat).name + ". Triggering full RemoveBaggedObject."); RemoveUIOverlay(passenger, componentInParent); BagPassengerManager.RemoveBaggedObject(componentInParent, passenger); } } public static bool IsPassengerDeadOrDestroyed(GameObject passenger) { if ((Object)(object)passenger == (Object)null) { return true; } HealthComponent component = passenger.GetComponent(); if ((Object)(object)component != (Object)null && !component.alive) { return true; } SpecialObjectAttributes component2 = passenger.GetComponent(); if (component2 != null && component2.durability <= 0) { return true; } return false; } } public static class BaggedObjectStatePatches { [HarmonyPatch(typeof(BaggedObject), "OnEnter")] public class BaggedObject_OnEnter { [HarmonyPrefix] public static bool Prefix(BaggedObject __instance) { if (__instance == null) { Log.Warning("[BaggedObject_OnEnter.Prefix] __instance is null"); return false; } if ((Object)(object)__instance.targetObject != (Object)null) { float time = Time.time; if (__instance.targetObject == _lastProcessedObject && time - _lastProcessTime < 0.5f) { Log.Debug($"[BaggedObject_OnEnter.Prefix] Blocking re-entry for {((Object)__instance.targetObject).name} (processed {time - _lastProcessTime:F3}s ago)"); return false; } } object obj; if (__instance == null) { obj = null; } else { EntityStateMachine outer = ((EntityState)__instance).outer; obj = ((outer != null) ? ((Component)outer).GetComponent() : null); } DrifterBagController val = (DrifterBagController)obj; if ((Object)(object)val == (Object)null) { Log.Warning("[BaggedObject_OnEnter.Prefix] bagController is null, proceeding with vanilla OnEnter"); return true; } GameObject val2 = __instance?.targetObject; if ((Object)(object)val2 == (Object)null) { if (!NetworkServer.active && (Object)(object)val != (Object)null) { GameObject val3 = val.baggedObject; if ((Object)(object)val3 == (Object)null && (Object)(object)val.vehicleSeat != (Object)null && val.vehicleSeat.hasPassenger) { val3 = val.vehicleSeat.NetworkpassengerBodyObject; } if ((Object)(object)val3 == (Object)null) { val3 = BagPatches.GetMainSeatObject(val); } if ((Object)(object)val3 != (Object)null) { __instance.targetObject = val3; val2 = val3; BaggedObjectPatches.UpdateTargetFields(__instance); Log.Debug("[BaggedObject_OnEnter.Prefix] RECOVERED targetObject from controller/seat: " + ((Object)val3).name); } } if ((Object)(object)val2 == (Object)null) { Log.Warning("[BaggedObject_OnEnter.Prefix] targetObject is null - likely deserialization failure or object destroyed"); object obj2; if (__instance == null) { obj2 = null; } else { EntityStateMachine outer2 = ((EntityState)__instance).outer; obj2 = ((outer2 != null) ? ((Component)outer2).gameObject : null); } NetworkUtils.LogObjectDetails((GameObject?)obj2, "BaggedObject_OnEnter.Prefix"); return false; } } if (!NetworkUtils.ValidateObjectReadyWithRecovery(val2)) { Log.Warning("[BaggedObject_OnEnter.Prefix] " + ((Object)val2).name + " is not ready for network operations (recovery attempted)"); return false; } if (ProjectileRecoveryPatches.IsUndergoingThrowOperation(val2)) { Log.Warning("[BaggedObject_OnEnter.Prefix] Blocking grab of " + ((Object)val2).name + " - object is currently undergoing throw operation"); return false; } NetworkUtils.LogNetworkOperation("BaggedObject_OnEnter", val2, NetworkServer.active, new Dictionary { { "bagController", ((Object)val).name }, { "isAuthority", ((NetworkBehaviour)val).hasAuthority } }); ConcurrentDictionary additionalSeats = BagPatches.GetState(val).AdditionalSeats; if (additionalSeats != null && additionalSeats.TryGetValue(val2, out var value)) { value.AssignPassenger(val2); if (NetworkUtils.IsNetworkIdentityInactive(val2)) { NetworkUtils.TryEnsureNetworkIdentityActive(val2); } if (__instance != null) { EntityStateMachine outer3 = ((EntityState)__instance).outer; if (outer3 != null) { outer3.SetNextStateToMain(); } } return false; } if (!NetworkServer.active && ((NetworkBehaviour)val).hasAuthority) { int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(val, val2); bool value2 = PluginConfig.Instance.PrioritizeMainSeat.Value; if (utilityMaxStock > 1 && !value2) { List baggedObjects = BagPatches.GetState(val).BaggedObjects; if (!baggedObjects.Contains(val2)) { int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(val); if (currentBaggedCount >= utilityMaxStock) { Log.Debug($"[BaggedObject_OnEnter.Prefix] Client BLOCKING grab of {((Object)val2).name} - bag full ({currentBaggedCount}/{utilityMaxStock})"); return false; } Log.Debug($"[BaggedObject_OnEnter.Prefix] Client allowing vanilla OnEnter for NEW GRAB of {((Object)val2).name} (capacity={utilityMaxStock}) but FLAGGING to block seat assignment"); baggedObjects.Add(val2); BagHelpers.AddTracker(val, val2); BagCarouselUpdater.UpdateCarousel(val); BagCarouselUpdater.UpdateNetworkBagState(val); BagPassengerManager.ForceRecalculateMass(val); } else { int currentBaggedCount2 = BagCapacityCalculator.GetCurrentBaggedCount(val); if (currentBaggedCount2 > utilityMaxStock) { Log.Debug($"[BaggedObject_OnEnter.Prefix] Client BLOCKING CYCLING of {((Object)val2).name} - bag over capacity ({currentBaggedCount2}/{utilityMaxStock})"); return false; } Log.Debug($"[BaggedObject_OnEnter.Prefix] Client allowing vanilla OnEnter for CYCLING of {((Object)val2).name} (capacity={utilityMaxStock})"); } return true; } } return true; } [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Unknown result type (might be due to invalid IL or missing references) //IL_0365: Unknown result type (might be due to invalid IL or missing references) //IL_036c: Expected O, but got Unknown if (__instance == null) { return; } EntityStateMachine outer = ((EntityState)__instance).outer; DrifterBagController val = ((outer != null) ? ((Component)outer).GetComponent() : null); GameObject targetObject = __instance.targetObject; if ((Object)(object)targetObject != (Object)null) { ProjectileFuse component = targetObject.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = false; } } if ((Object)(object)targetObject != (Object)null && (Object)(object)val != (Object)null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(val, targetObject); if (baggedObjectStateData != null) { baggedObjectStateData.ApplyToBaggedObject(__instance); if (ReflectionCache.DrifterBagController.Smacks != null) { int smacks = baggedObjectStateData.smacks; ReflectionCache.DrifterBagController.Smacks.SetValue(val, smacks); } Log.Debug($"[BaggedObject_OnEnter.Postfix] Restored breakout state for {((Object)targetObject).name}: age={baggedObjectStateData.elapsedBreakoutTime:F2}s, smacks={baggedObjectStateData.smacks}"); } BaggedObjectPatches.SynchronizeBaggedObjectState(val, targetObject); } BagPassengerManager.SuppressVanillaWalkSpeedModifier(__instance); if ((Object)(object)targetObject != (Object)null) { _lastProcessedObject = targetObject; _lastProcessTime = Time.time; } else { _lastProcessedObject = null; _lastProcessTime = Time.time; } if ((Object)(object)val == (Object)null || (Object)(object)targetObject == (Object)null) { return; } BaggedObject_OnExit.MarkObjectSuccessfullyInitialized(targetObject); bool flag = (Object)(object)BagHelpers.GetAdditionalSeat(val, targetObject) != (Object)null; bool flag2 = false; if (((NetworkBehaviour)val).hasAuthority && !NetworkServer.active) { int utilityMaxStock = BagCapacityCalculator.GetUtilityMaxStock(val, targetObject); bool flag3 = BagPatches.GetState(val).BaggedObjects.Contains(targetObject); bool value = PluginConfig.Instance.PrioritizeMainSeat.Value; if (utilityMaxStock > 1 && !flag3 && !value) { Log.Debug($"[BaggedObject_OnEnter.Postfix] Client skipping main seat population for NEW GRAB of {((Object)targetObject).name} (capacity={utilityMaxStock})"); } else { BottomlessBagNetworkController component2 = ((Component)val).GetComponent(); bool flag4 = true; if ((Object)(object)component2 != (Object)null && component2.selectedIndex < 0 && component2.GetBaggedObjects().Count > 0) { flag4 = false; } if (flag4 && (Object)(object)BagPatches.GetMainSeatObject(val) == (Object)null && !flag) { BagPatches.SetMainSeatObject(val, targetObject); } } BagState state = BagPatches.GetState(val); List baggedObjects = state.BaggedObjects; if (baggedObjects != null && !baggedObjects.Contains(targetObject)) { baggedObjects.Add(targetObject); state.AddInstanceId(((Object)targetObject).GetInstanceID()); BagHelpers.AddTracker(val, targetObject); flag2 = true; } } VehicleSeat vehicleSeat = val.vehicleSeat; bool flag5 = (Object)(object)vehicleSeat != (Object)null && vehicleSeat.hasPassenger && vehicleSeat.NetworkpassengerBodyObject == targetObject; GameObject mainSeatObject = BagPatches.GetMainSeatObject(val); bool flag6 = (Object)(object)mainSeatObject != (Object)null && mainSeatObject == targetObject; if (PluginConfig.Instance.EnableDebugLogs.Value) { NetworkIdentity component3 = targetObject.GetComponent(); object obj; if (!((Object)(object)component3 != (Object)null)) { obj = "null"; } else { NetworkInstanceId netId = component3.netId; obj = ((object)(NetworkInstanceId)(ref netId)).ToString(); } string text = (string)obj; Log.Debug("[BaggedObject_OnEnter.Postfix] " + ((Object)targetObject).name + ": " + $"seatHasTarget={flag5}, " + "tracked=" + ((!Object.op_Implicit((Object)(object)mainSeatObject)) ? "null" : ((Object)mainSeatObject).name) + ", " + $"trackedHasTarget={flag6}, " + $"isInAdditionalSeat={flag}. " + "NetId: " + text + "."); } if (!((NetworkBehaviour)val).hasAuthority && !flag5 && !flag6 && !flag) { OverlayController val2 = (OverlayController)ReflectionCache.BaggedObject.UIOverlayController.GetValue(__instance); if (val2 != null) { HudOverlayManager.RemoveOverlay(val2); ReflectionCache.BaggedObject.UIOverlayController.SetValue(__instance, null); } } if ((Object)(object)val != (Object)null && (Object)(object)targetObject != (Object)null) { BagCarouselUpdater.UpdateCarousel(val); if (flag2 && ((NetworkBehaviour)val).hasAuthority) { BagCarouselUpdater.UpdateNetworkBagState(val); } } else if ((Object)(object)val != (Object)null && (Object)(object)targetObject != (Object)null && !flag) { BaggedObjectUIPatches.RefreshUIOverlayForMainSeat(val, targetObject); } if (PluginConfig.Instance.EnableCarouselHUD.Value) { object? obj2 = ReflectionCache.BaggedObject.UIOverlayController?.GetValue(__instance); OverlayController val3 = (OverlayController)((obj2 is OverlayController) ? obj2 : null); if (val3 != null) { HudOverlayManager.RemoveOverlay(val3); ReflectionCache.BaggedObject.UIOverlayController?.SetValue(__instance, null); } } if (!flag) { BaggedObjectUIPatches.RefreshUIOverlayForMainSeat(val, targetObject); } bool flag7 = flag; bool flag8 = (Object)(object)val != (Object)null && (Object)(object)val.vehicleSeat != (Object)null && val.vehicleSeat.hasPassenger && val.vehicleSeat.NetworkpassengerBodyObject == targetObject; GameObject val4 = (((Object)(object)val != (Object)null) ? BagPatches.GetMainSeatObject(val) : null); bool flag9 = (Object)(object)val4 != (Object)null && val4 == targetObject; if (flag7 && !flag8 && !flag9) { if (__instance != null && (Object)(object)((EntityState)__instance).outer != (Object)null) { ((EntityState)__instance).outer.SetNextStateToMain(); } } else { _ = flag7 && !flag8 && flag9; } if (!PluginConfig.Instance.EnableBalance.Value) { return; } bool isBagScaleCapInfinite = PluginConfig.Instance.IsBagScaleCapInfinite; if (!PluginConfig.Instance.IsBagScaleCapInfinite && !(PluginConfig.Instance.ParsedBagScaleCap > 1f)) { return; } try { float num; if ((Object)(object)val != (Object)null) { num = 0f; BagState state2 = BagPatches.GetState(val); if (state2?.BaggedObjects != null) { foreach (GameObject baggedObject in state2.BaggedObjects) { if ((Object)(object)baggedObject != (Object)null) { num += val.CalculateBaggedObjectMass(baggedObject); } } } } else { num = (float)ReflectionCache.BaggedObject.BaggedMass.GetValue(__instance); } if (__instance != null) { ReflectionCache.BaggedObject.BaggedMass?.SetValue(__instance, num); BaggedObjectPatches.UpdateBagScale(__instance, num); } else { Log.Warning("[BaggedObject_OnEnter.Postfix] __instance is null, cannot update bag scale"); } } catch (Exception arg) { Log.Error($" [BaggedObject_OnEnter_Postfix] Error uncapping bag scale: {arg}"); } } } [HarmonyPatch(typeof(BaggedObject), "OnExit")] public class BaggedObject_OnExit { internal static readonly HashSet _preserveOverridesDuringCycling = new HashSet(); internal static readonly HashSet _successfullyInitializedObjects = new HashSet(); public static void MarkObjectSuccessfullyInitialized(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_successfullyInitializedObjects) { _successfullyInitializedObjects.Add(obj); } } public static void ClearObjectSuccessfullyInitialized(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_successfullyInitializedObjects) { _successfullyInitializedObjects.Remove(obj); } } public static void MarkPreserveOverridesDuringCycling(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_preserveOverridesDuringCycling) { _preserveOverridesDuringCycling.Add(obj); } } public static void ClearPreserveOverridesDuringCycling(GameObject obj) { if ((Object)(object)obj == (Object)null) { return; } lock (_preserveOverridesDuringCycling) { _preserveOverridesDuringCycling.Remove(obj); } } [HarmonyPrefix] public static bool Prefix(BaggedObject __instance) { if (__instance == null) { Log.Warning("[BaggedObject_OnExit.Prefix] __instance is null"); return true; } EntityStateMachine outer = ((EntityState)__instance).outer; DrifterBagController val = ((outer != null) ? ((Component)outer).GetComponent() : null); if (PluginConfig.Instance.EnableDebugLogs.Value) { GameObject obj = (((Object)(object)val != (Object)null) ? BagPatches.GetMainSeatObject(val) : null); EntityStateMachine outer2 = ((EntityState)__instance).outer; EntityStateMachine val2 = EntityStateMachine.FindByCustomName((outer2 != null) ? ((Component)outer2).gameObject : null, "Bag"); string text = ((val2 == null) ? null : ((object)val2.state)?.GetType().Name) ?? "null"; EntityState obj2 = ((val2 != null) ? val2.state : null); GameObject obj3 = ((BaggedObject)(((obj2 is BaggedObject) ? obj2 : null)?)).targetObject; Log.Debug("[BaggedObject_OnExit.Prefix] CALLED: InstanceTarget=" + BagHelpers.GetSafeName((Object?)(object)__instance?.targetObject) + ", StateTarget=" + BagHelpers.GetSafeName((Object?)(object)obj3) + ", State=" + text + ", MainPassenger=" + BagHelpers.GetSafeName((Object?)(object)obj)); } if ((Object)(object)val == (Object)null) { Log.Warning("[BaggedObject_OnExit.Prefix] bagController is null, proceeding with vanilla OnExit"); return true; } if (__instance == null || (Object)(object)__instance.targetObject == (Object)null) { Log.Warning("[BaggedObject_OnExit.Prefix] targetObject is null - likely deserialization failure or object destroyed"); object obj4; if (__instance == null) { obj4 = null; } else { EntityStateMachine outer3 = ((EntityState)__instance).outer; obj4 = ((outer3 != null) ? ((Component)outer3).gameObject : null); } NetworkUtils.LogObjectDetails((GameObject?)obj4, "BaggedObject_OnExit.Prefix"); } else { if (!NetworkUtils.ValidateObjectReady(__instance.targetObject)) { Log.Warning("[BaggedObject_OnExit.Prefix] " + ((Object)__instance.targetObject).name + " is not ready for network operations"); } NetworkUtils.LogNetworkOperation("BaggedObject_OnExit", __instance.targetObject, NetworkServer.active, new Dictionary { { "bagController", ((Object)val).name }, { "isAuthority", ((NetworkBehaviour)val).hasAuthority } }); } if (__instance != null && (Object)(object)__instance.targetObject != (Object)null) { ProjectileFuse component = __instance.targetObject.GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = true; } } bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; GameObject val3 = __instance?.targetObject; if ((Object)(object)val != (Object)null && (Object)(object)val3 != (Object)null) { GameObject mainSeatObject = BagPatches.GetMainSeatObject(val); flag4 = (Object)(object)mainSeatObject != (Object)null && val3 == mainSeatObject; flag5 = (Object)(object)val.vehicleSeat != (Object)null && val.vehicleSeat.hasPassenger && val.vehicleSeat.NetworkpassengerBodyObject == val3; flag2 = (Object)(object)val.vehicleSeat != (Object)null && val.vehicleSeat.hasPassenger && val.vehicleSeat.NetworkpassengerBodyObject != val3; HealthComponent val4 = default(HealthComponent); flag3 = val3.TryGetComponent(ref val4) && !val4.alive; flag = flag4 && flag5 && !flag3 && val3.activeInHierarchy && !flag2; } if (flag) { Log.Debug(" [BaggedObject_OnExit] " + BagHelpers.GetSafeName((Object?)(object)val3) + ": " + $"isTrackedAsMain={flag4}, " + $"isPhysicallyInSeat={flag5}, " + $"isDeadCheck={flag3}, " + $"activeInHierarchy={val3 != null && val3.activeInHierarchy}, " + $"isDifferentObjectInMainSeat={flag2}, " + $"shouldKeepOverrides={flag}."); } else { bool flag6 = false; if ((Object)(object)val3 != (Object)null) { lock (_preserveOverridesDuringCycling) { flag6 = _preserveOverridesDuringCycling.Contains(val3); _preserveOverridesDuringCycling.Remove(val3); } } if (flag6 && !flag2) { Log.Debug(" [BaggedObject_OnExit] Skipping UnsetAllOverrides - object " + BagHelpers.GetSafeName((Object?)(object)val3) + " is marked to preserve overrides during cycling."); } else { if (flag6) { Log.Debug(" [BaggedObject_OnExit] Forcing UnsetAllOverrides during cycling - different object in main seat or object is dead."); } if (__instance != null) { UnsetAllOverrides(__instance); } } } if (!Object.op_Implicit((Object)(object)__instance?.targetObject)) { Log.Debug(" [BaggedObject_OnExit] targetObject is null/destroyed, skipping original OnExit to prevent NRE (cleanup already attempted)."); if (__instance != null) { TrySpawnJunkForSkippedOnExit(__instance, "null/destroyed targetObject"); RemoveWalkSpeedPenalty(__instance); } return false; } bool flag7 = false; if ((Object)(object)__instance?.targetObject != (Object)null) { bool flag8 = (Object)(object)val != (Object)null && (Object)(object)BagHelpers.GetAdditionalSeat(val, __instance.targetObject) != (Object)null; bool flag9 = (Object)(object)val != (Object)null && (Object)(object)BagPatches.GetMainSeatObject(val) == (Object)(object)__instance.targetObject; if ((Object)(object)val != (Object)null && (flag8 || flag9)) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(val, __instance.targetObject) ?? new BaggedObjectStateData(); baggedObjectStateData.CaptureBreakoutStateFromBaggedObject(__instance); BaggedObjectPatches.SaveObjectState(val, __instance.targetObject, baggedObjectStateData); } if (!flag8) { PerformPassengerRestoration(val, __instance.targetObject); } HealthComponent val5 = default(HealthComponent); flag7 = __instance.targetObject.TryGetComponent(ref val5) && !val5.alive; } if (flag7) { Log.Debug(" [BaggedObject_OnExit] targetObject is dead/dying (" + BagHelpers.GetSafeName((Object?)(object)__instance?.targetObject) + "), skipping original OnExit to avoid crashes (cleanup already attempted)."); if (__instance != null) { TrySpawnJunkForSkippedOnExit(__instance, "dead/dying " + BagHelpers.GetSafeName((Object?)(object)__instance?.targetObject)); RemoveWalkSpeedPenalty(__instance); } return false; } return true; } } [HarmonyPatch(typeof(BaggedObject), "HoldsDeadBody")] public class BaggedObject_HoldsDeadBody_Patch { [HarmonyPrefix] public static bool Prefix(BaggedObject __instance, ref bool __result) { if (__instance == null || (Object)(object)__instance.targetObject == (Object)null) { __result = false; return false; } return true; } } [HarmonyPatch(typeof(BaggedObject), "FixedUpdate")] public class BaggedObject_FixedUpdate_Patch { [HarmonyPrefix] public static bool Prefix(BaggedObject __instance) { if (__instance == null || (Object)(object)__instance.targetObject == (Object)null || (Object)(object)((EntityState)__instance).outer == (Object)null || (Object)(object)__instance.drifterBagController == (Object)null) { return false; } if (((EntityState)__instance).isAuthority && (Object)(object)__instance.baseAI != (Object)null && (Object)(object)__instance.targetBody == (Object)null) { return false; } return true; } } [HarmonyPatch(typeof(BaggedObject), "UpdateBaggedObjectMass")] public class BaggedObject_UpdateBaggedObjectMass { [HarmonyPrefix] public static bool Prefix(BaggedObject __instance) { if (__instance == null || (Object)(object)((EntityState)__instance).outer == (Object)null) { return true; } DrifterBagController component = ((Component)((EntityState)__instance).outer).GetComponent(); if ((Object)(object)component == (Object)null) { return true; } Log.Debug("[BaggedObject_UpdateBaggedObjectMass] Suppressing vanilla penalty update for " + ((!Object.op_Implicit((Object)(object)__instance.targetObject)) ? "null" : ((Object)__instance.targetObject).name)); return false; } } [HarmonyPatch(typeof(EntityStateMachine), "SetNextStateToMain")] public class EntityStateMachine_SetNextStateToMain { [HarmonyPrefix] public static bool Prefix(EntityStateMachine __instance) { if ((Object)(object)__instance != (Object)null && __instance.customName == "Bag") { DrifterBagController component = ((Component)__instance).gameObject.GetComponent(); if ((Object)(object)component != (Object)null) { GameObject val = BagPatches.GetMainSeatObject(component); if ((Object)(object)val == (Object)null) { val = component.baggedObject; if ((Object)(object)val == (Object)null && (Object)(object)component.vehicleSeat != (Object)null && component.vehicleSeat.hasPassenger) { val = component.vehicleSeat.NetworkpassengerBodyObject; } } if ((Object)(object)val != (Object)null) { bool flag = false; GameObject mainSeatObject = BagPatches.GetMainSeatObject(component); if ((Object)(object)mainSeatObject != (Object)null && mainSeatObject == val) { flag = true; } else if (BagPatches.GetState(component).BaggedObjects.Contains(val)) { flag = true; } if (!flag) { if ((Object)(object)component.vehicleSeat != (Object)null && component.vehicleSeat.hasPassenger && component.vehicleSeat.NetworkpassengerBodyObject == val) { flag = true; } else { VehicleSeat[] componentsInChildren = ((Component)component).GetComponentsInChildren(true); VehicleSeat[] array = componentsInChildren; foreach (VehicleSeat val2 in array) { if ((Object)(object)val2 != (Object)null && val2.hasPassenger && val2.NetworkpassengerBodyObject == val) { flag = true; break; } } } } bool flag2 = BaggedObjectPatches.IsPassengerDeadOrDestroyed(val); if (!flag2 && flag) { return false; } } } } return true; } } [HarmonyPatch(typeof(EntityStateMachine), "SetState")] public class EntityStateMachine_SetState { [HarmonyPrefix] public static void Prefix(EntityStateMachine __instance, EntityState newState) { if ((Object)(object)__instance == (Object)null || newState == null || !_trackedESMs.TryGetValue(__instance, out BaggedObjectTracker value) || (Object)(object)value == (Object)null || value.isRemovingManual || DrifterBossGrabPlugin.IsSwappingPassengers) { return; } DrifterBagController controller = value.controller; if ((Object)(object)controller == (Object)null) { return; } GameObject gameObject = ((Component)__instance).gameObject; if ((Object)(object)gameObject == (Object)null) { return; } string name = ((object)newState).GetType().Name; string text = ((object)__instance.state)?.GetType()?.Name ?? "null"; if (newState is GenericCharacterVehicleSeated || name.Contains("SpawnState")) { return; } Type type = ((object)newState).GetType(); Type stateType = ((SerializableEntityStateType)(ref __instance.mainStateType)).stateType; bool flag = (type != null && stateType != null && type == stateType) || name == "GenericCharacterMain"; bool flag2 = name.Contains("Idle") || name.Contains("Uninitialized"); bool flag3 = flag && text.Contains("VehicleSeated"); bool flag4 = name.Contains("StunState") && text.Contains("VehicleSeated"); if (flag2 || flag3 || flag4) { return; } Log.Debug("[EntityStateMachine_SetState] Bagged object " + ((Object)gameObject).name + " ESM '" + __instance.customName + "' transitioning " + text + " → " + name + " (UNAUTHORIZED/ESCAPE) — cleaning up bag tracking"); try { PerformPassengerRestoration(controller, gameObject); BagPassengerManager.RemoveBaggedObject(controller, gameObject); BagCarouselUpdater.UpdateCarousel(controller); } catch (Exception ex) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[EntityStateMachine_SetState] Error during escape cleanup: " + ex.Message); } } } } private static readonly FieldInfo _skillOverrideSourceField = typeof(SkillOverride).GetField("source", BindingFlags.Instance | BindingFlags.Public); private static readonly FieldInfo _skillOverrideSkillDefField = typeof(SkillOverride).GetField("skillDef", BindingFlags.Instance | BindingFlags.Public); private static readonly FieldInfo _skillOverridePriorityField = typeof(SkillOverride).GetField("priority", BindingFlags.Instance | BindingFlags.Public); private static GameObject? _lastProcessedObject; private static float _lastProcessTime; private static readonly ConditionalWeakTable _trackedESMs = new ConditionalWeakTable(); public static void PerformPassengerRestoration(DrifterBagController? bagController, GameObject? restoreTarget) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)restoreTarget == (Object)null)) { if ((Object)(object)restoreTarget.transform.parent != (Object)null) { Log.Debug("[PerformPassengerRestoration] Unparenting " + ((Object)restoreTarget).name + " from " + ((Object)restoreTarget.transform.parent).name); restoreTarget.transform.SetParent((Transform)null, true); } Log.Debug("[PerformPassengerRestoration] Restoring " + ((Object)restoreTarget).name); Log.Debug($" Current Pos: {restoreTarget.transform.position}"); Log.Debug(" Current Parent: " + (((Object)(object)restoreTarget.transform.parent != (Object)null) ? ((Object)restoreTarget.transform.parent).name : "null")); BagState bagState = (((Object)(object)bagController != (Object)null) ? BagPatches.GetState(bagController) : null); if (bagState != null && bagState.DisabledCollidersByObject.TryGetValue(restoreTarget, out Dictionary value)) { BodyColliderCache.RestoreMovementColliders(value); bagState.DisabledCollidersByObject.Remove>(restoreTarget, out var _); Log.Debug("[PerformPassengerRestoration] Restored movement colliders for " + ((Object)restoreTarget).name); } CharacterBody component = restoreTarget.GetComponent(); BaggedObjectStateData baggedObjectStateData = (((Object)(object)bagController != (Object)null) ? BaggedObjectPatches.LoadObjectState(bagController, restoreTarget) : null); if (baggedObjectStateData != null && (Object)(object)component != (Object)null) { baggedObjectStateData.ApplyToCharacterBody(component); baggedObjectStateData.ResetBreakoutData(); Log.Debug("[PerformPassengerRestoration] Applied stats to " + ((Object)restoreTarget).name); } baggedObjectStateData?.RestorePhysicsAndHurtboxes(restoreTarget); } } public static void ForceCleanupOverrides(DrifterBagController bagController, GameObject targetObject) { if (!((Object)(object)bagController == (Object)null) && !((Object)(object)targetObject == (Object)null)) { BaggedObject val = BaggedObjectPatches.FindExistingBaggedObjectState(bagController, targetObject); if (val != null) { UnsetAllOverrides(val); } } } internal static void UnsetAllOverrides(BaggedObject instance) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown try { EntityStateMachine outer = ((EntityState)instance).outer; CharacterBody val = ((outer != null) ? ((Component)outer).GetComponent() : null); Log.Debug("[BaggedObjectStatePatches.UnsetAllOverrides] Starting cleanup for instance of " + ((object)instance).GetType().Name + " on " + ((!Object.op_Implicit((Object)(object)val)) ? "null" : ((Object)val).name) + "."); if (ReflectionCache.BaggedObject.OverriddenUtility != null && ReflectionCache.BaggedObject.UtilityOverride != null) { GenericSkill val2 = (GenericSkill)ReflectionCache.BaggedObject.OverriddenUtility.GetValue(instance); SkillDef val3 = (SkillDef)ReflectionCache.BaggedObject.UtilityOverride.GetValue(instance); if ((Object)(object)val2 != (Object)null) { if ((Object)(object)val3 != (Object)null) { val2.UnsetSkillOverride((object)instance, val3, (SkillOverridePriority)4); } ReflectionCache.BaggedObject.OverriddenUtility.SetValue(instance, null); } } if (ReflectionCache.BaggedObject.OverriddenPrimary != null && ReflectionCache.BaggedObject.PrimaryOverride != null) { GenericSkill val4 = (GenericSkill)ReflectionCache.BaggedObject.OverriddenPrimary.GetValue(instance); SkillDef val5 = (SkillDef)ReflectionCache.BaggedObject.PrimaryOverride.GetValue(instance); if ((Object)(object)val4 != (Object)null) { if ((Object)(object)val5 != (Object)null) { val4.UnsetSkillOverride((object)instance, val5, (SkillOverridePriority)4); } ReflectionCache.BaggedObject.OverriddenPrimary.SetValue(instance, null); } } SkillLocator val6 = ((val != null) ? val.skillLocator : null); if ((Object)(object)val6 != (Object)null) { if (Object.op_Implicit((Object)(object)val6.primary)) { CleanupSkillFromLocator(instance, val6.primary); } if (Object.op_Implicit((Object)(object)val6.secondary)) { CleanupSkillFromLocator(instance, val6.secondary); } if (Object.op_Implicit((Object)(object)val6.utility)) { CleanupSkillFromLocator(instance, val6.utility); } if (Object.op_Implicit((Object)(object)val6.special)) { CleanupSkillFromLocator(instance, val6.special); } } } catch (Exception ex) { Log.Error("Error in UnsetAllOverrides: " + ex.Message); } } private static void RemoveWalkSpeedPenalty(BaggedObject instance) { if (instance == null || (Object)(object)((EntityState)instance).outer == (Object)null) { return; } try { CharacterMotor component = ((Component)((EntityState)instance).outer).gameObject.GetComponent(); if (!((Object)(object)component == (Object)null) && ReflectionCache.BaggedObject.WalkSpeedModifier != null) { object? value = ReflectionCache.BaggedObject.WalkSpeedModifier.GetValue(instance); WalkSpeedPenaltyModifier val = (WalkSpeedPenaltyModifier)((value is WalkSpeedPenaltyModifier) ? value : null); if (val != null) { component.RemoveWalkSpeedPenalty(val); ReflectionCache.BaggedObject.WalkSpeedModifier.SetValue(instance, null); } } } catch (Exception ex) { Log.Error("Error in RemoveWalkSpeedPenalty: " + ex.Message); } } private static void TrySpawnJunkForSkippedOnExit(BaggedObject? instance, string reason) { //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_029d: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_02a2: Unknown result type (might be due to invalid IL or missing references) //IL_02cc: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_03cb: Unknown result type (might be due to invalid IL or missing references) //IL_03d9: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) try { DrifterBagController val = null; try { object? obj = ReflectionCache.BaggedObject.DrifterBagController?.GetValue(instance); val = (DrifterBagController)((obj is DrifterBagController) ? obj : null); } catch (Exception ex) { Log.Debug(" [TrySpawnJunk] Reflection failed: " + ex.Message); } if ((Object)(object)val == (Object)null && instance != null && (Object)(object)((EntityState)instance).outer != (Object)null && (Object)(object)((Component)((EntityState)instance).outer).gameObject != (Object)null) { val = ((Component)((EntityState)instance).outer).gameObject.GetComponent(); Log.Debug(" [TrySpawnJunk] Traverse returned null, GetComponent returned: " + ((!Object.op_Implicit((Object)(object)val)) ? "null" : ((Object)val).name)); } if (PluginConfig.Instance.EnableDebugLogs.Value) { string safeName = BagHelpers.GetSafeName((Object?)(object)val); string text = (((Object)(object)val != (Object)null) ? BagHelpers.GetSafeName((Object?)(object)val.baggedBody) : "NULL"); string text2 = (((Object)(object)val != (Object)null) ? BagHelpers.GetSafeName((Object?)(object)val.baggedAttributes) : "NULL"); Log.Debug($"[TrySpawnJunk] Reason: {reason} | bagController: {safeName} | Server: {NetworkServer.active} | baggedBody: {text} | attributes: {text2}"); } if ((Object)(object)val != (Object)null && NetworkServer.active) { bool flag = (Object)(object)instance?.targetObject == (Object)null; bool flag2 = false; if ((Object)(object)((EntityState)(instance?)).outer != (Object)null) { EntityStateMachine val2 = EntityStateMachine.FindByCustomName(((Component)((EntityState)instance).outer).gameObject, "Body"); if ((Object)(object)val2 != (Object)null) { lock (BaggedObject_OnExit._successfullyInitializedObjects) { flag2 = BaggedObject_OnExit._successfullyInitializedObjects.Contains(((Component)val2).gameObject); } } } EntityStateMachine val3 = EntityStateMachine.FindByCustomName(((Component)val).gameObject, "Bag"); bool flag3 = false; if ((Object)(object)val3 != (Object)null) { EntityState state = val3.state; BaggedObject val4 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val4 != null) { flag3 = (Object)(object)val4.targetObject != (Object)null; } } bool flag4 = DrifterBossGrabPlugin.IsSwappingPassengers || flag3; if (flag && !flag4 && flag2) { Log.Debug("[TrySpawnJunk] targetObject is null/destroyed — spawning junk WITHOUT ExecuteBody() to avoid incrementing wrong object's invisibilityCount"); CharacterBody component = ((Component)val).GetComponent(); CharacterMotor val5 = ((component != null) ? component.characterMotor : null); if ((Object)(object)val5 != (Object)null) { ((BaseCharacterController)val5).Motor.ForceUnground(0.1f); val5.velocity = new Vector3(val5.velocity.x, Mathf.Max(val5.velocity.y, 8f), val5.velocity.z); } Vector3 val6 = (Object.op_Implicit((Object)(object)component) ? component.corePosition : ((Component)val).transform.position); object? obj2 = ReflectionCache.DrifterBagController.JunkController?.GetValue(val); JunkController val7 = (JunkController)((obj2 is JunkController) ? obj2 : null); if ((Object)(object)val7 != (Object)null) { val7.CallCmdGenerateJunkQuantity(val6, 4); } } else if (flag && flag4) { Log.Debug($"[TrySpawnJunk] SKIPPED junk spawn - null target detected during passenger swap (isSwapping={DrifterBossGrabPlugin.IsSwappingPassengers}, hasValidBaggedObjectState={flag3})"); } else if (flag && !flag2) { Log.Debug("[TrySpawnJunk] SKIPPED junk spawn - null target detected during grab operation (object was not successfully initialized via OnEnter)"); } else if ((Object)(object)val.baggedBody != (Object)null && instance != null && (Object)(object)val.baggedBody != (Object)(object)instance.targetObject) { Log.Debug("[TrySpawnJunk] >>> baggedBody changed (auto-promoted)! Manually spawning junk for " + BagHelpers.GetSafeName((Object?)(object)instance?.targetObject) + " to protect new passenger " + BagHelpers.GetSafeName((Object?)(object)val.baggedBody) + "."); SpecialObjectAttributes val8 = ((instance != null && (Object)(object)instance.targetObject != (Object)null) ? instance.targetObject.GetComponent() : null); CharacterBody component2 = ((Component)val).GetComponent(); Vector3 val9 = (Object.op_Implicit((Object)(object)component2) ? component2.corePosition : ((Component)val).transform.position); int num = 4; object? obj3 = ReflectionCache.DrifterBagController.JunkController?.GetValue(val); JunkController val10 = (JunkController)((obj3 is JunkController) ? obj3 : null); if ((Object)(object)val10 != (Object)null) { val10.CallCmdGenerateJunkQuantity(val9, num); } } else { Log.Debug("[TrySpawnJunk] >>> Calling ExecuteBody() to spawn junk for " + BagHelpers.GetSafeName((Object?)(object)instance?.targetObject)); val.ExecuteBody(); val.ResetBaggedObject(); } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TrySpawnJunk] >>> SKIPPED ExecuteBody - controller null: {(Object)(object)val == (Object)null}, server: {NetworkServer.active}"); } } catch (Exception ex2) { Log.Error(" [TrySpawnJunk] Error: " + ex2.Message); } } private static void CleanupSkillFromLocator(BaggedObject instance, GenericSkill skill) { //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)skill)) { return; } try { if (ReflectionCache.GenericSkill.SkillOverrides == null || _skillOverrideSourceField == null) { return; } IList list = (IList)ReflectionCache.GenericSkill.SkillOverrides.GetValue(skill); if (list == null) { return; } for (int num = list.Count - 1; num >= 0; num--) { object obj = list[num]; object obj2 = _skillOverrideSourceField?.GetValue(obj); if (obj2 == instance) { object? obj3 = _skillOverrideSkillDefField?.GetValue(obj); SkillDef val = (SkillDef)((obj3 is SkillDef) ? obj3 : null); SkillOverridePriority val2 = (SkillOverridePriority)(_skillOverridePriorityField?.GetValue(obj) ?? ((object)(SkillOverridePriority)4)); if ((Object)(object)val != (Object)null) { skill.UnsetSkillOverride((object)instance, val, val2); } } } } catch (Exception ex) { Log.Error("[CleanupSkillFromLocator] Failed to cleanup skill overrides: " + ex.Message); } } [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { object obj; if (__instance == null) { obj = null; } else { EntityStateMachine outer = ((EntityState)__instance).outer; obj = ((outer != null) ? ((Component)outer).GetComponent() : null); } DrifterBagController val = (DrifterBagController)obj; if ((Object)(object)val == (Object)null || (Object)(object)__instance?.targetObject == (Object)null) { return; } GameObject mainSeatObject = BagPatches.GetMainSeatObject(val); bool flag = (Object)(object)mainSeatObject != (Object)null && __instance.targetObject == mainSeatObject; bool flag2 = (Object)(object)BagHelpers.GetAdditionalSeat(val, __instance.targetObject) != (Object)null; bool flag3 = (Object)(object)val.vehicleSeat != (Object)null && val.vehicleSeat.hasPassenger && val.vehicleSeat.NetworkpassengerBodyObject == __instance.targetObject; bool flag4 = flag3 || flag2; bool flag5 = false; bool flag6 = (Object)(object)__instance.targetObject == (Object)null || !__instance.targetObject.activeInHierarchy; if ((Object)(object)__instance.targetObject != (Object)null && !flag6) { SpecialObjectAttributes component = __instance.targetObject.GetComponent(); if ((Object)(object)component != (Object)null && component.durability <= 0) { flag5 = true; } } try { if (!flag5 && (Object)(object)__instance.targetObject != (Object)null && ReflectionCache.BaggedObject.HoldsDeadBody != null) { flag5 = (bool)ReflectionCache.BaggedObject.HoldsDeadBody.Invoke(__instance, null); } } catch (Exception ex) { Log.Error("[BaggedObject_OnExit.Postfix] Failed to check HoldsDeadBody: " + ex.Message); } bool flag7 = flag5 || flag6; bool flag8 = (Object)(object)val != (Object)null && ((NetworkBehaviour)val).hasAuthority; if ((DrifterBossGrabPlugin.IsSwappingPassengers || CycleNetworkHandler.SuppressBroadcasts) && !flag7) { return; } if (flag && !flag2 && !flag4) { BottomlessBagNetworkController bottomlessBagNetworkController = null; if ((Object)(object)val != (Object)null) { bottomlessBagNetworkController = ((Component)val).GetComponent(); _ = (Object)(object)bottomlessBagNetworkController != (Object)null; } if ((Object)(object)bottomlessBagNetworkController != (Object)null && bottomlessBagNetworkController.selectedIndex < 0 && (Object)(object)val != (Object)null && (Object)(object)__instance.targetObject != (Object)null) { BagPassengerManager.RemoveBaggedObject(val, __instance.targetObject); } } else if (flag4 && (Object)(object)val != (Object)null) { BagCarouselUpdater.UpdateCarousel(val); } } public static void RegisterTrackedESM(EntityStateMachine esm, BaggedObjectTracker tracker) { if (!((Object)(object)esm == (Object)null) && !((Object)(object)tracker == (Object)null)) { _trackedESMs.Remove(esm); _trackedESMs.Add(esm, tracker); } } public static void UnregisterTrackedESM(EntityStateMachine esm) { if (!((Object)(object)esm == (Object)null)) { _trackedESMs.Remove(esm); } } } public static class BaggedObjectStateStorage { private static Dictionary> _perObjectStateStorage = new Dictionary>(); private static Dictionary> _temporaryPreservedStates = new Dictionary>(); public static void SaveObjectState(DrifterBagController controller, GameObject obj, BaggedObjectStateData state) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null || state == null) { return; } try { Log.Debug($"[SaveObjectState] Saving state for {((Object)obj).name}: baseMaxHealth={state.baseMaxHealth}, mass={state.baggedMass}"); if ((Object)(object)state.targetObject == (Object)null && state.baggedMass == 0f && state.baseMaxHealth == 0f) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[SaveObjectState] BLOCKED saving stub state for " + ((Object)obj).name + " - has default invalid values"); } return; } if (!_perObjectStateStorage.TryGetValue(controller, out Dictionary value)) { value = new Dictionary(); _perObjectStateStorage[controller] = value; } int instanceID = ((Object)obj).GetInstanceID(); if (value.ContainsKey(instanceID)) { Log.Debug("[SaveObjectState] Overwriting existing state for " + ((Object)obj).name); } value[instanceID] = state; } catch (Exception ex) { Log.Error(" [SaveObjectState] Error saving state: " + ex.Message); } } public static BaggedObjectStateData? LoadObjectState(DrifterBagController controller, GameObject obj) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return null; } try { if (_perObjectStateStorage.TryGetValue(controller, out Dictionary value)) { int instanceID = ((Object)obj).GetInstanceID(); if (value.TryGetValue(instanceID, out var value2)) { Log.Debug($"[LoadObjectState] Loaded state for {((Object)obj).name}: baseMaxHealth={value2.baseMaxHealth}, mass={value2.baggedMass}"); if ((Object)(object)value2.targetObject == (Object)null && value2.baggedMass == 0f && value2.baseMaxHealth == 0f) { Log.Error("[LoadObjectState] CRITICAL: Loaded STUB STATE for " + ((Object)obj).name + "! This will cause instant death!"); Log.Error(string.Format("[LoadObjectState] Stub state details: baseMaxHealth={0}, mass={1}, targetObject={2}", value2.baseMaxHealth, value2.baggedMass, (!Object.op_Implicit((Object)(object)value2.targetObject)) ? "null" : ((Object)value2.targetObject).name)); } return value2; } } Log.Debug("[LoadObjectState] No state found for " + ((Object)obj).name); return null; } catch (Exception ex) { Log.Error(" [LoadObjectState] Error loading state: " + ex.Message); return null; } } public static BaggedObjectStateData? FindStateForObject(GameObject obj) { if ((Object)(object)obj == (Object)null) { return null; } try { int instanceID = ((Object)obj).GetInstanceID(); foreach (Dictionary value2 in _perObjectStateStorage.Values) { if (value2.TryGetValue(instanceID, out var value)) { return value; } } return null; } catch (Exception ex) { Log.Error(" [FindStateForObject] Error finding state: " + ex.Message); return null; } } public static void CleanupObjectState(DrifterBagController controller, GameObject obj, bool preserveForThrow = false) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return; } if (preserveForThrow) { PreserveStateForThrow(controller, obj); return; } try { if (_perObjectStateStorage.TryGetValue(controller, out Dictionary value)) { int instanceID = ((Object)obj).GetInstanceID(); if (value.Remove(instanceID)) { Log.Debug($" [CleanupObjectState] Removed state for object {instanceID}"); } } } catch (Exception ex) { Log.Error(" [CleanupObjectState] Error cleaning up state: " + ex.Message); } } public static void PreserveStateForThrow(DrifterBagController controller, GameObject obj) { BaggedObjectStateData baggedObjectStateData = LoadObjectState(controller, obj); if (baggedObjectStateData != null) { if (!_temporaryPreservedStates.TryGetValue(controller, out Dictionary value)) { value = new Dictionary(); _temporaryPreservedStates[controller] = value; } int instanceID = ((Object)obj).GetInstanceID(); value[instanceID] = baggedObjectStateData; Log.Debug("[PreserveStateForThrow] Preserved state for " + ((Object)obj).name); } } public static void RestorePreservedState(DrifterBagController controller, GameObject obj) { int instanceID = ((Object)obj).GetInstanceID(); if (_temporaryPreservedStates.TryGetValue(controller, out Dictionary value) && value.TryGetValue(instanceID, out var value2)) { if (!_perObjectStateStorage.TryGetValue(controller, out Dictionary value3)) { value3 = new Dictionary(); _perObjectStateStorage[controller] = value3; } value3[instanceID] = value2; value.Remove(instanceID); Log.Debug("[RestorePreservedState] Restored preserved state for " + ((Object)obj).name); } } public static void ClearTemporaryPreservation(DrifterBagController controller, GameObject obj) { int instanceID = ((Object)obj).GetInstanceID(); if (_temporaryPreservedStates.TryGetValue(controller, out Dictionary value)) { value.Remove(instanceID); } } public static void ClearAllTemporaryPreservation(DrifterBagController controller) { if (_temporaryPreservedStates.TryGetValue(controller, out Dictionary value)) { value.Clear(); _temporaryPreservedStates.Remove(controller); } } } public static class BaggedObjectUIPatches { private static readonly FieldInfo _uiOverlayControllerField = ReflectionCache.BaggedObject.UIOverlayController; private static readonly FieldInfo _overriddenUtilityField = ReflectionCache.BaggedObject.OverriddenUtility; private static readonly FieldInfo _overriddenPrimaryField = ReflectionCache.BaggedObject.OverriddenPrimary; private static readonly FieldInfo _utilityOverrideField = ReflectionCache.BaggedObject.UtilityOverride; private static readonly FieldInfo _primaryOverrideField = ReflectionCache.BaggedObject.PrimaryOverride; private static readonly PropertyInfo _instancesListProperty = typeof(OverlayController).GetProperty("instancesList", BindingFlags.Instance | BindingFlags.Public); private static readonly MethodInfo _onUIOverlayInstanceRemoveMethod = ReflectionCache.Misc.OnUIOverlayInstanceRemove; public static void RefreshUIOverlayForMainSeat(DrifterBagController? bagController, GameObject? targetObject) { DrifterBagController val = bagController; if ((Object)(object)val == (Object)null && (Object)(object)targetObject != (Object)null) { foreach (DrifterBagController allController in BagPatches.GetAllControllers()) { GameObject mainSeatObject = BagPatches.GetMainSeatObject(allController); if ((Object)(object)mainSeatObject != (Object)null && ((Object)mainSeatObject).GetInstanceID() == ((Object)targetObject).GetInstanceID()) { val = allController; break; } } } if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)targetObject == (Object)null) { RemoveUIOverlayForNullState(val); return; } bool flag = false; VehicleSeat vehicleSeat = val.vehicleSeat; if ((Object)(object)vehicleSeat != (Object)null) { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject != (Object)null) { flag = targetObject == networkpassengerBodyObject; } } GameObject mainSeatObject2 = BagPatches.GetMainSeatObject(val); if (!flag && (Object)(object)mainSeatObject2 != (Object)null) { flag = targetObject == mainSeatObject2; } if (!((Object)(object)BagHelpers.GetAdditionalSeat(val, targetObject) != (Object)null)) { BaggedObjectPatches.SynchronizeBaggedObjectState(val, targetObject); } } public static void RemoveUIOverlay(GameObject targetObject, DrifterBagController? bagController = null) { //IL_00cd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)targetObject == (Object)null) { return; } if ((Object)(object)bagController == (Object)null) { foreach (DrifterBagController allController in BagPatches.GetAllControllers()) { if (BagPatches.GetMainSeatObject(allController) == targetObject) { bagController = allController; break; } } } BaggedObject val = null; if ((Object)(object)bagController != (Object)null) { val = BaggedObjectPatches.FindOrCreateBaggedObjectState(bagController, targetObject); } if (val == null) { return; } if ((Object)(object)bagController != (Object)null) { bool flag = false; VehicleSeat vehicleSeat = bagController.vehicleSeat; if ((Object)(object)vehicleSeat != (Object)null) { GameObject networkpassengerBodyObject = vehicleSeat.NetworkpassengerBodyObject; if ((Object)(object)networkpassengerBodyObject != (Object)null) { flag = targetObject == networkpassengerBodyObject; } } GameObject mainSeatObject = BagPatches.GetMainSeatObject(bagController); bool flag2 = (Object)(object)mainSeatObject != (Object)null && targetObject == mainSeatObject; if (flag || flag2) { return; } } OverlayController val2 = ((val == null) ? ((OverlayController)null) : ((OverlayController)_uiOverlayControllerField.GetValue(val))); if (val2 != null) { HudOverlayManager.RemoveOverlay(val2); _uiOverlayControllerField.SetValue(val, null); } } public static void RemoveUIOverlayForNullState(DrifterBagController bagController) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Expected O, but got Unknown //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Expected O, but got Unknown //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_01b0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)bagController == (Object)null) { return; } BaggedObject val = null; EntityStateMachine[] componentsInChildren = ((Component)bagController).GetComponentsInChildren(true); EntityStateMachine[] array = componentsInChildren; foreach (EntityStateMachine val2 in array) { if (val2.state != null && ((object)val2.state).GetType() == typeof(BaggedObject)) { val = (BaggedObject)val2.state; break; } } if (val == null) { EntityStateMachine[] array2 = componentsInChildren; foreach (EntityStateMachine val3 in array2) { if (val3.state != null && ((object)val3.state).GetType() == typeof(BaggedObject)) { val = (BaggedObject)val3.state; break; } } } if (val == null) { return; } if (val != null) { GenericSkill val4 = (GenericSkill)_overriddenUtilityField.GetValue(val); if ((Object)(object)val4 != (Object)null) { SkillDef val5 = (SkillDef)_utilityOverrideField.GetValue(val); if ((Object)(object)val5 != (Object)null) { val4.UnsetSkillOverride((object)val, val5, (SkillOverridePriority)4); } _overriddenUtilityField.SetValue(val, null); } GenericSkill val6 = (GenericSkill)_overriddenPrimaryField.GetValue(val); if ((Object)(object)val6 != (Object)null) { SkillDef val7 = (SkillDef)_primaryOverrideField.GetValue(val); if ((Object)(object)val7 != (Object)null) { val6.UnsetSkillOverride((object)val, val7, (SkillOverridePriority)4); } _overriddenPrimaryField.SetValue(val, null); } } bool flag = (Object)(object)BagPatches.GetMainSeatObject(bagController) != (Object)null; bool flag2 = false; if ((Object)(object)bagController.vehicleSeat != (Object)null && bagController.vehicleSeat.hasPassenger) { flag2 = true; } if (flag || flag2) { return; } OverlayController val8 = ((!(_uiOverlayControllerField != null)) ? ((OverlayController)null) : ((OverlayController)_uiOverlayControllerField.GetValue(val))); if (val8 == null) { return; } try { MethodInfo onUIOverlayInstanceRemoveMethod = _onUIOverlayInstanceRemoveMethod; if (onUIOverlayInstanceRemoveMethod != null && _instancesListProperty != null) { try { IReadOnlyList readOnlyList = (IReadOnlyList)_instancesListProperty.GetValue(val8); if (readOnlyList != null) { foreach (GameObject item in readOnlyList) { if ((Object)(object)item != (Object)null) { onUIOverlayInstanceRemoveMethod.Invoke(val, new object[2] { val8, item }); } } } } catch (Exception ex) { Log.Error("[RemoveUIOverlayForNullState] Failed to iterate overlay instances: " + ex.Message); } } HudOverlayManager.RemoveOverlay(val8); _uiOverlayControllerField?.SetValue(val, null); } catch (Exception ex2) { Log.Debug(" [RemoveUIOverlayForNullState] Exception removing overlay: " + ex2.Message); } } } public static class GrabbableObjectPatches { private static class ComponentPool { private const int MaxPoolSize = 25; private static readonly Stack> _rendererLists = new Stack>(); private static readonly Stack> _colliderLists = new Stack>(); private static readonly Stack> _lightLists = new Stack>(); private static readonly Stack> _behaviorLists = new Stack>(); [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List RentRendererList(int capacity = 16) { if (_rendererLists.Count > 0) { List list = _rendererLists.Pop(); list.Clear(); if (list.Capacity < capacity) { list.Capacity = capacity; } return list; } return new List(capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnRendererList(List list) { if (list != null && _rendererLists.Count < 25) { _rendererLists.Push(list); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List RentColliderList(int capacity = 16) { if (_colliderLists.Count > 0) { List list = _colliderLists.Pop(); list.Clear(); if (list.Capacity < capacity) { list.Capacity = capacity; } return list; } return new List(capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnColliderList(List list) { if (list != null && _colliderLists.Count < 25) { _colliderLists.Push(list); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List RentLightList(int capacity = 8) { if (_lightLists.Count > 0) { List list = _lightLists.Pop(); list.Clear(); if (list.Capacity < capacity) { list.Capacity = capacity; } return list; } return new List(capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnLightList(List list) { if (list != null && _lightLists.Count < 25) { _lightLists.Push(list); } } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static List RentBehaviorList(int capacity = 8) { if (_behaviorLists.Count > 0) { List list = _behaviorLists.Pop(); list.Clear(); if (list.Capacity < capacity) { list.Capacity = capacity; } return list; } return new List(capacity); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void ReturnBehaviorList(List list) { if (list != null && _behaviorLists.Count < 25) { _behaviorLists.Push(list); } } } [HarmonyPatch(typeof(DirectorCore), "TrySpawnObject")] public class DirectorCore_TrySpawnObject_Patch { [HarmonyPostfix] public static void Postfix(GameObject __result) { if (Object.op_Implicit((Object)(object)__result)) { AddSpecialObjectAttributesToGrabbableObject(__result); } } } [HarmonyPatch(typeof(SpecialObjectAttributes), "Start")] public class SpecialObjectAttributes_Start_Patch { [HarmonyPostfix] public static void Postfix(SpecialObjectAttributes __instance) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance.portraitIcon == (Object)null) { string lowerCaseName = ((Object)((Component)__instance).gameObject).name.ToLowerInvariant(); string iconPathForObject = GetIconPathForObject(lowerCaseName); if (!string.IsNullOrEmpty(iconPathForObject)) { __instance.portraitIcon = Addressables.LoadAssetAsync((object)iconPathForObject).WaitForCompletion(); } } } } [HarmonyPatch(typeof(BaseCaptainSupplyDropState), "OnEnter")] public class BaseCaptainSupplyDropState_OnEnter_Patch { [HarmonyPostfix] public static void Postfix(BaseCaptainSupplyDropState __instance) { AddSpecialObjectAttributesToGrabbableObject(((Component)((EntityState)__instance).outer).gameObject); } } [CompilerGenerated] private sealed class d__8 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public GameObject survivorPod; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__8(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(5f); <>1__state = 1; return true; case 1: { <>1__state = -1; EntityStateMachine val = default(EntityStateMachine); if ((Object)(object)survivorPod != (Object)null && survivorPod.TryGetComponent(ref val) && (val.state is Landed || val.state is PreRelease || val.state is Release || val.state is ReleaseFinished)) { AddSpecialObjectAttributesToGrabbableObject(survivorPod); } 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 d__11 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; private int 5__2; private int 5__3; private GameObject[] <>7__wrap3; private int <>7__wrap4; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__11(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>7__wrap3 = null; <>1__state = -2; } private bool MoveNext() { int num = <>1__state; if (num != 0) { if (num != 1) { return false; } <>1__state = -1; goto IL_00d3; } <>1__state = -1; GameObject[] array = Object.FindObjectsByType((FindObjectsSortMode)0); 5__2 = 0; int num2 = array.Length; 5__3 = 100; <>7__wrap3 = array; <>7__wrap4 = 0; goto IL_00e1; IL_00d3: <>7__wrap4++; goto IL_00e1; IL_00e1: if (<>7__wrap4 < <>7__wrap3.Length) { GameObject val = <>7__wrap3[<>7__wrap4]; if (!((Object)(object)val == (Object)null)) { try { AddSpecialObjectAttributesToGrabbableObject(val); } catch (Exception ex) { Log.Error("[GrabPatch] Failed to add attributes to " + ((!Object.op_Implicit((Object)(object)val)) ? "null" : ((Object)val).name) + ": " + ex.Message); } 5__2++; if (5__2 % 5__3 == 0) { <>2__current = null; <>1__state = 1; return true; } } goto IL_00d3; } <>7__wrap3 = 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 readonly Type SceneReductionType = typeof(SceneReduction); private static readonly Type EntityStateMachineType = typeof(EntityStateMachine); private static readonly Type NetworkIdentityType = typeof(NetworkIdentity); private static readonly Type SpecialObjectAttributesType = typeof(SpecialObjectAttributes); private static readonly Regex NumericSuffixPattern = new Regex("\\s*\\(\\d+\\)$", RegexOptions.Compiled); private static GameObject FindEntityStateMachineTarget(GameObject obj) { if (((Object)obj).name.Contains("_LOD")) { Transform parent = obj.transform.parent; SceneReduction val = default(SceneReduction); while ((Object)(object)parent != (Object)null) { if (((Component)parent).gameObject.TryGetComponent(ref val)) { return ((Component)parent).gameObject; } parent = parent.parent; } } EntityStateMachine val2 = default(EntityStateMachine); if (obj.TryGetComponent(ref val2)) { return obj; } Transform parent2 = obj.transform.parent; while ((Object)(object)parent2 != (Object)null) { if (((Component)parent2).gameObject.TryGetComponent(ref val2) && PluginConfig.IsGrabbable(((Component)parent2).gameObject)) { return ((Component)parent2).gameObject; } parent2 = parent2.parent; } if (!PluginConfig.IsGrabbable(((Component)obj.transform.root).gameObject)) { return obj; } return ((Component)obj.transform.root).gameObject; } public static void AddSpecialObjectAttributesToGrabbableObject(GameObject obj) { //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return; } string text = ((Object)obj).name; string text2 = text.ToLowerInvariant(); if (!PluginConfig.IsGrabbable(obj)) { return; } Log.Debug("[GrabbableObjectPatches] AddSpecialObjectAttributesToGrabbableObject called for " + text); EntityStateMachine val = default(EntityStateMachine); if (text2.Contains("survivorpod") && obj.TryGetComponent(ref val) && val.state is Descent) { DrifterBossGrabPlugin? instance = DrifterBossGrabPlugin.Instance; if (instance != null) { ((MonoBehaviour)instance).StartCoroutine(DelayedSurvivorPodSetup(obj)); } return; } if (string.IsNullOrEmpty(text)) { string text4 = (((Object)obj).name = "GrabbableObject_" + ((Object)obj).GetInstanceID()); text = text4; text2 = text.ToLowerInvariant(); } GameObject val2 = FindEntityStateMachineTarget(obj); EntityStateMachine val3 = default(EntityStateMachine); if (!val2.TryGetComponent(ref val3)) { val3 = val2.AddComponent(); val3.customName = "Body"; val3.initialStateType = new SerializableEntityStateType(typeof(Uninitialized)); val3.mainStateType = new SerializableEntityStateType(typeof(Uninitialized)); val3.networkIndex = -1; val3.AllowStartWithoutNetworker = true; if (val3.state is Uninitialized) { val3.SetState(EntityStateCatalog.InstantiateState(ref val3.initialStateType)); } } NetworkIdentity val4 = default(NetworkIdentity); if (!val2.TryGetComponent(ref val4)) { val4 = val2.AddComponent(); val4.serverOnly = false; val4.localPlayerAuthority = false; try { if (NetworkServer.active) { NetworkServer.Spawn(val2); } } catch (Exception ex) { Log.Error("[GrabPatch] Failed to spawn object " + text + " on network: " + ex.Message); } } SpecialObjectAttributes val5 = default(SpecialObjectAttributes); if (val2.TryGetComponent(ref val5)) { if (PluginConfig.IsGrabbable(obj)) { if (!val5.grabbable || string.IsNullOrEmpty(val5.breakoutStateMachineName)) { val5.grabbable = true; val5.breakoutStateMachineName = ""; val5.orientToFloor = true; } if (!val5.isVoid && text2.Contains("void")) { val5.isVoid = true; } Light[] componentsInChildren = obj.GetComponentsInChildren(false); Light[] array = componentsInChildren; foreach (Light item in array) { if (!val5.lightsToDisable.Contains(item)) { val5.lightsToDisable.Add(item); } } PickupDisplay[] componentsInChildren2 = obj.GetComponentsInChildren(false); PickupDisplay[] array2 = componentsInChildren2; foreach (PickupDisplay item2 in array2) { if (!val5.pickupDisplaysToDisable.Contains(item2)) { val5.pickupDisplaysToDisable.Add(item2); } } } else { val5.grabbable = false; } return; } SpecialObjectAttributes val6 = val2.AddComponent(); (float massOverride, int maxDurability) tuple = CalculateScaledAttributes(obj, text); float item3 = tuple.massOverride; int item4 = tuple.maxDurability; val6.grabbable = true; val6.massOverride = item3; val6.maxDurability = item4; val6.durability = item4; val6.hullClassification = (HullClassification)0; val6.breakoutStateMachineName = ""; val6.orientToFloor = true; string input = text.Replace("(Clone)", ""); input = NumericSuffixPattern.Replace(input, ""); val6.bestName = input; val6.isVoid = text2.Contains("void"); val6.renderersToDisable = new List(16); val6.behavioursToDisable = new List(8); val6.collisionToDisable = new List(16); val6.childObjectsToDisable = new List(4); val6.pickupDisplaysToDisable = new List(2); val6.lightsToDisable = new List(4); val6.objectsToDetach = new List(2); val6.childSpecialObjectAttributes = new List(2); val6.skillHighlightRenderers = new List(4); val6.soundEventsToStop = new List(2); val6.soundEventsToPlay = new List(2); List list = ComponentPool.RentRendererList(); obj.GetComponentsInChildren(false, list); foreach (Renderer item6 in list) { val6.renderersToDisable.Add(item6); } ComponentPool.ReturnRendererList(list); List list2 = ComponentPool.RentColliderList(); obj.GetComponentsInChildren(false, list2); foreach (Collider item7 in list2) { val6.collisionToDisable.Add(((Component)item7).gameObject); } ComponentPool.ReturnColliderList(list2); List list3 = ComponentPool.RentLightList(); obj.GetComponentsInChildren(false, list3); foreach (Light item8 in list3) { val6.lightsToDisable.Add(item8); } ComponentPool.ReturnLightList(list3); PickupDisplay[] componentsInChildren3 = obj.GetComponentsInChildren(false); PickupDisplay[] array3 = componentsInChildren3; foreach (PickupDisplay item5 in array3) { val6.pickupDisplaysToDisable.Add(item5); } } [IteratorStateMachine(typeof(d__8))] private static IEnumerator DelayedSurvivorPodSetup(GameObject survivorPod) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__8(0) { survivorPod = survivorPod }; } public static void AddSpecialObjectAttributesToProjectile(GameObject obj) { //IL_00fd: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return; } string text = ((Object)obj).name; Log.Debug("[GrabbableObjectPatches] AddSpecialObjectAttributesToProjectile called for " + text); string text2 = text.ToLowerInvariant(); if (string.IsNullOrEmpty(text)) { string text4 = (((Object)obj).name = "Projectile_" + ((Object)obj).GetInstanceID()); text = text4; text2 = text.ToLowerInvariant(); } NetworkIdentity val = default(NetworkIdentity); if (!obj.TryGetComponent(ref val)) { val = obj.AddComponent(); val.serverOnly = false; val.localPlayerAuthority = false; try { if (NetworkServer.active) { NetworkServer.Spawn(obj); } } catch (Exception ex) { Log.Error("[GrabPatch] Failed to spawn projectile " + text + " on network: " + ex.Message); } } SpecialObjectAttributes val2 = default(SpecialObjectAttributes); if (!obj.TryGetComponent(ref val2)) { val2 = obj.AddComponent(); (float massOverride, int maxDurability) tuple = CalculateScaledAttributes(obj, text); float item = tuple.massOverride; int item2 = tuple.maxDurability; val2.grabbable = true; val2.massOverride = item; val2.maxDurability = item2; val2.durability = item2; val2.hullClassification = (HullClassification)0; val2.breakoutStateMachineName = ""; val2.orientToFloor = true; string input = text.Replace("(Clone)", ""); input = NumericSuffixPattern.Replace(input, ""); val2.bestName = input; val2.isVoid = text2.Contains("void"); } else { if (!val2.grabbable) { val2.grabbable = true; } if (string.IsNullOrEmpty(val2.breakoutStateMachineName)) { val2.breakoutStateMachineName = ""; } val2.orientToFloor = true; } val2.renderersToDisable = new List(16); val2.behavioursToDisable = new List(8); val2.collisionToDisable = new List(16); val2.childObjectsToDisable = new List(4); val2.pickupDisplaysToDisable = new List(2); val2.lightsToDisable = new List(4); val2.objectsToDetach = new List(2); val2.childSpecialObjectAttributes = new List(2); val2.skillHighlightRenderers = new List(4); val2.soundEventsToStop = new List(2); val2.soundEventsToPlay = new List(2); List list = ComponentPool.RentRendererList(); obj.GetComponentsInChildren(false, list); foreach (Renderer item6 in list) { val2.renderersToDisable.Add(item6); } ComponentPool.ReturnRendererList(list); List list2 = ComponentPool.RentColliderList(); obj.GetComponentsInChildren(false, list2); foreach (Collider item7 in list2) { val2.collisionToDisable.Add(((Component)item7).gameObject); } ComponentPool.ReturnColliderList(list2); List list3 = ComponentPool.RentLightList(); obj.GetComponentsInChildren(false, list3); foreach (Light item8 in list3) { val2.lightsToDisable.Add(item8); } ComponentPool.ReturnLightList(list3); PickupDisplay[] componentsInChildren = obj.GetComponentsInChildren(false); PickupDisplay[] array = componentsInChildren; foreach (PickupDisplay item3 in array) { val2.pickupDisplaysToDisable.Add(item3); } ProjectileStickOnImpact[] componentsInChildren2 = obj.GetComponentsInChildren(true); ProjectileStickOnImpact[] array2 = componentsInChildren2; foreach (ProjectileStickOnImpact item4 in array2) { val2.behavioursToDisable.Add((MonoBehaviour)(object)item4); } ProjectileFuse[] componentsInChildren3 = obj.GetComponentsInChildren(true); ProjectileFuse[] array3 = componentsInChildren3; foreach (ProjectileFuse item5 in array3) { val2.behavioursToDisable.Add((MonoBehaviour)(object)item5); } } public static void EnsureAllGrabbableObjectsHaveSpecialObjectAttributes() { if (Object.op_Implicit((Object)(object)DrifterBossGrabPlugin.Instance)) { ((MonoBehaviour)DrifterBossGrabPlugin.Instance).StartCoroutine(EnsureAllGrabbableObjectsHaveSpecialObjectAttributesAsync()); return; } GameObject[] array = Object.FindObjectsByType((FindObjectsSortMode)0); foreach (GameObject obj in array) { AddSpecialObjectAttributesToGrabbableObject(obj); } } [IteratorStateMachine(typeof(d__11))] public static IEnumerator EnsureAllGrabbableObjectsHaveSpecialObjectAttributesAsync() { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__11(0); } private static float CalculateObjectSizeMetric(GameObject obj) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)obj == (Object)null) { return 1f; } float num = 0f; Collider[] componentsInChildren = obj.GetComponentsInChildren(false); Collider[] array = componentsInChildren; foreach (Collider val in array) { if ((Object)(object)val == (Object)null || !val.enabled) { continue; } BoxCollider val2 = (BoxCollider)(object)((val is BoxCollider) ? val : null); if (val2 != null) { Vector3 size = val2.size; num += size.x * size.y * size.z; continue; } SphereCollider val3 = (SphereCollider)(object)((val is SphereCollider) ? val : null); if (val3 != null) { float radius = val3.radius; num += 4.1887903f * radius * radius * radius; continue; } CapsuleCollider val4 = (CapsuleCollider)(object)((val is CapsuleCollider) ? val : null); if (val4 != null) { float radius2 = val4.radius; float height = val4.height; num += MathF.PI * radius2 * radius2 * height; continue; } MeshCollider val5 = (MeshCollider)(object)((val is MeshCollider) ? val : null); if (val5 != null) { Bounds bounds = ((Collider)val5).bounds; num += ((Bounds)(ref bounds)).size.x * ((Bounds)(ref bounds)).size.y * ((Bounds)(ref bounds)).size.z; } } return Mathf.Max(num, 0.1f); } private static (float massOverride, int maxDurability) CalculateScaledAttributes(GameObject obj, string objName) { float num = CalculateObjectSizeMetric(obj); float num2 = Mathf.Clamp(num / 10f, 0.5f, 5f); float num3 = 100f * num2; int num4 = Mathf.RoundToInt(8f * num2); num3 = Mathf.Max(num3, 25f); num4 = Mathf.Max(num4, 3); return (num3, num4); } public static string GetIconPathForObject(string lowerCaseName) { if (lowerCaseName.Contains("lunar") || lowerCaseName.Contains("newt") || lowerCaseName.Contains("portalshop") || lowerCaseName.Contains("portalms")) { return "RoR2/Base/LunarIcon_1.png"; } if (lowerCaseName.Contains("void")) { return "RoR2/Base/VoidIcon_2.png"; } if (lowerCaseName.Contains("halcyonite") || lowerCaseName.Contains("colossus")) { return "RoR2/Base/texColossusExpansionIcon2White.png"; } if (lowerCaseName.Contains("portalgoldshores")) { return "RoR2/Base/TitanGoldDuringTP/texGoldHeartIcon.png"; } if (lowerCaseName.Contains("teleporter") || lowerCaseName.Contains("portal")) { return "RoR2/Base/Common/MiscIcons/texTeleporterIconOutlined.png"; } if (lowerCaseName.Contains("shrine") || lowerCaseName.Contains("statue")) { return "RoR2/Base/ShrineIcon.png"; } if (lowerCaseName.Contains("pillar")) { return "RoR2/Base/PillarIcon.png"; } if (lowerCaseName.Contains("vending")) { return "RoR2/DLC1/VendingMachine/texVendingMachineBody.png"; } if (lowerCaseName.Contains("pot")) { return "RoR2/Base/ExplosivePotDestructible/texExplosivePotDestructibleBody.png"; } if (lowerCaseName.Contains("ship") || lowerCaseName.Contains("survivor")) { return "RoR2/Base/Common/MiscIcons/texRescueshipIcon.png"; } if (lowerCaseName.Contains("rock") || lowerCaseName.Contains("chunk") || lowerCaseName.Contains("boulder")) { return "RoR2/Base/skymeadow/texSMMaulingRock.png"; } return "RoR2/Base/Common/MiscIcons/texMysteryIcon.png"; } } public static class RepossessExitPatches { [HarmonyPatch(typeof(RepossessExit), "OnEnter")] public class RepossessExit_OnEnter_Patch { private static GameObject? originalChosenTarget; [HarmonyPrefix] public static bool Prefix(RepossessExit __instance) { object? obj = _chosenTargetField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { GameObject originalTarget = GetOriginalTarget(__instance); if (!((Object)(object)originalTarget != (Object)null)) { Log.Warning("[RepossessExit Prefix] chosenTarget is null from " + ((object)__instance).GetType().Name); originalChosenTarget = null; return true; } val = originalTarget; _chosenTargetField?.SetValue(__instance, val); Log.Debug("[RepossessExit Prefix] Recovered chosenTarget from deserialization: " + ((Object)originalTarget).name); } originalChosenTarget = val; StoreOriginalTarget(__instance, val); if (PluginConfig.Instance.EnableDebugLogs.Value) { EntityStateMachine outer = ((EntityState)__instance).outer; DrifterBagController val2 = ((outer != null) ? ((Component)outer).GetComponent() : null); Log.Debug($" RepossessExit Prefix: originalChosenTarget = {originalChosenTarget}."); Log.Debug($"[RepossessExit Prefix] EnableBalance={PluginConfig.Instance.EnableBalance.Value}, NetworkServer.active={NetworkServer.active}, hasAuthority={((val2 != null) ? new bool?(((NetworkBehaviour)val2).hasAuthority) : null)}"); } return true; } [HarmonyPostfix] public static void Postfix(RepossessExit __instance) { //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.Instance.EnableBossGrabbing.Value && !PluginConfig.Instance.EnableNPCGrabbing.Value) { return; } object? obj = _chosenTargetField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null && (Object)(object)originalChosenTarget == (Object)null) { Log.Warning("[RepossessExit Postfix] chosenTarget is null from " + ((object)__instance).GetType().Name); return; } Log.Debug($" RepossessExit Postfix: chosenTarget = {val}, originalChosenTarget = {originalChosenTarget}."); if ((Object)(object)val == (Object)null && (Object)(object)originalChosenTarget != (Object)null && PluginConfig.IsGrabbable(originalChosenTarget)) { _chosenTargetField?.SetValue(__instance, originalChosenTarget); _activatedHitpauseField?.SetValue(__instance, true); val = originalChosenTarget; } else if ((Object)(object)val == (Object)null && (Object)(object)originalChosenTarget != (Object)null) { CharacterBody component = originalChosenTarget.GetComponent(); Log.Debug($" Checking body: {component}, ungrabbable: {Object.op_Implicit((Object)(object)component) && ((Enum)component.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288)}"); if (Object.op_Implicit((Object)(object)component)) { bool flag = component.isBoss || component.isChampion; bool isElite = component.isElite; bool flag2 = ((Enum)component.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288); bool flag3 = !flag && !flag2 && PluginConfig.Instance.EnableNPCGrabbing.Value; bool flag4 = (PluginConfig.Instance.EnableBossGrabbing.Value && flag) || (PluginConfig.Instance.EnableNPCGrabbing.Value && flag2) || flag3 || PluginConfig.Instance.EnableLockedObjectGrabbing.Value; bool flag5 = PluginConfig.IsBlacklisted(((Object)component).name); Log.Debug($" Body {((Object)component).name}: isBoss={flag}, isElite={isElite}, ungrabbable={flag2}, isStandardRejected={flag3}, canGrab={flag4}, isBlacklisted={flag5}"); if (flag4 && !flag5) { _chosenTargetField?.SetValue(__instance, originalChosenTarget); _activatedHitpauseField?.SetValue(__instance, true); val = originalChosenTarget; } } } if (!((Object)(object)originalChosenTarget != (Object)null) || NetworkServer.active || !NetworkClient.active) { return; } if (ProjectileRecoveryPatches.IsUndergoingThrowOperation(originalChosenTarget)) { Log.Warning("[RepossessExit Postfix] Blocking grab request for " + ((Object)originalChosenTarget).name + " - object is currently undergoing throw operation"); return; } EntityStateMachine outer = ((EntityState)__instance).outer; DrifterBagController val2 = ((outer != null) ? ((Component)outer).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { Log.Debug("[RepossessExit Postfix] Sending grab request to host for " + ((Object)originalChosenTarget).name); CycleNetworkHandler.SendGrabObjectRequest(val2, originalChosenTarget); } } } [HarmonyPatch(typeof(RepossessExit), "OnSerialize")] public class RepossessExit_OnSerialize_Patch { private static GameObject? _savedTarget; [HarmonyPrefix] public static void Prefix(RepossessExit __instance) { object? obj = _chosenTargetField?.GetValue(__instance); _savedTarget = (GameObject?)((obj is GameObject) ? obj : null); if ((Object)(object)_savedTarget == (Object)null) { GameObject originalTarget = GetOriginalTarget(__instance); if ((Object)(object)originalTarget != (Object)null) { _chosenTargetField?.SetValue(__instance, originalTarget); Log.Debug("[RepossessExit OnSerialize] Restored chosenTarget for serialization: " + ((Object)originalTarget).name); } } } [HarmonyPostfix] public static void Postfix(RepossessExit __instance) { if ((Object)(object)_savedTarget == (Object)null) { _chosenTargetField?.SetValue(__instance, null); } _savedTarget = null; } } [HarmonyPatch(typeof(RepossessExit), "OnDeserialize")] public class RepossessExit_OnDeserialize_Patch { [HarmonyPostfix] public static void Postfix(RepossessExit __instance, NetworkReader reader) { object? obj = _chosenTargetField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val != (Object)null) { StoreOriginalTarget(__instance, val); Log.Debug("[RepossessExit OnDeserialize] Received chosenTarget: " + ((Object)val).name); } } } [HarmonyPatch(typeof(RepossessExit), "OnExit")] public class RepossessExit_OnExit_Patch { [HarmonyPostfix] public static void Postfix(RepossessExit __instance) { if (!PluginConfig.Instance.EnableSuccessiveGrabStockRefresh.Value) { return; } object? obj = _chosenTargetField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuccessiveGrab] Skipping stock refresh - chosenTarget is null (grab unsuccessful)"); } return; } EntityStateMachine outer = ((EntityState)__instance).outer; DrifterBagController val2 = ((outer != null) ? ((Component)outer).GetComponent() : null); if ((Object)(object)val2 == (Object)null) { return; } CharacterBody component = ((Component)val2).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.skillLocator == (Object)null) { return; } GenericSkill utility = component.skillLocator.utility; if ((Object)(object)utility == (Object)null) { return; } if (utility.stock == 0 && BagCapacityCalculator.HasRoomForGrab(val2)) { if (PluginConfig.Instance.PrioritizeMainSeat.Value) { EntityStateMachine[] components = ((Component)val2).GetComponents(); BaggedObject val3 = null; EntityStateMachine[] array = components; foreach (EntityStateMachine val4 in array) { if (val4.customName == "Bag") { EntityState state = val4.state; BaggedObject val5 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val5 != null) { val3 = val5; break; } } } if (val3 != null) { object? obj2 = ReflectionCache.BaggedObject.OverriddenUtility?.GetValue(val3); GenericSkill val6 = (GenericSkill)((obj2 is GenericSkill) ? obj2 : null); object? obj3 = ReflectionCache.BaggedObject.UtilityOverride?.GetValue(val3); SkillDef val7 = (SkillDef)((obj3 is SkillDef) ? obj3 : null); if ((Object)(object)val6 != (Object)null && (Object)(object)val7 != (Object)null) { val6.UnsetSkillOverride((object)val3, val7, (SkillOverridePriority)4); ReflectionCache.BaggedObject.OverriddenUtility?.SetValue(val3, null); utility.stock = 1; val3.TryOverrideUtility(utility); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuccessiveGrab] Refreshed stock from 0 to 1 after successful grab (with PrioritizeMainSeat - override temporarily removed)"); } } else { utility.stock = 1; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuccessiveGrab] Refreshed stock from 0 to 1 after successful grab (PrioritizeMainSeat enabled but no override found)"); } } } else { utility.stock = 1; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuccessiveGrab] Refreshed stock from 0 to 1 after successful grab (PrioritizeMainSeat enabled but no BaggedObject state found)"); } } } else { utility.stock = 1; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuccessiveGrab] Refreshed stock from 0 to 1 after successful grab (PrioritizeMainSeat disabled)"); } } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[SuccessiveGrab] Skipping stock refresh - stock is {utility.stock} (not 0)"); } } } [HarmonyPatch(typeof(BaggedObject), "OnEnter")] public class BaggedObject_OnEnter_Patch { [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { try { object? obj = _targetObjectField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); _ = (Object)(object)val == (Object)null; } catch (Exception ex) { Log.Error(" Error in BaggedObject.OnEnter debug logging: " + ex.Message); } } } [HarmonyPatch(typeof(BaggedObject), "OnExit")] public class BaggedObject_OnExit_Patch { [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { try { object? obj = _targetObjectField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { return; } EntityStateMachine outer = ((EntityState)__instance).outer; DrifterBagController val2 = ((outer != null) ? ((Component)outer).GetComponent() : null); if ((Object)(object)val2 != (Object)null) { BagState state = BagPatches.GetState(val2); VehicleSeat vehicleSeat = val2.vehicleSeat; bool flag = (Object)(object)((vehicleSeat != null) ? vehicleSeat.NetworkpassengerBodyObject : null) == (Object)(object)val; bool flag2 = state?.AdditionalSeats.ContainsKey(val) ?? false; if (flag || flag2) { Log.Debug($" [BaggedObject.OnExit] Skipping restoration for {((Object)val).name} - still in bag (Main={flag}, Additional={flag2})"); } } } catch (Exception ex) { Log.Error(" Error in BaggedObject.OnExit restoration: " + ex.Message); } } } private static readonly FieldInfo _chosenTargetField = ReflectionCache.RepossessExit.ChosenTarget; private static readonly FieldInfo _activatedHitpauseField = ReflectionCache.RepossessExit.ActivatedHitpause; private static readonly FieldInfo _targetObjectField = ReflectionCache.BaggedObject.TargetObject; private static readonly ConditionalWeakTable> _originalTargets = new ConditionalWeakTable>(); public static void StoreOriginalTarget(RepossessExit instance, GameObject? target) { if (_originalTargets.TryGetValue(instance, out StrongBox value)) { value.Value = target; } else { _originalTargets.Add(instance, new StrongBox(target)); } } public static GameObject? GetOriginalTarget(RepossessExit instance) { if (_originalTargets.TryGetValue(instance, out StrongBox value)) { return value.Value; } return null; } } public static class RepossessPatches { [HarmonyPatch(typeof(DrifterBagController), "CalculateBaggedObjectMass")] public class DrifterBagController_CalculateBaggedObjectMass_Patch { [HarmonyPrefix] public static bool Prefix(DrifterBagController __instance, GameObject targetObject, ref float __result) { if (!Object.op_Implicit((Object)(object)targetObject)) { __result = 0f; return false; } float num = 0f; CharacterBody val = default(CharacterBody); if (targetObject.TryGetComponent(ref val)) { GameObject val2 = null; val2 = BodyCatalog.FindBodyPrefab(val.baseNameToken); if ((Object)(object)val2 == (Object)null) { val2 = targetObject; } IPhysMotor val3 = default(IPhysMotor); if (val2.TryGetComponent(ref val3)) { num = val3.mass; } } IPhysMotor val4 = default(IPhysMotor); if (num <= 0f && targetObject.TryGetComponent(ref val4)) { num = val4.mass; } SpecialObjectAttributes val5 = default(SpecialObjectAttributes); if (num <= 0f && targetObject.TryGetComponent(ref val5)) { num = val5.massOverride; } if (num <= 0f) { num = 1f; } if (PluginConfig.Instance.EnableBalance.Value) { num = CharacterFlagMassBonus.ApplyFlagBonus(targetObject, num); } if (!PluginConfig.Instance.IsMassCapInfinite) { float num2 = float.MaxValue; if (float.TryParse(PluginConfig.Instance.MassCap.Value, out var result)) { num2 = result; } if (PluginConfig.Instance.EnableBalance.Value) { float num3 = CapacityScalingSystem.CalculateMassCapacity(__instance); if (num3 != float.MaxValue) { num2 = ((num3 > num2) ? num3 : num2); } } __result = Mathf.Clamp(num, 0f, num2); } else { __result = Mathf.Max(num, 0f); } return false; } } [HarmonyPatch(typeof(DrifterBagController), "RecalculateBaggedObjectMass")] public class DrifterBagController_RecalculateBaggedObjectMass_Patch { [HarmonyPrefix] public static bool Prefix(DrifterBagController __instance) { float num = 0f; List baggedObjects = BagPatches.GetState(__instance).BaggedObjects; if (baggedObjects != null) { foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(item)) { num += __instance.CalculateBaggedObjectMass(item); } } } num = Mathf.Max(num, 0f); ReflectionCache.DrifterBagController.BaggedMass.SetValue(__instance, num); EntityStateMachine[] components = ((Component)__instance).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (val.customName == "Bag") { EntityState state = val.state; BaggedObject val2 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val2 != null) { BaggedObjectPatches.UpdateBagScale(val2, num); break; } } } return false; } } [HarmonyPatch(typeof(DrifterBagController), "OnSyncBaggedObject")] public class DrifterBagController_OnSyncBaggedObject_Patch { [HarmonyPostfix] public static void Postfix(DrifterBagController __instance) { BagPassengerManager.ForceRecalculateMass(__instance); if (NetworkServer.active || !((Object)(object)__instance.baggedObject != (Object)null)) { return; } EntityStateMachine[] components = ((Component)__instance).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { if (!(val.customName == "Bag")) { continue; } EntityState state = val.state; BaggedObject val2 = (BaggedObject)(object)((state is BaggedObject) ? state : null); if (val2 != null) { if ((Object)(object)val2.targetObject == (Object)null) { val2.targetObject = __instance.baggedObject; BaggedObjectPatches.UpdateTargetFields(val2); Log.Debug("[OnSyncBaggedObject] Active Recovery: Pushed " + ((Object)__instance.baggedObject).name + " into BaggedObject state."); } break; } } } } [HarmonyPatch(typeof(DrifterBagController), "Awake")] public class DrifterBagController_Awake_Patch { [HarmonyPostfix] public static void Postfix(DrifterBagController __instance) { if (PluginConfig.Instance.EnableBalance.Value) { __instance.maxSmacks = PluginConfig.Instance.MaxSmacks.Value; } if ((Object)(object)((Component)__instance).GetComponent() == (Object)null) { ((Component)__instance).gameObject.AddComponent(); } } } [HarmonyPatch(typeof(BaggedObject), "OnEnter")] public class BaggedObject_OnEnter_ExtendBreakoutTime { [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) GameObject val = ((!(ReflectionCache.BaggedObject.TargetObject != null)) ? ((GameObject)null) : ((GameObject)ReflectionCache.BaggedObject.TargetObject.GetValue(__instance))); if ((Object)(object)val == (Object)null) { return; } if (PluginConfig.Instance.EnableBalance.Value && ReflectionCache.BaggedObject.BreakoutTime != null) { float num = (float)ReflectionCache.BaggedObject.BreakoutTime.GetValue(__instance); ReflectionCache.BaggedObject.BreakoutTime.SetValue(__instance, num * PluginConfig.Instance.BreakoutTimeMultiplier.Value); } if ((Object)(object)val != (Object)null && NetworkServer.active) { NetworkIdentity component = val.GetComponent(); if ((Object)(object)component != (Object)null) { NetworkServer.Spawn(val); } } bool flag = PersistenceObjectManager.IsObjectPersisted(val); if (NetworkServer.active && PluginConfig.Instance.EnableObjectPersistence.Value && !flag) { PersistenceNetworkHandler.SendBaggedObjectsPersistenceMessage(new List { val }); } DrifterBagController component2 = ((Component)((EntityState)__instance).outer).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)val != (Object)null) { BaggedObjectPatches.RefreshUIOverlayForMainSeat(component2, val); } } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] public class SpecialObjectAttributes_get_isTargetable { [HarmonyPrefix] public static bool Prefix(SpecialObjectAttributes __instance) { if (!DrifterBossGrabPlugin.IsDrifterPresent) { return true; } __instance.childSpecialObjectAttributes.RemoveAll((SpecialObjectAttributes s) => (Object)(object)s == (Object)null); __instance.renderersToDisable.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); __instance.behavioursToDisable.RemoveAll((MonoBehaviour b) => (Object)(object)b == (Object)null); __instance.childObjectsToDisable.RemoveAll((GameObject c) => (Object)(object)c == (Object)null); __instance.pickupDisplaysToDisable.RemoveAll((PickupDisplay p) => (Object)(object)p == (Object)null); __instance.lightsToDisable.RemoveAll((Light l) => (Object)(object)l == (Object)null); __instance.objectsToDetach.RemoveAll((GameObject o) => (Object)(object)o == (Object)null); __instance.skillHighlightRenderers.RemoveAll((Renderer r) => (Object)(object)r == (Object)null); return true; } [HarmonyPostfix] public static void Postfix(SpecialObjectAttributes __instance, ref bool __result) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!DrifterBossGrabPlugin.IsDrifterPresent) { return; } CharacterBody component = ((Component)__instance).gameObject.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { bool isBoss = component.isBoss; bool flag = ((Enum)component.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288); if (((isBoss && PluginConfig.Instance.EnableBossGrabbing.Value) || (flag && PluginConfig.Instance.EnableNPCGrabbing.Value)) && !PluginConfig.IsBlacklisted(((Object)((Component)__instance).gameObject).name)) { __result = true; } } if (PluginConfig.Instance.EnableLockedObjectGrabbing.Value && __instance.locked) { __result = true; } } } [HarmonyPatch(typeof(RepossessBullseyeSearch), "HurtBoxPassesRequirements")] public class RepossessBullseyeSearch_HurtBoxPassesRequirements { [HarmonyPostfix] public static void Postfix(ref bool __result, HurtBox hurtBox) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) __result = false; if (!Object.op_Implicit((Object)(object)hurtBox) || !Object.op_Implicit((Object)(object)hurtBox.healthComponent) || !hurtBox.healthComponent.alive) { return; } CharacterBody body = hurtBox.healthComponent.body; bool flag = false; if (Object.op_Implicit((Object)(object)body)) { if ((body.isBoss && !PluginConfig.Instance.EnableBossGrabbing.Value) || (((Enum)body.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288) && !body.isBoss && !PluginConfig.Instance.EnableNPCGrabbing.Value)) { return; } flag = true; } if (flag && !PluginConfig.IsBlacklisted(((Object)body).name)) { __result = true; } } } [HarmonyPatch(typeof(SpecialObjectAttributes), "AvoidCapture")] public class SpecialObjectAttributes_AvoidCapture { [HarmonyPrefix] public static bool Prefix(SpecialObjectAttributes __instance) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (!DrifterBossGrabPlugin.IsDrifterPresent) { return true; } if (PluginConfig.IsBlacklisted(((Object)((Component)__instance).gameObject).name)) { return true; } CharacterBody component = ((Component)__instance).gameObject.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { bool isBoss = component.isBoss; bool flag = ((Enum)component.bodyFlags).HasFlag((Enum)(object)(BodyFlags)524288); bool flag2 = (isBoss && PluginConfig.Instance.EnableBossGrabbing.Value) || (flag && PluginConfig.Instance.EnableNPCGrabbing.Value); return !flag2; } return true; } } [HarmonyPatch(typeof(AimRepossess), "OnEnter")] public class AimRepossess_OnEnter_Patch { [HarmonyPrefix] public static void Prefix(AimRepossess __instance) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[AimRepossess.OnEnter] Prefix: range={__instance.searchRange}."); } if (PluginConfig.Instance.EnableBalance.Value) { __instance.searchRange *= PluginConfig.Instance.SearchRadiusMultiplier.Value; } } } [HarmonyPatch(typeof(Repossess), "OnEnter")] public class Repossess_OnEnter_Patch { [HarmonyPrefix] public static void Prefix(Repossess __instance) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[Repossess.OnEnter] Prefix: range={__instance.searchRange}."); } if (PluginConfig.Instance.EnableBalance.Value) { __instance.searchRange *= PluginConfig.Instance.SearchRadiusMultiplier.Value; } } } } public static class SkillPatches { [HarmonyPatch(typeof(GenericSkill), "RunRecharge", new Type[] { typeof(float) })] public class GenericSkill_RunRecharge { [HarmonyPrefix] public static bool Prefix(GenericSkill __instance) { //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) if (!PluginConfig.Instance.BottomlessBagEnabled.Value || !PluginConfig.Instance.EnableStockRefreshClamping.Value) { return true; } if (Object.op_Implicit((Object)(object)__instance.characterBody) && __instance.characterBody.bodyIndex == BodyCatalog.FindBodyIndex("DrifterBody") && Object.op_Implicit((Object)(object)__instance.characterBody.skillLocator) && (Object)(object)__instance.characterBody.skillLocator.utility == (Object)(object)__instance) { DrifterBagController component = ((Component)__instance.characterBody).GetComponent(); if ((Object)(object)component != (Object)null) { int currentBaggedCount = BagCapacityCalculator.GetCurrentBaggedCount(component); int num = Mathf.Max(1, __instance.maxStock - currentBaggedCount); if (__instance.stock >= num) { __instance.rechargeStopwatch = 0f; return false; } } } return true; } } } public static class SpecialObjectAttributesPatches { [HarmonyPatch(typeof(SpecialObjectAttributes), "OnEnable")] public class SpecialObjectAttributes_OnEnable_Patch { [HarmonyPostfix] public static void Postfix(SpecialObjectAttributes __instance) { RegisteredObjects.Add(((Component)__instance).gameObject); } } [HarmonyPatch(typeof(SpecialObjectAttributes), "OnDisable")] public class SpecialObjectAttributes_OnDisable_Patch { [HarmonyPostfix] public static void Postfix(SpecialObjectAttributes __instance) { RegisteredObjects.Remove(((Component)__instance).gameObject); } } [HarmonyPatch(typeof(SpecialObjectAttributes), "Start")] public class SpecialObjectAttributes_Start_Patch { [HarmonyPostfix] public static void Postfix(SpecialObjectAttributes __instance) { } } [HarmonyPatch(typeof(BaggedObject), "OnEnter")] public class BaggedObject_OnEnter_Patch { [HarmonyPrefix] public static void Prefix(BaggedObject __instance) { object? obj = _targetObjectField?.GetValue(__instance); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if ((Object)(object)val == (Object)null) { return; } SpecialObjectAttributes component = val.GetComponent(); if ((Object)(object)component == (Object)null) { return; } Collider[] componentsInChildren = val.GetComponentsInChildren(true); if (!(_collidersToDisableField?.GetValue(component) is List list)) { return; } Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if (!IsEssentialCollider(val2, val) && !list.Contains(val2)) { list.Add(val2); } } } [HarmonyPostfix] public static void Postfix(BaggedObject __instance) { if (PluginConfig.Instance.EnableCarouselHUD.Value) { object? obj = _uiOverlayControllerField?.GetValue(__instance); OverlayController val = (OverlayController)((obj is OverlayController) ? obj : null); if (val != null) { HudOverlayManager.RemoveOverlay(val); _uiOverlayControllerField?.SetValue(__instance, null); } } } } public static readonly HashSet RegisteredObjects = new HashSet(); private static readonly FieldInfo _targetObjectField = ReflectionCache.BaggedObject.TargetObject; private static readonly FieldInfo _collidersToDisableField = ReflectionCache.SpecialObjectAttributes.CollidersToDisable; private static readonly FieldInfo _uiOverlayControllerField = ReflectionCache.BaggedObject.UIOverlayController; private static bool IsEssentialCollider(Collider collider, GameObject root) { if ((Object)(object)((Component)collider).gameObject == (Object)(object)root) { return true; } if ((Object)(object)((Component)collider).GetComponent() != (Object)null) { return true; } if ((Object)(object)((Component)collider).GetComponentInParent(true) != (Object)null) { return true; } if ((Object)(object)((Component)collider).GetComponent() != (Object)null) { return true; } return false; } } public static class StateCalculationPatches { [HarmonyPatch(typeof(BluntForceHit3), "OnEnter")] public class BluntForceHit3_OnEnter_UseFormula { [HarmonyPostfix] public static void Postfix(BluntForceHit3 __instance) { if (PluginConfig.Instance.EnableBalance.Value) { DrifterBagController component = ((EntityState)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { ((BasicMeleeAttack)__instance).damageCoefficient = SlamDamageCalculator.GetEffectiveCoefficient(component); Log.Debug($"[BluntForceHit3_OnEnter] Applied formula-based bludgeon damage coefficient: {((BasicMeleeAttack)__instance).damageCoefficient:F2}"); } } } } [HarmonyPatch(typeof(SuffocateSlam), "OnEnter")] public class SuffocateSlam_OnEnter_UseDynamicCapacity { [HarmonyPostfix] public static void Postfix(SuffocateSlam __instance) { if (!PluginConfig.Instance.EnableBalance.Value) { return; } DrifterBagController component = ((EntityState)__instance).GetComponent(); if (!((Object)(object)component == (Object)null)) { ((BasicMeleeAttack)__instance).damageCoefficient = SlamDamageCalculator.GetEffectiveCoefficient(component); float num = CapacityScalingSystem.CalculateMassCapacity(component); float num2 = component.baggedMass / DrifterBagController.maxMass; float num3 = component.baggedMass / num; float num4 = __instance.durationIncreaseWithMass * num2; ((BasicMeleeAttack)__instance).baseDuration = ((BasicMeleeAttack)__instance).baseDuration - num4; ((BasicMeleeAttack)__instance).baseDuration = ((BasicMeleeAttack)__instance).baseDuration + __instance.durationIncreaseWithMass * num3; float num5 = ((BluntForceBase)__instance).baseDurationBeforeInterruptable / ((BasicMeleeAttack)__instance).baseDuration; ((BluntForceBase)__instance).durationBeforeInterruptable = ((BasicMeleeAttack)__instance).baseDuration * num5; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuffocateSlam_OnEnter] Applied formula-based damage:"); Log.Debug($" Damage Coef: {((BasicMeleeAttack)__instance).damageCoefficient:F2} (mass={component.baggedMass:F1}, capacity={num:F1})"); Log.Debug($" Base Duration: {((BasicMeleeAttack)__instance).baseDuration:F2}s"); } } } } [HarmonyPatch(typeof(SuffocateSlam), "AuthorityModifyOverlapAttack")] public class SuffocateSlam_AuthorityModifyOverlapAttack_ApplyCustomDamage { [HarmonyPrefix] [HarmonyPriority(800)] public static void Prefix(SuffocateSlam __instance, OverlapAttack overlapAttack) { if (!PluginConfig.Instance.EnableBalance.Value) { return; } DrifterBagController component = ((EntityState)__instance).GetComponent(); if ((Object)(object)component == (Object)null) { return; } float effectiveCoefficient = SlamDamageCalculator.GetEffectiveCoefficient(component); CharacterBody characterBody = ((EntityState)__instance).characterBody; if ((Object)(object)characterBody != (Object)null) { overlapAttack.damage = characterBody.damage * effectiveCoefficient; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[SuffocateSlam_AuthorityModifyOverlapAttack] Applied custom damage:"); Log.Debug($" OverlapAttack Damage: {overlapAttack.damage:F2} (coef={effectiveCoefficient:F2}, baseDamage={characterBody.damage:F2})"); } } } } } public static class ZoneDetectionPatches { public static class Timing { public const float MapZoneCheckInterval = 5f; } private static bool areOutOfBoundsZonesInverted; private static bool zoneInversionDetected; public static void DetectZoneInversion(Vector3 playerPosition) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (zoneInversionDetected) { return; } MapZone[] array = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); int num = 0; bool flag = false; int num2 = LayerMask.NameToLayer("CollideWithCharacterHullOnly"); MapZone[] array2 = array; foreach (MapZone val in array2) { if ((int)val.zoneType == 0 && ((Component)val).gameObject.layer == num2) { num++; if (val.IsPointInsideMapZone(playerPosition)) { flag = true; } } } if (num > 0) { areOutOfBoundsZonesInverted = !flag; zoneInversionDetected = true; } else { areOutOfBoundsZonesInverted = false; zoneInversionDetected = true; } } public static void ResetZoneInversionDetection() { zoneInversionDetected = false; areOutOfBoundsZonesInverted = false; } } public static class UIPatches { private static GameObject? _massCapacityUIControllerObject; public static void InitializeMassCapacityUI(CharacterBody drifterBody) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)drifterBody == (Object)null || drifterBody.bodyIndex != BodyCatalog.FindBodyIndex("DrifterBody")) { return; } Log.Debug("[UIPatches] InitializeMassCapacityUI() called for " + ((Object)drifterBody).name); if ((Object)(object)((Component)drifterBody).GetComponent() == (Object)null) { ((Component)drifterBody).gameObject.AddComponent(); Log.Debug("[UIPatches] Added BaggedObjectInfoUIController to " + ((Object)drifterBody).name); } if (((NetworkBehaviour)drifterBody).hasAuthority) { MassCapacityUIController component = ((Component)drifterBody).GetComponent(); if ((Object)(object)component == (Object)null) { ((Component)drifterBody).gameObject.AddComponent(); _massCapacityUIControllerObject = ((Component)drifterBody).gameObject; Log.Debug("[UIPatches] Added MassCapacityUIController to " + ((Object)drifterBody).name); } else { _massCapacityUIControllerObject = ((Component)drifterBody).gameObject; Log.Debug("[UIPatches] MassCapacityUIController already exists on " + ((Object)drifterBody).name); } } } public static void CleanupMassCapacityUI() { Log.Debug("[UIPatches] MassCapacityUIController cleanup not needed (component on DrifterBody)"); } public static void UpdateMassCapacityUIOnCapacityChange(DrifterBagController controller) { if (!((Object)(object)_massCapacityUIControllerObject == (Object)null)) { MassCapacityUIController component = _massCapacityUIControllerObject.GetComponent(); if ((Object)(object)component != (Object)null) { component.UpdateCapacityUI(); } } } } public static class RunLifecyclePatches { public static void Initialize() { Run.onRunStartGlobal += OnRunStartGlobal; Run.onRunDestroyGlobal += OnRunDestroyGlobal; } public static void Cleanup() { Run.onRunStartGlobal -= OnRunStartGlobal; Run.onRunDestroyGlobal -= OnRunDestroyGlobal; } private static void OnRunStartGlobal(Run run) { PersistenceManager.Initialize(); PersistenceManager.ClearPersistedObjects(); PersistenceObjectsTracker.ClearTrackedObjects(); Log.Debug(" Persistence system initialized on run start"); } private static void OnRunDestroyGlobal(Run run) { PersistenceManager.Cleanup(); PersistenceObjectsTracker.ClearTrackedObjects(); Log.Debug(" Persistence system cleaned up on run destroy"); } } public static class ProjectilePatches { [HarmonyPatch(typeof(ProjectileController), "Start")] public class ProjectileController_Start_Patch { [HarmonyPostfix] public static void Postfix(ProjectileController __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)((Component)__instance).gameObject == (Object)null) { return; } ProjectileGrabbingMode value = PluginConfig.Instance.ProjectileGrabbingMode.Value; if (value == ProjectileGrabbingMode.None) { return; } bool flag = IsSurvivorProjectile(__instance); if ((value == ProjectileGrabbingMode.SurvivorOnly && !flag) || PluginConfig.IsBlacklisted(((Object)((Component)__instance).gameObject).name)) { return; } SpecialObjectAttributes component = ((Component)__instance).gameObject.GetComponent(); if ((Object)(object)component != (Object)null) { return; } HealthComponent component2 = ((Component)__instance).gameObject.GetComponent(); if (!((Object)(object)component2 != (Object)null)) { CharacterBody component3 = ((Component)__instance).gameObject.GetComponent(); if (!((Object)(object)component3 != (Object)null)) { GrabbableObjectPatches.AddSpecialObjectAttributesToProjectile(((Component)__instance).gameObject); } } } } public static bool IsSurvivorProjectile(ProjectileController projectileController) { if ((Object)(object)projectileController == (Object)null || (Object)(object)projectileController.owner == (Object)null) { return false; } CharacterBody component = projectileController.owner.GetComponent(); return (Object)(object)component != (Object)null && component.isPlayerControlled; } } public static class ProjectileRecoveryPatches { public static class ProjectileRecovery { public const float TeleportForwardDistance = 4f; public const float TeleportUpDistance = 2f; public const float RecoveryUpDistance = 2f; } [HarmonyPatch(typeof(ThrownObjectProjectileController), "OnSyncPassenger")] public class ThrownObjectProjectileController_OnSyncPassenger_Patch { [HarmonyPostfix] public static void Postfix(ThrownObjectProjectileController __instance, GameObject passengerObject) { if ((Object)(object)passengerObject == (Object)null) { Log.Warning("[ThrownObjectProjectileController_OnSyncPassenger] passengerObject is null"); return; } if (!NetworkUtils.ValidateObjectReadyWithRecovery(passengerObject)) { Log.Warning("[ThrownObjectProjectileController_OnSyncPassenger] " + ((Object)passengerObject).name + " is not ready for network operations (recovery attempted)"); return; } lock (_projectileStateLock) { if (projectileStateObjects.Contains(passengerObject)) { Log.Debug("[ThrownObjectProjectileController_OnSyncPassenger] " + ((Object)passengerObject).name + " already processed, skipping"); return; } } NetworkUtils.LogNetworkOperation("ThrownObjectProjectileController_OnSyncPassenger", passengerObject, NetworkServer.active, new Dictionary { { "projectile", ((Object)(object)__instance != (Object)null) ? ((Object)__instance).name : "null" } }); if ((Object)(object)__instance != (Object)null) { ProcessThrownObject(__instance, passengerObject); } } } [HarmonyPatch(typeof(MapZone), "TryZoneStart")] public class MapZone_TryZoneStart_Patch { [HarmonyPrefix] public static bool Prefix(MapZone __instance, Collider other) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Invalid comparison between Unknown and I4 //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Invalid comparison between Unknown and I4 if ((int)__instance.zoneType != 0) { return true; } Log.Debug($"[Recovery] MapZone triggered: {((Object)__instance).name} (ZoneLayer: {((Component)__instance).gameObject.layer}) | Object: {((Object)other).name} | ObjectLayer: {((Component)other).gameObject.layer}"); CharacterBody component = ((Component)other).GetComponent(); GameObject val = (GameObject)(((Object)(object)component != (Object)null) ? ((object)((Component)component).gameObject) : ((object)FindTrackedObjectInHierarchy(((Component)other).gameObject))); if ((Object)(object)val != (Object)null) { if (IsInProjectileState(val)) { Log.Debug("[Recovery] Tracked object " + ((Object)val).name + " hit OOB zone " + ((Object)__instance).name); if (PluginConfig.IsRecoveryBlacklisted(((Object)val).name)) { Log.Debug("[Recovery] " + ((Object)val).name + " is blacklisted from recovery, letting vanilla handle"); return true; } if ((Object)(object)component != (Object)null && Object.op_Implicit((Object)(object)component.teamComponent) && (int)component.teamComponent.teamIndex != 1 && PluginConfig.Instance.EnemyRecoveryMode.Value == EnemyRecoveryMode.Kill) { Log.Debug("[Recovery] Letting vanilla handle OOB for enemy " + ((Object)component).name + " (Kill mode)"); return true; } if ((Object)(object)component != (Object)null) { if (component.isBoss || component.isChampion) { if (!PluginConfig.Instance.RecoverBaggedBosses.Value) { Log.Debug("[Recovery] Boss recovery disabled for " + ((Object)component).name + ", letting vanilla handle"); return true; } } else if (!PluginConfig.Instance.RecoverBaggedNPCs.Value) { Log.Debug("[Recovery] NPC recovery disabled for " + ((Object)component).name + ", letting vanilla handle"); return true; } } else if (!PluginConfig.Instance.RecoverBaggedEnvironmentObjects.Value) { Log.Debug("[Recovery] Environment object recovery disabled for " + ((Object)val).name + ", letting vanilla handle"); return true; } RecoverObject(val); return false; } } else { ProjectileController val2 = ((Component)other).GetComponent() ?? ((Component)other).GetComponentInParent(); if (Object.op_Implicit((Object)(object)val2) && !Object.op_Implicit((Object)(object)((Component)other).GetComponent())) { Log.Debug("[Recovery] Generic Projectile hit MapZone: " + ((Object)other).name + " (Parent: " + ((Object)val2).name + ")"); ThrownObjectProjectileController component2 = ((Component)val2).GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.Networkpassenger != (Object)null) { GameObject networkpassenger = component2.Networkpassenger; CharacterBody component3 = networkpassenger.GetComponent(); if ((Object)(object)component3 != (Object)null && (Object)(object)component3.teamComponent != (Object)null && (int)component3.teamComponent.teamIndex != 1 && PluginConfig.Instance.EnemyRecoveryMode.Value == EnemyRecoveryMode.Kill) { Log.Debug("[Recovery] Letting vanilla handle OOB for thrown enemy " + ((Object)networkpassenger).name + " (Kill mode)"); return true; } } RecoverProjectile(((Component)val2).gameObject); return false; } } return true; } } [HarmonyPatch(typeof(ThrownObjectProjectileController), "ImpactBehavior")] public class ThrownObjectProjectileController_ImpactBehavior_Patch { [HarmonyPrefix] public static void Prefix(ThrownObjectProjectileController __instance) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: 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) if (PluginConfig.Instance.EnableDebugLogs.Value && (Object)(object)__instance.Networkpassenger != (Object)null) { GameObject networkpassenger = __instance.Networkpassenger; Log.Debug("[Impact.Prefix] Projectile: " + ((Object)__instance).name + " | Passenger: " + ((Object)networkpassenger).name); Log.Debug($" Proj Pos: {((Component)__instance).transform.position}"); Log.Debug($" Pass Pos: {networkpassenger.transform.position}"); Log.Debug(" Pass Parent: " + (Object.op_Implicit((Object)(object)networkpassenger.transform.parent) ? ((Object)networkpassenger.transform.parent).name : "null")); try { object[] array = new object[2]; _calculatePassengerFinalPositionMethod.Invoke(__instance, array); Vector3 val = (Vector3)array[0]; Quaternion val2 = (Quaternion)array[1]; Log.Debug($" Calculated Final Pos: {val}, Rot: {val2}"); } catch (Exception ex) { Log.Warning(" Failed to invoke CalculatePassengerFinalPosition: " + ((ex.InnerException != null) ? ex.InnerException.Message : ex.Message)); } } } [HarmonyPostfix] public static void Postfix(ThrownObjectProjectileController __instance) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance.Networkpassenger != (Object)null)) { return; } if (PluginConfig.Instance.EnableDebugLogs.Value) { GameObject networkpassenger = __instance.Networkpassenger; Log.Debug("[Impact.Postfix] Projectile: " + ((Object)__instance).name + " | Passenger: " + ((Object)networkpassenger).name); Log.Debug($" Final Pass Pos: {networkpassenger.transform.position}"); Log.Debug(" Final Pass Parent: " + (Object.op_Implicit((Object)(object)networkpassenger.transform.parent) ? ((Object)networkpassenger.transform.parent).name : "null")); Log.Debug("[Recovery] ThrownObjectProjectileController impacted. Clearing throw state for " + ((Object)networkpassenger).name); } lock (_throwTrackingLock) { if (_objectsUndergoingThrow.Contains(__instance.Networkpassenger)) { _objectsUndergoingThrow.Remove(__instance.Networkpassenger); } } RemoveFromProjectileState(__instance.Networkpassenger); } } [HarmonyPatch(typeof(ThrownObjectProjectileController), "OnDestroy")] public class ThrownObjectProjectileController_OnDestroy_Patch { [HarmonyPrefix] public static void Prefix(ThrownObjectProjectileController __instance) { if (!((Object)(object)__instance.Networkpassenger != (Object)null)) { return; } lock (_throwTrackingLock) { if (_objectsUndergoingThrow.Contains(__instance.Networkpassenger)) { Log.Debug("[Recovery] ThrownObjectProjectileController destroyed. Safety clearing throw state for " + ((Object)__instance.Networkpassenger).name); _objectsUndergoingThrow.Remove(__instance.Networkpassenger); } } RemoveFromProjectileState(__instance.Networkpassenger); } } internal static readonly HashSet projectileStateObjects = new HashSet(); private static readonly object _projectileStateLock = new object(); private static readonly HashSet _objectsUndergoingThrow = new HashSet(); private static readonly object _throwTrackingLock = new object(); private static readonly ConditionalWeakTable lastKnownOwners = new ConditionalWeakTable(); private static readonly Dictionary _originalLayersByObject = new Dictionary(); private static readonly object _layerLock = new object(); private static readonly FieldInfo _projectileControllerField = ReflectionCache.ThrownObjectProjectileController.ProjectileController; private static readonly MethodInfo _calculatePassengerFinalPositionMethod = ReflectionCache.ThrownObjectProjectileController.CalculatePassengerFinalPosition; public static bool IsUndergoingThrowOperation(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } lock (_throwTrackingLock) { return _objectsUndergoingThrow.Contains(obj); } } public static void RecoverObject(GameObject passenger) { //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01de: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_021a: Unknown result type (might be due to invalid IL or missing references) //IL_021f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)passenger == (Object)null) { return; } if (PluginConfig.IsRecoveryBlacklisted(((Object)passenger).name)) { Log.Debug("[Recovery] " + ((Object)passenger).name + " is blacklisted from recovery, letting vanilla handle"); return; } CharacterBody component = passenger.GetComponent(); if ((Object)(object)component != (Object)null) { if (component.isBoss || component.isChampion) { if (!PluginConfig.Instance.RecoverBaggedBosses.Value) { Log.Debug("[Recovery] Boss recovery disabled for " + ((Object)passenger).name + ", letting vanilla handle"); return; } } else if (!PluginConfig.Instance.RecoverBaggedNPCs.Value) { Log.Debug("[Recovery] NPC recovery disabled for " + ((Object)passenger).name + ", letting vanilla handle"); return; } } else if (!PluginConfig.Instance.RecoverBaggedEnvironmentObjects.Value) { Log.Debug("[Recovery] Environment object recovery disabled for " + ((Object)passenger).name + ", letting vanilla handle"); return; } DrifterBagController value = null; SpecialObjectAttributes component2 = passenger.GetComponent(); if ((Object)(object)component2 != (Object)null) { foreach (DrifterBagController allController in BagPatches.GetAllControllers()) { if (BagHelpers.IsBaggedObject(allController, passenger)) { value = allController; break; } } } if ((Object)(object)value == (Object)null) { lastKnownOwners.TryGetValue(passenger, out value); } if ((Object)(object)value == (Object)null || (Object)(object)value.characterBody == (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[Recovery] Could not find bag owner/destination for " + ((Object)passenger).name); } return; } Log.Debug("[Recovery] Recovering " + ((Object)passenger).name + " for " + ((Object)value.characterBody).name); Log.Debug("[Recovery] Attempting to recover bagged object: " + ((Object)passenger).name); Vector3 position = value.characterBody.corePosition + value.characterBody.transform.forward * 4f + Vector3.up * 2f; if (Object.op_Implicit((Object)(object)Run.instance)) { position = Run.instance.FindSafeTeleportPosition(value.characterBody, ((Component)value).transform, 0f, 100f); } BagPassengerManager.RemoveBaggedObject(value, passenger); passenger.transform.position = position; RemoveFromProjectileState(passenger); BagState state = BagPatches.GetState(value); if (state != null && state.DisabledCollidersByObject.TryGetValue(passenger, out Dictionary value2)) { BodyColliderCache.RestoreMovementColliders(value2); state.DisabledCollidersByObject.Remove>(passenger, out var _); } lock (_throwTrackingLock) { if (_objectsUndergoingThrow.Contains(passenger)) { _objectsUndergoingThrow.Remove(passenger); } } } private static void ProcessThrownObject(ThrownObjectProjectileController __instance, GameObject passenger) { //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)passenger == (Object)null) { Log.Error("[ThrowPatch] Passenger is null, cannot process thrown object"); return; } string name = ((Object)passenger).name; lock (_throwTrackingLock) { _objectsUndergoingThrow.Add(passenger); } lock (_projectileStateLock) { projectileStateObjects.Add(passenger); } if (PluginConfig.Instance.EnableRecoveryFeature.Value) { int layer = 0; ((Component)__instance).gameObject.layer = layer; Transform transform = passenger.transform; lock (_layerLock) { if (!_originalLayersByObject.ContainsKey(passenger)) { _originalLayersByObject[passenger] = passenger.layer; } } passenger.layer = layer; Transform[] componentsInChildren = ((Component)__instance).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (!((Object)(object)val == (Object)(object)transform) && !val.IsChildOf(transform)) { ((Component)val).gameObject.layer = layer; } } } object? obj = _projectileControllerField?.GetValue(__instance); ProjectileController val2 = (ProjectileController)((obj is ProjectileController) ? obj : null); if ((Object)(object)val2 == (Object)null) { Log.Error("[ThrowPatch] Failed to get projectileController from " + ((object)__instance).GetType().Name); return; } GameObject owner = val2.owner; if ((Object)(object)owner != (Object)null) { DrifterBagController component = owner.GetComponent(); if ((Object)(object)component != (Object)null) { lastKnownOwners.Remove(passenger); lastKnownOwners.Add(passenger, component); if (NetworkServer.active) { Log.Debug("[ProcessThrownObject] SERVER: Removing " + name + " from bag tracking (throw operation)"); BaggedObjectStatePatches.PerformPassengerRestoration(component, passenger); BagPassengerManager.RemoveBaggedObject(component, passenger); PersistenceObjectsTracker.UntrackBaggedObject(passenger); NetworkIdentity component2 = passenger.GetComponent(); if ((Object)(object)component2 != (Object)null) { BottomlessBagNetworkController component3 = ((Component)component).GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.RemoveBaggedObjectId(component2.netId); NetworkInstanceId netId = component2.netId; Log.Debug($"[ProcessThrownObject] SERVER: Removed {name} (netId={((NetworkInstanceId)(ref netId)).Value}) from network state"); } CycleNetworkHandler.SendBagStateUpdate(component, component2.netId, isThrowOperation: true); Log.Debug("[ProcessThrownObject] SERVER: Sent bag state update for thrown " + name); } else { Log.Warning("[ProcessThrownObject] " + name + " does not have NetworkIdentity, cannot send state update"); } } else { BagState state = BagPatches.GetState(component); if (state.BaggedObjects != null && state.BaggedObjects.Contains(passenger)) { BaggedObjectStatePatches.PerformPassengerRestoration(component, passenger); BagPassengerManager.RemoveBaggedObject(component, passenger, isDestroying: false, skipStateReset: true, preserveStateDuringThrow: true); } PersistenceObjectsTracker.UntrackBaggedObject(passenger); } } else { Log.Warning("[ProcessThrownObject] Owner does not have DrifterBagController component"); } } else { Log.Warning("[ProcessThrownObject] Projectile owner is null"); } } public static void RecoverProjectile(GameObject projectile) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)projectile == (Object)null) { return; } ProjectileController component = projectile.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.owner != (Object)null) { projectile.transform.position = component.owner.transform.position + Vector3.up * 2f; Rigidbody component2 = projectile.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.velocity = Vector3.zero; component2.angularVelocity = Vector3.zero; } } } private static GameObject? FindTrackedObjectInHierarchy(GameObject obj) { if ((Object)(object)obj == (Object)null) { return null; } Transform val = obj.transform; while ((Object)(object)val != (Object)null) { if (IsInProjectileState(((Component)val).gameObject)) { return ((Component)val).gameObject; } val = val.parent; } return null; } public static bool IsInProjectileState(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } lock (_projectileStateLock) { return projectileStateObjects.Contains(obj) || _objectsUndergoingThrow.Contains(obj); } } public static int GetProjectileStateCount(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 0; } int num = 0; lock (_projectileStateLock) { foreach (GameObject projectileStateObject in projectileStateObjects) { if ((Object)(object)projectileStateObject != (Object)null && BagHelpers.IsBaggedObject(controller, projectileStateObject)) { num++; } } return num; } } public static void RemoveFromProjectileState(GameObject obj) { if ((Object)(object)obj != (Object)null) { lock (_projectileStateLock) { projectileStateObjects.Remove(obj); } } if (!PluginConfig.Instance.EnableRecoveryFeature.Value || !((Object)(object)obj != (Object)null)) { return; } lock (_layerLock) { if (_originalLayersByObject.TryGetValue(obj, out var value)) { obj.layer = value; _originalLayersByObject.Remove(obj); } } } } [HarmonyPatch(typeof(BossGroup))] public static class BossGroupPatches { [HarmonyPrefix] [HarmonyPatch("DropRewards")] public static void DropRewardsPrefix(BossGroup __instance) { //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { return; } ModelLocator val = ((Component)__instance).GetComponent() ?? ((Component)__instance).GetComponentInParent(); if ((Object)(object)val != (Object)null && (Object)(object)val.modelTransform != (Object)null) { Transform val2 = SearchForPivot(val.modelTransform, "HologramPivot"); if ((Object)(object)val2 != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[BossGroupPatches] Redirecting rewards for {((Object)__instance).name} to {((Object)val2).name} at {val2.position}"); } __instance.dropPosition = val2; } } int num = (Object.op_Implicit((Object)(object)Run.instance) ? Run.instance.participatingPlayerCount : (-1)); object value = Traverse.Create((object)__instance).Field("rng").GetValue(); IList list = Traverse.Create((object)__instance).Field("bossDrops").GetValue() as IList; IList list2 = Traverse.Create((object)__instance).Field("bossDropTables").GetValue() as IList; if (value == null) { Log.Warning("[BossGroupDiagnostics] ALERT: RNG is null! Rewards will abort in vanilla code."); } if ((Object)(object)__instance.dropPosition == (Object)null) { Log.Warning("[BossGroupDiagnostics] ALERT: dropPosition is null! No item will be spawned."); } if ((Object)(object)__instance.dropTable == (Object)null && NetworkServer.active) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Warning("[BossGroup] BossGroup " + ((Object)__instance).name + " has no dropTable! Injecting dtTier2Item fallback."); } __instance.dropTable = Addressables.LoadAssetAsync((object)"RoR2/Base/Common/dtTier2Item.asset").WaitForCompletion(); } } private static Transform? SearchForPivot(Transform parent, string name) { if (((Object)parent).name == name) { return parent; } for (int i = 0; i < parent.childCount; i++) { Transform val = SearchForPivot(parent.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } } public static class SceneExitPatches { [HarmonyPatch(typeof(SceneExitController), "OnEnable")] public class SceneExitController_OnEnable { [HarmonyPostfix] public static void Postfix(SceneExitController __instance) { SceneExitController.onBeginExit += OnBeginExit; } } [HarmonyPatch(typeof(SceneExitController), "OnDisable")] public class SceneExitController_OnDisable { [HarmonyPostfix] public static void Postfix(SceneExitController __instance) { SceneExitController.onBeginExit -= OnBeginExit; } } private static bool _hasCapturedForScene; public static void ResetCaptureFlag() { _hasCapturedForScene = false; } private static void OnBeginExit(SceneExitController exitController) { Log.Debug("[SceneExitPatches] SceneExitController.onBeginExit called. Executing persistence capture."); ExecutePersistenceCapture(); } private static void ExecutePersistenceCapture() { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return; } if (_hasCapturedForScene) { Log.Debug("[SceneExitPatches] Persistence capture already executed for this scene transition. Skipping."); return; } _hasCapturedForScene = true; List currentlyBaggedObjects = PersistenceManager.GetCurrentlyBaggedObjects(); if (NetworkServer.active) { PersistenceNetworkHandler.SendBaggedObjectsPersistenceMessage(currentlyBaggedObjects); } PersistenceManager.CaptureCurrentlyBaggedObjects(); PersistenceManager.MoveObjectsToPersistenceContainer(); Log.Debug(string.Format(" Captured {0} bagged objects on scene exit{1}", currentlyBaggedObjects.Count, NetworkServer.active ? " and sent persistence message" : "")); } } public static class TeleporterPatches { [CompilerGenerated] private sealed class d__15 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public CombatDirector director; public float expectedCredits; private float 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__15(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Expected O, but got Unknown //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__2 = director.monsterCredit; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] Credit check IMMEDIATELY after add - credits={5__2}, expected≥{expectedCredits:F0}"); } if (5__2 < expectedCredits * 0.9f) { Log.Error($"[TeleporterPatches.Director] CRITICAL: Credits already lost IMMEDIATELY after adding! Expected ≥{expectedCredits * 0.9f:F0}, got {5__2:F0}"); } <>2__current = (object)new WaitForEndOfFrame(); <>1__state = 1; return true; case 1: { <>1__state = -1; float monsterCredit2 = director.monsterCredit; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] Credit check next frame - credits={monsterCredit2}"); } if (monsterCredit2 != 5__2) { Log.Error($"[TeleporterPatches.Director] CRITICAL: Credits changed between frames! {5__2:F0} → {monsterCredit2:F0}"); } <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 2; return true; } case 2: { <>1__state = -1; float monsterCredit = director.monsterCredit; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] Credit check after 0.5s - credits={monsterCredit}"); } if (monsterCredit < expectedCredits * 0.9f) { Log.Error($"[TeleporterPatches.Director] CRITICAL: Credits were lost! Expected ≥{expectedCredits * 0.9f:F0}, got {monsterCredit:F0}"); CombatDirectorPatches.ClearTeleporterDirectorRestoring(director); } else { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] Credits verified and persisting ({monsterCredit:F0}), clearing restoration flag"); } CombatDirectorPatches.ClearTeleporterDirectorRestoring(director); } 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 readonly FieldInfo? _baseSingletonField = typeof(TeleporterInteraction).BaseType?.GetField("instance", BindingFlags.Static | BindingFlags.Public); public static void PatchStaleReferences(TeleporterInteraction teleporter) { //IL_0d61: Unknown result type (might be due to invalid IL or missing references) //IL_0d68: Expected O, but got Unknown //IL_0cc5: Unknown result type (might be due to invalid IL or missing references) //IL_0cca: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0619: Unknown result type (might be due to invalid IL or missing references) //IL_0a3b: Unknown result type (might be due to invalid IL or missing references) //IL_0a45: Expected O, but got Unknown if ((Object)(object)teleporter == (Object)null || (Object)(object)((Component)teleporter).gameObject == (Object)null) { return; } if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Patching stale references for teleporter: " + ((Object)teleporter).name); } EntityStateMachine[] components = ((Component)teleporter).GetComponents(); EntityStateMachine val = ((IEnumerable)components).FirstOrDefault((Func)((EntityStateMachine esm) => esm.customName == "Body")) ?? ((Component)teleporter).GetComponent(); if ((Object)(object)val != (Object)null) { Log.Debug(string.Format("[TeleporterPatches.State] Current State: {0}, ActivationState: {1}, shrineBonusStacks={2}", ((object)val.state)?.GetType().Name ?? "null", teleporter.activationState, teleporter.shrineBonusStacks)); } if ((Object)(object)val != (Object)null && teleporter.isInFinalSequence) { Type nestedType = typeof(TeleporterInteraction).GetNestedType("ChargedState", BindingFlags.NonPublic); if (nestedType != null) { object? obj = Activator.CreateInstance(nestedType); EntityState val2 = (EntityState)((obj is EntityState) ? obj : null); if (val2 != null) { Log.Debug("[TeleporterPatches.State] Teleporter is in FinishedState. Kicking back to ChargedState to allow re-interaction."); val.SetNextState(val2); } } } SceneExitController component = ((Component)teleporter).GetComponent(); if ((Object)(object)component != (Object)null) { FieldInfo field = typeof(SceneExitController).GetField("exitState", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { Log.Debug("[TeleporterPatches.State] Resetting SceneExitController.exitState from Finished to Idle."); field.SetValue(component, 0); } } try { RestoreSingleton(); HoldoutZoneController component2 = ((Component)teleporter).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.Network_charge = 0f; float f = ((ReflectionCache.HoldoutZoneController.RadiusVelocity?.GetValue(component2) is float num) ? num : 0f); if (float.IsNaN(f) || float.IsInfinity(f)) { ReflectionCache.HoldoutZoneController.RadiusVelocity?.SetValue(component2, 0f); } ReflectionCache.HoldoutZoneController.CurrentRadius?.SetValue(component2, component2.baseRadius); ((Behaviour)component2).enabled = teleporter.isCharging; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.HoldoutZone] Reset charge/radius for {((Object)teleporter).name} (Enabled: {((Behaviour)component2).enabled})"); } } OutsideInteractableLocker component3 = ((Component)teleporter).GetComponent(); if ((Object)(object)component3 != (Object)null) { try { float radius = component3.radius; Object.DestroyImmediate((Object)(object)component3); OutsideInteractableLocker val3 = ((Component)teleporter).gameObject.AddComponent(); if ((Object)(object)val3 != (Object)null) { val3.radius = radius; ((Behaviour)val3).enabled = teleporter.isCharging; } if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Replaced OutsideInteractableLocker with fresh instance."); } } catch (Exception ex) { Log.Error("[TeleporterPatches] Locker nuclear reset error: " + ex.Message); } } object? obj2 = ReflectionCache.TeleporterInteraction.BossDirector?.GetValue(teleporter); CombatDirector val4 = (CombatDirector)((obj2 is CombatDirector) ? obj2 : null); if ((Object)(object)val4 != (Object)null && (Object)(object)((Component)val4).gameObject != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] CombatDirector found - INITIAL credits={val4.monsterCredit}, enabled={((Behaviour)val4).enabled}"); } object? obj3 = ReflectionCache.CombatDirector.CombatSquad?.GetValue(val4); CombatSquad val5 = (CombatSquad)((obj3 is CombatSquad) ? obj3 : null); if ((Object)(object)val5 != (Object)null && (Object)(object)((Component)val5).gameObject != (Object)null) { IList list = ReflectionCache.CombatSquad.MembersList?.GetValue(val5) as IList; FieldInfo field2 = typeof(CombatSquad).GetField("defeatedServer", BindingFlags.Instance | BindingFlags.NonPublic); if (field2 != null) { bool flag = (bool)(field2.GetValue(val5) ?? ((object)false)); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] Resetting CombatSquad.defeatedServer from {flag} -> False"); } field2.SetValue(val5, false); } FieldInfo field3 = typeof(CombatSquad).GetField("memberHistory", BindingFlags.Instance | BindingFlags.NonPublic); if (field3 != null && field3.GetValue(val5) is IList list2) { list2.Clear(); } if (list != null) { for (int num2 = list.Count - 1; num2 >= 0; num2--) { object? obj4 = list[num2]; Object val6 = (Object)((obj4 is Object) ? obj4 : null); if (val6 == (Object)null) { list.RemoveAt(num2); } } } } OutsideInteractableLocker component4 = ((Component)teleporter).GetComponent(); if ((Object)(object)component4 != (Object)null) { try { IDictionary dictionary = ReflectionCache.OutsideInteractableLocker.LockObjectMap?.GetValue(component4) as IDictionary; IDictionary dictionary2 = ReflectionCache.OutsideInteractableLocker.LockInteractableMap?.GetValue(component4) as IDictionary; dictionary?.Clear(); dictionary2?.Clear(); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Cleared stale locker maps for " + ((Object)teleporter).name); } } catch (Exception ex2) { Log.Warning("[TeleporterPatches] Failed to clear locker maps: " + ex2.Message); } } float num3 = (Object.op_Implicit((Object)(object)teleporter.holdoutZoneController) ? teleporter.holdoutZoneController.baseRadius : 60f); if (num3 < 10f) { num3 = 60f; } ReflectionCache.CombatDirector.MinSpawnRange?.SetValue(val4, num3 * 1.5f); ReflectionCache.CombatDirector.MaxSpawnDistance?.SetValue(val4, num3 * 2f); ReflectionCache.CombatDirector.BossOverrideSpawnSingleBoss?.SetValue(val4, true); BossGroup component5 = ((Component)teleporter).GetComponent(); bool flag2 = false; if ((Object)(object)component5 != (Object)null && (Object)(object)component5.combatSquad != (Object)null) { FieldInfo combatSquad = ReflectionCache.CombatDirector.CombatSquad; if (combatSquad != null) { combatSquad.SetValue(val4, component5.combatSquad); flag2 = true; bool flag3 = VerifyBossGroupSubscription(component5); CombatSquad combatSquad2 = component5.combatSquad; Log.Debug($"[TeleporterPatches.Director] Squad linked: director.combatSquad={((combatSquad2 != null) ? new NetworkInstanceId?(((NetworkBehaviour)combatSquad2).netId) : null)}, subscriptionValid={flag3}"); } else { Log.Error("[TeleporterPatches.Director] CRITICAL: Cannot link squad - CombatSquad field not found for " + ((Object)teleporter).name); } } else { Log.Error("[TeleporterPatches.Director] CRITICAL: Cannot link squad - BossGroup " + (((Object)(object)component5 == (Object)null) ? "is null" : "combatSquad is null") + " for " + ((Object)teleporter).name); } if (!flag2 && (Object)(object)component5 != (Object)null && (Object)(object)component5.combatSquad != (Object)null) { Log.Warning("[TeleporterPatches] Squad linking failed, forcing fallback: director=" + ((Object)val4).name + ", bossGroup=" + ((Object)component5).name); try { FieldInfo combatSquad3 = ReflectionCache.CombatDirector.CombatSquad; if (combatSquad3 != null) { combatSquad3.SetValue(val4, component5.combatSquad); flag2 = true; if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Fallback squad linking successful"); } } } catch (Exception ex3) { Log.Error("[TeleporterPatches] Fallback squad linking failed: " + ex3.Message); } } if (PluginConfig.Instance.EnableDebugLogs.Value) { string[] obj5 = new string[5] { "[TeleporterPatches.Director] Hardened Results: ", string.Format("minSpawnRange={0}, ", ReflectionCache.CombatDirector.MinSpawnRange?.GetValue(val4) ?? "FAIL"), string.Format("credits={0}, ", ReflectionCache.CombatDirector.MonsterCredit?.GetValue(val4) ?? "FAIL"), $"squadLinked={flag2}, ", null }; Run instance = Run.instance; obj5[4] = $"playerCount={((instance != null) ? instance.participatingPlayerCount : (-1))}"; Log.Debug(string.Concat(obj5)); } if (teleporter.isCharging) { ((Behaviour)val4).enabled = true; float num4 = (((Object)(object)Run.instance != (Object)null) ? Run.instance.compensatedDifficultyCoefficient : 1f); float num5 = (float)Math.Max(val4.overrideCost, (int)(600f * Mathf.Pow(num4, 0.5f))) * (float)(1 + teleporter.shrineBonusStacks); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] BEFORE adding credits - monsterCredit={val4.monsterCredit}, shrineBonusStacks={teleporter.shrineBonusStacks}, spawnCredits={num5}"); } CombatDirectorPatches.MarkTeleporterDirectorAsRestoring(val4); val4.currentSpawnTarget = ((Component)teleporter).gameObject; val4.monsterCredit += num5; val4.SetNextSpawnAsBoss(); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches.Director] AFTER adding credits - monsterCredit={val4.monsterCredit}, expected={val4.monsterCredit - num5 + num5:F0}"); object arg = ((Behaviour)val4).enabled; GameObject currentSpawnTarget = val4.currentSpawnTarget; Log.Debug(string.Format("[TeleporterPatches.Director] Director state: enabled={0}, spawnTarget={1}", arg, ((currentSpawnTarget != null) ? ((Object)currentSpawnTarget).name : null) ?? "null")); } ((MonoBehaviour)val4).StartCoroutine(VerifyCreditsPersist(val4, num5)); } } BossGroup component6 = ((Component)teleporter).GetComponent(); if ((Object)(object)component6 != (Object)null && (Object)(object)((Component)component6).gameObject != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { object arg2 = component6.bonusRewardCount; PickupDropTable dropTable = component6.dropTable; Log.Debug(string.Format("[TeleporterPatches.BossGroup] BossGroup found - bonusRewardCount={0}, dropTable={1}", arg2, ((dropTable != null) ? ((Object)dropTable).name : null) ?? "null")); } ReflectionCache.BossGroup.BossMemoryCount?.SetValue(component6, 0); component6.bonusRewardCount = teleporter.shrineBonusStacks; if (NetworkServer.active && !teleporter.isCharged) { ReflectionCache.TeleporterInteraction.MonstersCleared?.SetValue(teleporter, false); FieldInfo field4 = typeof(BossGroup).GetField("rng", BindingFlags.Instance | BindingFlags.NonPublic); ulong num6 = ((Run.instance?.bossRewardRng != null) ? Run.instance.bossRewardRng.nextUlong : ((ulong)DateTime.Now.Ticks)); field4?.SetValue(component6, (object?)new Xoroshiro128Plus(num6)); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches.BossGroup] Set fresh RNG with seed source: " + ((Run.instance?.bossRewardRng != null) ? "Run" : "Time")); } List list3 = (List)(ReflectionCache.BossGroup.BossDropTables?.GetValue(component6)); if (list3 == null) { list3 = new List(); ReflectionCache.BossGroup.BossDropTables?.SetValue(component6, list3); } if (PluginConfig.Instance.EnableDebugLogs.Value) { string[] obj6 = new string[6] { "[TeleporterPatches.BossGroup] PRE-PATCH: dropTable=", ((Object)(object)component6.dropTable != (Object)null) ? ((Object)component6.dropTable).name : "NULL", ", ", $"bonusCount={component6.bonusRewardCount}, ", $"currentTablesCount={list3.Count}, ", null }; CombatSquad combatSquad4 = component6.combatSquad; obj6[5] = $"squadMembers={((combatSquad4 != null) ? combatSquad4.readOnlyMembersList.Count : (-1))}"; Log.Debug(string.Concat(obj6)); } if (list3.Count == 0) { if ((Object)(object)component6.dropTable != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Restoring reward dropTable: " + ((Object)component6.dropTable).name); } list3.Add(component6.dropTable); } else { PickupDropTable val7 = Resources.Load("DropTables/dtTier2Item"); if ((Object)(object)val7 != (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Using FAIL-SAFE dtTier2Item drop table."); } list3.Add(val7); } } } ReflectionCache.BossGroup.BossDrops?.SetValue(component6, new List()); ReflectionCache.BossGroup.BossDropTablesLocked?.SetValue(component6, false); } component6.dropPosition = ((Component)teleporter).transform; try { ReflectionCache.BossGroup.ResetBossBar?.Invoke(component6, null); } catch { } } object? obj8 = ReflectionCache.TeleporterInteraction.PositionIndicator?.GetValue(teleporter); Component val8 = (Component)((obj8 is Component) ? obj8 : null); if ((Object)(object)val8 == (Object)null) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Recreating destroyed teleporterPositionIndicator for " + ((Object)teleporter).name); } GameObject val9 = LegacyResourcesAPI.Load("Prefabs/PositionIndicators/TeleporterChargingPositionIndicator"); if ((Object)(object)val9 != (Object)null) { GameObject val10 = Object.Instantiate(val9, ((Component)teleporter).transform.position, Quaternion.identity); PositionIndicator component7 = val10.GetComponent(); if ((Object)(object)component7 != (Object)null) { component7.targetTransform = ((Component)teleporter).transform; ReflectionCache.TeleporterInteraction.PositionIndicator?.SetValue(teleporter, component7); ChargeIndicatorController component8 = val10.GetComponent(); if ((Object)(object)component8 != (Object)null) { component2 = ((Component)teleporter).GetComponent(); component8.holdoutZoneController = component2; component8.isActivated = teleporter.isActivated; component8.isCharged = teleporter.isCharged; component8.isDiscovered = teleporter.isDiscovered; } val10.SetActive(false); } } } MPEventSystem val11 = (MPEventSystem)EventSystem.current; LocalUser value = (((Object)(object)val11 != (Object)null) ? val11.localUser : null); ReflectionCache.TeleporterInteraction.CachedLocalUser?.SetValue(teleporter, value); } catch (Exception ex4) { Log.Error("[TeleporterPatches] Error during stale reference patching: " + ex4.Message); } } private static void SilenceSingleton(TeleporterInteraction __instance) { TeleporterInteraction primary = MultiTeleporterTracker.GetPrimary(); if ((Object)(object)primary != (Object)null && (Object)(object)primary != (Object)(object)__instance) { TeleporterInteraction.instance = null; if (_baseSingletonField != null) { _baseSingletonField.SetValue(null, null); } } } private static void RestoreSingleton() { TeleporterInteraction primary = MultiTeleporterTracker.GetPrimary(); if ((Object)(object)primary != (Object)null) { TeleporterInteraction.instance = primary; if (_baseSingletonField != null) { _baseSingletonField.SetValue(null, primary); } } } [HarmonyPatch(typeof(TeleporterInteraction), "Awake")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPrefix] [HarmonyPriority(800)] private static void AwakePrefix(TeleporterInteraction __instance) { SilenceSingleton(__instance); } [HarmonyPatch(typeof(TeleporterInteraction), "Awake")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void AwakePostfix(TeleporterInteraction __instance) { if ((Object)(object)MultiTeleporterTracker.GetPrimary() == (Object)null) { MultiTeleporterTracker.RegisterPrimary(__instance); } else { MultiTeleporterTracker.RegisterSecondary(__instance); } RestoreSingleton(); } [HarmonyPatch(typeof(TeleporterInteraction), "OnEnable")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPrefix] [HarmonyPriority(800)] private static void OnEnablePrefix(TeleporterInteraction __instance) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown SilenceSingleton(__instance); TeleporterInteraction primary = MultiTeleporterTracker.GetPrimary(); if (!((Object)(object)primary != (Object)null) || !((Object)(object)primary != (Object)(object)__instance)) { return; } MultiTeleporterTracker.MarkPendingInit(__instance); EntityStateMachine val = (EntityStateMachine)ReflectionCache.TeleporterInteraction.MainStateMachine.GetValue(__instance); if (!((Object)(object)val == (Object)null)) { return; } EntityStateMachine val2 = ((IEnumerable)((Component)__instance).GetComponents()).FirstOrDefault((Func)((EntityStateMachine x) => x.customName == "Body")) ?? ((Component)__instance).GetComponent(); if ((Object)(object)val2 != (Object)null) { ReflectionCache.TeleporterInteraction.MainStateMachine.SetValue(__instance, val2); if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Restored mainStateMachine field for " + ((Object)((Component)__instance).gameObject).name + " via Reflection"); } } } [HarmonyPatch(typeof(TeleporterInteraction), "OnEnable")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPostfix] private static void OnEnablePostfix(TeleporterInteraction __instance) { RestoreSingleton(); } [HarmonyPatch(typeof(TeleporterInteraction), "OnInteractionBegin")] [HarmonyPrefix] private static void OnInteractionBeginPrefix(TeleporterInteraction __instance) { BossGroup component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null && PluginConfig.Instance.EnableDebugLogs.Value) { List list = (List)(ReflectionCache.BossGroup.BossDropTables?.GetValue(component)); object[] obj = new object[5] { list?.Count ?? (-1), null, null, null, null }; PickupDropTable dropTable = component.dropTable; obj[1] = ((dropTable != null) ? ((Object)dropTable).name : null) ?? "null"; obj[2] = component.bonusRewardCount; obj[3] = __instance.shrineBonusStacks; obj[4] = (Object)(object)component.combatSquad != (Object)null; Log.Debug(string.Format("[TeleporterPatches] Teleporter Activated! BossGroup: tables={0}, dropTable={1}, bonusRewards={2}, shrineBonusStacks={3}, squadExists={4}", obj)); } } [HarmonyPatch(typeof(BossGroup), "OnMemberDiscovered")] [HarmonyPrefix] private static void OnBossMemberDiscoveredPrefix(BossGroup __instance, CharacterMaster memberMaster) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)memberMaster == (Object)null) && PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterPatches] Boss Discovered: {((Object)memberMaster).name}. Total members in squad: {__instance.combatSquad.readOnlyMembersList.Count}"); } } [HarmonyPatch(typeof(BossGroup), "OnDefeatedServer")] [HarmonyPrefix] private static void OnBossDefeatedServerPrefix(BossGroup __instance) { if (PluginConfig.Instance.EnableDebugLogs.Value) { string name = ((Object)__instance).name; object arg = __instance.bonusRewardCount; PickupDropTable dropTable = __instance.dropTable; Log.Debug(string.Format("[TeleporterPatches] BossGroup {0} defeated! bonusRewardCount={1}, dropTable={2}. Logic handled by safety patches.", name, arg, ((dropTable != null) ? ((Object)dropTable).name : null) ?? "null")); } } [HarmonyPatch(typeof(ChargedState), "OnEnter")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPrefix] private static bool ChargedStateOnEnterPrefix(BaseState __instance) { TeleporterInteraction component = ((EntityState)__instance).GetComponent(); if ((Object)(object)component != (Object)null) { if (PersistenceManager.IsTeleporterCurrentlyBagged(((Component)component).gameObject)) { if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Blocking ChargedState.OnEnter for bagged teleporter " + ((Object)((Component)component).gameObject).name); } return false; } if (MultiTeleporterTracker.IsSecondary(component) && PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterPatches] Secondary teleporter " + ((Object)((Component)component).gameObject).name + " charged — allowing rewards, blocking portal."); } } return true; } [HarmonyPatch(typeof(TeleporterInteraction), "PingTeleporter")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPrefix] private static bool PingTeleporterPrefix(TeleporterInteraction __instance) { return !PersistenceManager.IsTeleporterCurrentlyBagged(((Component)__instance).gameObject); } [HarmonyPatch(typeof(TeleporterInteraction), "UpdateMonstersClear")] [HarmonyPatch(/*Could not decode attribute arguments.*/)] [HarmonyPrefix] private static bool UpdateMonstersClearPrefix(TeleporterInteraction __instance) { if (PersistenceManager.IsTeleporterCurrentlyBagged(((Component)__instance).gameObject)) { return false; } object? obj = ReflectionCache.TeleporterInteraction.BossGroup?.GetValue(__instance); BossGroup val = (BossGroup)((obj is BossGroup) ? obj : null); return (Object)(object)val != (Object)null; } private static bool VerifyBossGroupSubscription(BossGroup bossGroup) { if ((Object)(object)bossGroup.combatSquad == (Object)null) { Log.Error("[TeleporterPatches] BossGroup " + ((Object)bossGroup).name + " has null combatSquad!"); return false; } if ((Object)(object)((Component)bossGroup.combatSquad).gameObject == (Object)null) { Log.Error("[TeleporterPatches] BossGroup " + ((Object)bossGroup).name + " has destroyed combatSquad!"); return false; } if (!((Behaviour)bossGroup.combatSquad).isActiveAndEnabled) { Log.Warning("[TeleporterPatches] BossGroup " + ((Object)bossGroup).name + " combatSquad is not active!"); return false; } return true; } [IteratorStateMachine(typeof(d__15))] private static IEnumerator VerifyCreditsPersist(CombatDirector director, float expectedCredits) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__15(0) { director = director, expectedCredits = expectedCredits }; } [HarmonyPatch(typeof(CharacterMaster), "OnSyncCombatSquadInstanceId")] [HarmonyPrefix] private static void OnSyncCombatSquadInstanceIdPrefix(CharacterMaster __instance, NetworkInstanceId ___combatSquadInstanceId) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if (___combatSquadInstanceId == NetworkInstanceId.Invalid) { if (__instance.isBoss) { Log.Warning("[TeleporterDiagnostics] Boss " + ((Object)__instance).name + " is being assigned Invalid squad ID! This will prevent tracking."); } } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterDiagnostics] {((Object)__instance).name} assigned to squad {___combatSquadInstanceId}"); } } [HarmonyPatch(typeof(CombatSquad), "MemberDiscovered")] [HarmonyPrefix] private static void MemberDiscoveredPrefix(CombatSquad __instance, CharacterMaster memberMaster) { BossGroup component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null && PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[TeleporterDiagnostics] Squad of " + ((Object)component).name + " discovered member: " + ((Object)memberMaster).name); } } [HarmonyPatch(typeof(CombatDirector), "Spawn")] [HarmonyPostfix] private static void SpawnPostfix(CombatDirector __instance, bool __result, SpawnCard spawnCard) { //IL_0072: Unknown result type (might be due to invalid IL or missing references) if (!__result) { return; } try { object? obj = ReflectionCache.CombatDirector.CombatSquad?.GetValue(__instance); CombatSquad val = (CombatSquad)((obj is CombatSquad) ? obj : null); if ((Object)(object)((Component)__instance).gameObject.GetComponent() != (Object)null) { if ((Object)(object)val == (Object)null) { Log.Error("[TeleporterDiagnostics] Spawn by " + ((Object)__instance).name + " but director.combatSquad is NULL! Spawned monster will not be tracked!"); } else if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterDiagnostics] Spawn by {((Object)__instance).name} using squad {((NetworkBehaviour)val).netId}, squadMembers={val.memberCount}"); } } } catch (Exception ex) { Log.Error("[TeleporterDiagnostics] Spawn verification failed: " + ex.Message); } } [HarmonyPatch(typeof(CombatSquad), "Awake")] [HarmonyPostfix] private static void CombatSquadAwakePostfix(CombatSquad __instance) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) BossGroup component = ((Component)__instance).GetComponent(); if ((Object)(object)component != (Object)null && PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug($"[TeleporterDiagnostics] CombatSquad awakened with BossGroup {((Object)component).name}, netId={((NetworkBehaviour)__instance).netId}"); if (!((Behaviour)component).isActiveAndEnabled) { Log.Warning("[TeleporterDiagnostics] BossGroup " + ((Object)component).name + " is not active when CombatSquad awakened!"); } } } } [HarmonyPatch] public static class TeleporterSafetyPatches { [HarmonyFinalizer] [HarmonyPatch(typeof(OutsideInteractableLocker), "FixedUpdate")] public static Exception? LockerFixedUpdateFinalizer(Exception? __exception) { return null; } [HarmonyFinalizer] [HarmonyPatch(typeof(OutsideInteractableLocker), "OnDisable")] public static Exception? LockerOnDisableFinalizer(Exception? __exception) { return null; } [HarmonyFinalizer] [HarmonyPatch(typeof(OutsideInteractableLocker), "UnlockAll")] public static Exception? LockerUnlockAllFinalizer(Exception? __exception) { return null; } [HarmonyPrefix] [HarmonyPatch(typeof(BossGroup), "DropRewards")] public static void BossGroupDropRewardsPrefix(BossGroup __instance) { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown if (NetworkServer.active && !(ReflectionCache.BossGroup.rng == null) && ((Object)(object)__instance.dropTable == (Object)null || ReflectionCache.BossGroup.rng.GetValue(__instance) == null)) { Log.Debug("[BossGroupSafety] " + ((Object)__instance).name + " is missing critical reward data: " + $"dropTable={(Object)(object)__instance.dropTable != (Object)null}, " + $"rng={ReflectionCache.BossGroup.rng.GetValue(__instance) != null}"); if ((Object)(object)__instance.dropTable == (Object)null) { __instance.dropTable = Addressables.LoadAssetAsync((object)"RoR2/Base/Common/dtTier2Item.asset").WaitForCompletion(); } if (ReflectionCache.BossGroup.rng.GetValue(__instance) == null) { ulong num = ((Run.instance?.bossRewardRng != null) ? Run.instance.bossRewardRng.nextUlong : ((ulong)DateTime.Now.Ticks)); ReflectionCache.BossGroup.rng.SetValue(__instance, (object?)new Xoroshiro128Plus(num)); } Log.Debug("[BossGroupSafety] Fallback injection complete for " + ((Object)__instance).name + "."); } } } } namespace DrifterBossGrabMod.Core { public class BaggedObjectStateData { private static readonly FieldInfo _targetBodyField = ReflectionCache.BaggedObject.TargetBody; private static readonly FieldInfo _isBodyField = ReflectionCache.BaggedObject.IsBody; private static readonly FieldInfo _vehiclePassengerAttributesField = ReflectionCache.BaggedObject.VehiclePassengerAttributes; private static readonly FieldInfo _baggedMassField = ReflectionCache.BaggedObject.BaggedMass; private static readonly FieldInfo _bagScale01Field = ReflectionCache.BaggedObject.BagScale01; private static readonly FieldInfo _movespeedPenaltyField = ReflectionCache.BaggedObjectAdditional.MovespeedPenalty; private static readonly FieldInfo? _attackSpeedStatField = ReflectionCache.BaggedObjectAdditional.AttackSpeedStat; private static readonly FieldInfo? _damageStatField = ReflectionCache.BaggedObjectAdditional.DamageStat; private static readonly FieldInfo? _critStatField = ReflectionCache.BaggedObjectAdditional.CritStat; private static readonly FieldInfo? _moveSpeedStatField = ReflectionCache.BaggedObjectAdditional.MoveSpeedStat; private static readonly FieldInfo _drifterBagControllerField = ReflectionCache.BaggedObject.DrifterBagController; public CharacterBody? targetBody; public GameObject? targetObject; public bool isBody; public float baggedMass; public float bagScale01; public float movespeedPenalty; public float attackSpeedStat; public float damageStat; public float critStat; public float moveSpeedStat; public float armorStat; public float regenStat; public float baseMaxHealth; public float baseRegen; public float baseMaxShield; public float baseMoveSpeed; public float baseDamage; public float baseAttackSpeed; public float baseArmor; public float baseCrit; public float level; public float experience; public uint teamIndex; public bool isElite; public BodyFlags bodyFlags; public string? subtitleNameToken; public uint skinIndex; public int junkSpawnCount; public float breakoutTime = 10f; public float breakoutAttempts; public float elapsedBreakoutTime; public int smacks; public bool hasCapturedModelTransformState; public SpecialObjectAttributes? vehiclePassengerAttributes; public bool originalIsKinematic; public bool originalUseGravity; public float originalMass; public float originalDrag; public float originalAngularDrag; public bool hasCapturedRigidbodyState; public void CaptureFromBaggedObject(BaggedObject state) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Expected I4, but got Unknown //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_034d: Unknown result type (might be due to invalid IL or missing references) //IL_0353: Expected O, but got Unknown if (state == null) { Log.Error("[BaggedObjectStateData] Cannot capture from null BaggedObject"); return; } try { targetBody = (CharacterBody)(_targetBodyField?.GetValue(state)); isBody = _isBodyField != null && (bool)_isBodyField.GetValue(state); vehiclePassengerAttributes = (SpecialObjectAttributes)(_vehiclePassengerAttributesField?.GetValue(state)); targetObject = state.targetObject; baggedMass = ((_baggedMassField != null) ? ((float)_baggedMassField.GetValue(state)) : 0f); bagScale01 = ((_bagScale01Field != null) ? ((float)_bagScale01Field.GetValue(state)) : 0.5f); movespeedPenalty = ((_movespeedPenaltyField != null) ? ((float)_movespeedPenaltyField.GetValue(state)) : 0f); attackSpeedStat = ((_attackSpeedStatField != null) ? ((float)_attackSpeedStatField.GetValue(state)) : 1f); damageStat = ((_damageStatField != null) ? ((float)_damageStatField.GetValue(state)) : 0f); critStat = ((_critStatField != null) ? ((float)_critStatField.GetValue(state)) : 0f); moveSpeedStat = ((_moveSpeedStatField != null) ? ((float)_moveSpeedStatField.GetValue(state)) : 0f); if ((Object)(object)targetBody != (Object)null) { armorStat = targetBody.armor; regenStat = targetBody.regen; baseMaxHealth = targetBody.baseMaxHealth; baseRegen = targetBody.baseRegen; baseMaxShield = targetBody.baseMaxShield; baseMoveSpeed = targetBody.baseMoveSpeed; baseDamage = targetBody.baseDamage; baseAttackSpeed = targetBody.baseAttackSpeed; baseArmor = targetBody.baseArmor; baseCrit = targetBody.baseCrit; level = 0f; experience = targetBody.experience; teamIndex = (uint)(int)targetBody.teamComponent.teamIndex; isElite = targetBody.isElite; bodyFlags = targetBody.bodyFlags; subtitleNameToken = targetBody.subtitleNameToken; skinIndex = targetBody.skinIndex; } if (ReflectionCache.BaggedObject.BreakoutTime != null) { breakoutTime = (float)ReflectionCache.BaggedObject.BreakoutTime.GetValue(state); } if (ReflectionCache.BaggedObject.BreakoutAttempts != null) { breakoutAttempts = (float)ReflectionCache.BaggedObject.BreakoutAttempts.GetValue(state); } if (ReflectionCache.EntityState.FixedAge != null) { elapsedBreakoutTime = (float)ReflectionCache.EntityState.FixedAge.GetValue(state); } DrifterBagController val = (DrifterBagController)(_drifterBagControllerField?.GetValue(state)); if ((Object)(object)val != (Object)null && ReflectionCache.DrifterBagController.Smacks != null) { smacks = Convert.ToInt32(ReflectionCache.DrifterBagController.Smacks.GetValue(val)); } string[] obj = new string[5] { "[BaggedObjectStateData] Captured state for ", null, null, null, null }; GameObject? obj2 = targetObject; obj[1] = ((obj2 != null) ? ((Object)obj2).name : null) ?? "null"; obj[2] = ": "; obj[3] = $"mass={baggedMass}, scale={bagScale01}, penalty={movespeedPenalty}, "; obj[4] = $"damage={damageStat}, attackSpeed={attackSpeedStat}, crit={critStat}, moveSpeed={moveSpeedStat}"; Log.Debug(string.Concat(obj)); } catch (Exception ex) { Log.Error("[BaggedObjectStateData] Error capturing from BaggedObject: " + ex.Message); } } public void CaptureBreakoutStateFromBaggedObject(BaggedObject state) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown if (state == null) { return; } try { if (ReflectionCache.BaggedObject.BreakoutTime != null) { breakoutTime = (float)ReflectionCache.BaggedObject.BreakoutTime.GetValue(state); } if (ReflectionCache.BaggedObject.BreakoutAttempts != null) { breakoutAttempts = (float)ReflectionCache.BaggedObject.BreakoutAttempts.GetValue(state); } if (ReflectionCache.EntityState.FixedAge != null) { elapsedBreakoutTime = (float)ReflectionCache.EntityState.FixedAge.GetValue(state); } DrifterBagController val = (DrifterBagController)(_drifterBagControllerField?.GetValue(state)); if ((Object)(object)val != (Object)null && ReflectionCache.DrifterBagController.Smacks != null) { smacks = (int)ReflectionCache.DrifterBagController.Smacks.GetValue(val); } GameObject? obj = targetObject; Log.Debug("[BaggedObjectStateData] Captured breakout state for " + (((obj != null) ? ((Object)obj).name : null) ?? "null") + ": " + $"age={elapsedBreakoutTime}, breakoutTime={breakoutTime}"); } catch (Exception ex) { Log.Error("[BaggedObjectStateData] Error capturing breakout state from BaggedObject: " + ex.Message); } } public void ApplyToBaggedObject(BaggedObject state) { //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown if (state == null) { Log.Error("[BaggedObjectStateData] Cannot apply to null BaggedObject"); return; } if ((Object)(object)targetObject == (Object)null && baggedMass == 0f) { Log.Debug("[BaggedObjectStateData] Skipping application of uninitialized 'stub' state (targetObject is null)."); return; } if (!((Object)(object)targetObject == (Object)null)) { Object val = (Object)(object)targetObject; if (val == null || Object.op_Implicit(val)) { try { _targetBodyField?.SetValue(state, targetBody); _isBodyField?.SetValue(state, isBody); _vehiclePassengerAttributesField?.SetValue(state, vehiclePassengerAttributes); state.targetObject = targetObject; _baggedMassField?.SetValue(state, baggedMass); _bagScale01Field?.SetValue(state, bagScale01); _movespeedPenaltyField?.SetValue(state, movespeedPenalty); _attackSpeedStatField?.SetValue(state, attackSpeedStat); _damageStatField?.SetValue(state, damageStat); _critStatField?.SetValue(state, critStat); _moveSpeedStatField?.SetValue(state, moveSpeedStat); if (ReflectionCache.BaggedObject.BreakoutTime != null && breakoutTime > 0f) { ReflectionCache.BaggedObject.BreakoutTime.SetValue(state, breakoutTime); } if (ReflectionCache.BaggedObject.BreakoutAttempts != null && breakoutAttempts > 0f) { ReflectionCache.BaggedObject.BreakoutAttempts.SetValue(state, breakoutAttempts); } if (ReflectionCache.EntityState.FixedAge != null && elapsedBreakoutTime > 0f) { ReflectionCache.EntityState.FixedAge.SetValue(state, elapsedBreakoutTime); } DrifterBagController val2 = (DrifterBagController)(_drifterBagControllerField?.GetValue(state)); if ((Object)(object)val2 != (Object)null && ReflectionCache.DrifterBagController.Smacks != null) { ReflectionCache.DrifterBagController.Smacks.SetValue(val2, smacks); } if ((Object)(object)targetBody != (Object)null) { ApplyToCharacterBody(targetBody); } if (PluginConfig.Instance.EnableDebugLogs.Value) { string text = (((Object)(object)targetObject != (Object)null) ? ((Object)targetObject).name : (((Object)(object)state.targetObject != (Object)null) ? ((Object)state.targetObject).name : "null")); Log.Debug("[BaggedObjectStateData] Applied state to " + text + ": " + $"mass={baggedMass}, age={elapsedBreakoutTime}, scale={bagScale01}, penalty={movespeedPenalty}, " + $"damage={damageStat}, attackSpeed={attackSpeedStat}, crit={critStat}, moveSpeed={moveSpeedStat}, " + $"level={level}, isElite={isElite}"); } return; } catch (Exception ex) { Log.Error("[BaggedObjectStateData] Error applying to BaggedObject: " + ex.Message); return; } } } Log.Debug("[BaggedObjectStateData] Skipping application - targetObject is null or destroyed."); } public void ApplyToCharacterBody(CharacterBody body) { //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null) { return; } Log.Debug($"[ApplyToCharacterBody] ENTRY: body.name={((Object)body).name}, body.baseMaxHealth={body.baseMaxHealth}, state.baseMaxHealth={baseMaxHealth}"); if (baseMaxHealth <= 0f) { Log.Warning($"[ApplyToCharacterBody] ABORTED: Attempting to apply INVALID baseMaxHealth={baseMaxHealth} to {((Object)body).name}. This would have killed the object. State state is likely uninitialized."); return; } try { body.baseMaxHealth = baseMaxHealth; Log.Debug($"[ApplyToCharacterBody] AFTER SET: body.baseMaxHealth={body.baseMaxHealth}"); body.baseRegen = baseRegen; body.baseMaxShield = baseMaxShield; body.baseMoveSpeed = baseMoveSpeed; body.baseDamage = baseDamage; body.baseAttackSpeed = baseAttackSpeed; body.baseArmor = baseArmor; body.baseCrit = baseCrit; body.experience = experience; body.teamComponent.teamIndex = (TeamIndex)(sbyte)teamIndex; body.bodyFlags = bodyFlags; body.subtitleNameToken = subtitleNameToken ?? body.subtitleNameToken; body.skinIndex = skinIndex; body.RecalculateStats(); Log.Debug($"[ApplyToCharacterBody] Captured stats: baseMaxHealth={baseMaxHealth}, baseRegen={baseRegen}, baseDamage={baseDamage}, level={level}"); if (baseMaxHealth <= 0f) { Log.Error($"[ApplyToCharacterBody] CRITICAL: Attempting to apply INVALID baseMaxHealth={baseMaxHealth} to {((Object)body).name}! This will kill the object!"); } } catch (Exception ex) { Log.Error("[BaggedObjectStateData] Error applying to CharacterBody: " + ex.Message); } } public void RestorePhysicsAndHurtboxes(GameObject target) { if ((Object)(object)target == (Object)null) { return; } Rigidbody component = target.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { if (hasCapturedRigidbodyState) { component.isKinematic = originalIsKinematic; component.useGravity = originalUseGravity; component.mass = originalMass; component.drag = originalDrag; component.angularDrag = originalAngularDrag; component.detectCollisions = true; } else { component.isKinematic = false; component.detectCollisions = true; } } CharacterBody component2 = target.GetComponent(); if (!((Object)(object)component2 != (Object)null) || !((Object)(object)component2.modelLocator != (Object)null)) { return; } Transform modelTransform = component2.modelLocator.modelTransform; if ((Object)(object)modelTransform != (Object)null) { HurtBoxGroup component3 = ((Component)modelTransform).GetComponent(); if ((Object)(object)component3 != (Object)null && component3.hurtBoxesDeactivatorCounter > 0) { int hurtBoxesDeactivatorCounter = component3.hurtBoxesDeactivatorCounter; component3.hurtBoxesDeactivatorCounter = 0; Log.Debug($"[BaggedObjectStateData] Reset hurtBoxesDeactivatorCounter from {hurtBoxesDeactivatorCounter} to 0 for {((Object)target).name}"); } } } public void CalculateFromObject(GameObject targetObject, DrifterBagController controller) { //IL_07fe: 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) //IL_0684: Expected I4, but got Unknown //IL_069c: Unknown result type (might be due to invalid IL or missing references) //IL_06a1: Unknown result type (might be due to invalid IL or missing references) if (PluginConfig.Instance.EnableDebugLogs.Value) { StackTrace stackTrace = new StackTrace(); MethodBase method = stackTrace.GetFrame(1).GetMethod(); Log.Debug("[CalculateFromObject] ENTRY: targetObject=" + (((targetObject != null) ? ((Object)targetObject).name : null) ?? "null") + ", caller=" + method?.DeclaringType?.Name + "." + method?.Name); string text = ""; for (int i = 1; i < Math.Min(stackTrace.FrameCount, 5); i++) { MethodBase method2 = stackTrace.GetFrame(i).GetMethod(); text = text + " -> " + method2.DeclaringType?.Name + "." + method2.Name; } Log.Debug("[CalculateFromObject] CALL STACK: " + text); } if ((Object)(object)targetObject == (Object)null) { Log.Error("[BaggedObjectStateData] Cannot calculate from null targetObject"); return; } if ((Object)(object)controller == (Object)null) { Log.Error("[BaggedObjectStateData] Cannot calculate from null controller"); return; } try { this.targetObject = targetObject; HealthComponent component = targetObject.GetComponent(); targetBody = targetObject.GetComponent(); isBody = (Object)(object)component != (Object)null; vehiclePassengerAttributes = targetObject.GetComponent(); Rigidbody component2 = targetObject.GetComponent(); if ((Object)(object)component2 != (Object)null && !hasCapturedRigidbodyState) { originalIsKinematic = component2.isKinematic; originalUseGravity = component2.useGravity; originalMass = component2.mass; originalDrag = component2.drag; originalAngularDrag = component2.angularDrag; hasCapturedRigidbodyState = true; } if (PluginConfig.Instance.EnableDebugLogs.Value) { Log.Debug("[CalculateFromObject] targetObject=" + ((Object)targetObject).name + ", targetBody=" + (((Object)(object)targetBody != (Object)null) ? ((Object)targetBody).name : "null") + ", healthComponent=" + (((Object)(object)component != (Object)null) ? "exists" : "null")); if ((Object)(object)component != (Object)null && (Object)(object)component.body != (Object)null) { Log.Debug($"[CalculateFromObject] healthComponent.body={((Object)component.body).name}, healthComponent.body.baseMaxHealth={component.body.baseMaxHealth}"); } if ((Object)(object)targetBody != (Object)null) { Log.Debug($"[CalculateFromObject] targetBody.baseMaxHealth={targetBody.baseMaxHealth}"); } } baggedMass = controller.CalculateBaggedObjectMass(targetObject); float num = baggedMass; float num2 = (((Object)(object)controller != (Object)null) ? CapacityScalingSystem.CalculateMassCapacity(controller) : DrifterBagController.maxMass); if (!PluginConfig.Instance.EnableBalance.Value || !PluginConfig.Instance.IsBagScaleCapInfinite) { float num3 = 1f; if (float.TryParse(PluginConfig.Instance.BagScaleCap.Value, out var result) && result > 1f) { num3 = result; } num = Mathf.Clamp(baggedMass, 1f, num2); } else { num = Mathf.Max(baggedMass, 1f); } float num4 = (num - 1f) / (num2 - 1f); bagScale01 = 0.5f + 0.5f * num4; float num5 = 0f; if (PluginConfig.Instance.EnableBalance.Value && (Object)(object)controller != (Object)null) { CharacterBody component3 = ((Component)controller).GetComponent(); float value = (((Object)(object)component3 != (Object)null) ? component3.maxHealth : 0f); float value2 = (((Object)(object)component3 != (Object)null) ? component3.level : 1f); float num6 = (((Object)(object)component3 != (Object)null && (Object)(object)component3.skillLocator != (Object)null && (Object)(object)component3.skillLocator.utility != (Object)null) ? ((float)component3.skillLocator.utility.maxStock) : 1f); float value3 = (((Object)(object)controller != (Object)null) ? CapacityScalingSystem.CalculateMassCapacity(controller) : DrifterBagController.maxMass); float value4 = (((Object)(object)controller != (Object)null) ? ((float)CapacityScalingSystem.GetTotalCapacity(controller)) : 1f); float result2 = 700f; string value5 = PluginConfig.Instance.MassCap.Value; if (string.Equals(value5, "INF", StringComparison.OrdinalIgnoreCase) || string.Equals(value5, "Infinity", StringComparison.OrdinalIgnoreCase)) { result2 = float.MaxValue; } else if (!float.TryParse(value5, out result2)) { result2 = 700f; } Dictionary variables = new Dictionary { ["T"] = baggedMass, ["M"] = value3, ["C"] = value4, ["H"] = value, ["L"] = value2, ["MC"] = result2 }; num5 = FormulaParser.Evaluate(PluginConfig.Instance.MovespeedPenaltyFormula.Value, variables); } movespeedPenalty = num5; Log.Debug("[CalculateFromObject] About to capture stats. targetBody=" + (((Object)(object)targetBody != (Object)null) ? "NOT NULL" : "NULL")); if ((Object)(object)targetBody != (Object)null) { attackSpeedStat = targetBody.attackSpeed; damageStat = targetBody.baseDamage; critStat = targetBody.crit; moveSpeedStat = targetBody.moveSpeed; armorStat = targetBody.armor; regenStat = targetBody.regen; baseMaxHealth = targetBody.baseMaxHealth; baseRegen = targetBody.baseRegen; baseMaxShield = targetBody.baseMaxShield; baseMoveSpeed = targetBody.baseMoveSpeed; baseDamage = targetBody.baseDamage; baseAttackSpeed = targetBody.baseAttackSpeed; baseArmor = targetBody.baseArmor; baseCrit = targetBody.baseCrit; level = 0f; experience = targetBody.experience; teamIndex = (uint)(int)targetBody.teamComponent.teamIndex; isElite = targetBody.isElite; bodyFlags = targetBody.bodyFlags; subtitleNameToken = targetBody.subtitleNameToken; skinIndex = targetBody.skinIndex; if (PluginConfig.Instance.EnableDebugLogs.Value) { if (baseMaxHealth <= 0f) { Log.Error($"[CalculateFromObject] CRITICAL: Captured INVALID baseMaxHealth={baseMaxHealth} for {((Object)targetObject).name}! This will cause instant death on restoration."); } else { Log.Debug($"[CalculateFromObject] Captured valid stats for {((Object)targetObject).name}: baseMaxHealth={baseMaxHealth}, level={level}"); } } } else { attackSpeedStat = 1f; damageStat = 0f; critStat = 0f; moveSpeedStat = 0f; armorStat = 0f; regenStat = 0f; baseMaxHealth = 0f; baseRegen = 0f; baseMaxShield = 0f; baseMoveSpeed = 0f; baseDamage = 0f; baseAttackSpeed = 0f; baseArmor = 0f; baseCrit = 0f; level = 1f; experience = 0f; teamIndex = uint.MaxValue; isElite = false; bodyFlags = (BodyFlags)0; subtitleNameToken = null; skinIndex = 0u; } breakoutTime = 0f; breakoutAttempts = 0f; elapsedBreakoutTime = 0f; if (!hasCapturedModelTransformState) { ModelLocator component4 = targetObject.GetComponent(); if ((Object)(object)component4 != (Object)null) { hasCapturedModelTransformState = true; } } junkSpawnCount = CalculateJunkSpawnCount(baggedMass); Log.Debug("[BaggedObjectStateData] Calculated state for " + ((Object)targetObject).name + ": " + $"mass={baggedMass}, scale={bagScale01}, penalty={movespeedPenalty}, " + $"damage={damageStat}, attackSpeed={attackSpeedStat}, crit={critStat}, moveSpeed={moveSpeedStat}"); } catch (Exception ex) { Log.Error("[BaggedObjectStateData] Error calculating from object: " + ex.Message); } } public void CaptureFromAdditionalTimer(AdditionalSeatBreakoutTimer timer) { if (!((Object)(object)timer == (Object)null)) { breakoutTime = timer.breakoutTime; breakoutAttempts = timer.breakoutAttempts; elapsedBreakoutTime = timer.GetElapsedBreakoutTime(); Log.Debug($"[BaggedObjectStateData] Captured timer state from AdditionalSeat: age={elapsedBreakoutTime}, attempts={breakoutAttempts}"); } } private static int CalculateJunkSpawnCount(float mass) { return Mathf.Max(1, Mathf.CeilToInt(mass / 100f)); } public void ResetBreakoutData() { breakoutTime = 0f; breakoutAttempts = 0f; elapsedBreakoutTime = 0f; smacks = 0; GameObject? obj = targetObject; Log.Debug("[BaggedObjectStateData] Reset breakout data for " + (((obj != null) ? ((Object)obj).name : null) ?? "null")); } } public class BagState { private readonly HashSet _baggedObjectIds = new HashSet(); private bool _massDirty = true; public object BagLock { get; } = new object(); public List BaggedObjects { get; set; } = new List(); public ConcurrentDictionary AdditionalSeats { get; set; } = new ConcurrentDictionary(); public GameObject? MainSeatObject { get; set; } public GameObject? IncomingObject { get; set; } public int IntendedSelectedIndex { get; set; } = -1; public UncappedBagScaleComponent? UncappedBagScale { get; set; } public ConcurrentDictionary> DisabledCollidersByObject { get; } = new ConcurrentDictionary>(); public bool IsMassDirty => _massDirty; public void MarkMassDirty() { _massDirty = true; } internal void ClearMassDirty() { _massDirty = false; } public bool ContainsInstanceId(int instanceId) { return _baggedObjectIds.Contains(instanceId); } public void AddInstanceId(int instanceId) { _baggedObjectIds.Add(instanceId); } public void RemoveInstanceId(int instanceId) { _baggedObjectIds.Remove(instanceId); } } public static class MultiTeleporterTracker { private static List _cachedTeleporters = new List(); private static bool _teleportersDirty = true; private static TeleporterInteraction? _primaryTeleporter; private static readonly HashSet _secondaryTeleporters = new HashSet(); private static readonly HashSet _pendingInit = new HashSet(); private static readonly object _lock = new object(); public static void RegisterPrimary(TeleporterInteraction teleporter) { if (!PluginConfig.Instance.EnableObjectPersistence.Value || (Object)(object)teleporter == (Object)null) { return; } lock (_lock) { _primaryTeleporter = teleporter; Log.Debug($"[MultiTeleporterTracker] Registered primary teleporter: {((Object)((Component)teleporter).gameObject).name} (InstanceID: {((Object)teleporter).GetInstanceID()})"); } } public static void RegisterSecondary(TeleporterInteraction teleporter) { if (!PluginConfig.Instance.EnableObjectPersistence.Value || (Object)(object)teleporter == (Object)null) { return; } lock (_lock) { if (!((Object)(object)teleporter == (Object)(object)_primaryTeleporter)) { _secondaryTeleporters.Add(teleporter); Log.Debug($"[MultiTeleporterTracker] Registered secondary teleporter: {((Object)((Component)teleporter).gameObject).name} (InstanceID: {((Object)teleporter).GetInstanceID()})"); } } } public static void UnregisterSecondary(TeleporterInteraction teleporter) { if (!PluginConfig.Instance.EnableObjectPersistence.Value || (Object)(object)teleporter == (Object)null) { return; } lock (_lock) { if (_secondaryTeleporters.Remove(teleporter)) { Log.Debug("[MultiTeleporterTracker] Unregistered secondary teleporter: " + ((Object)((Component)teleporter).gameObject).name); } } } public static TeleporterInteraction? GetPrimary() { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return null; } lock (_lock) { return _primaryTeleporter; } } public static bool IsSecondary(TeleporterInteraction teleporter) { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return false; } lock (_lock) { return _secondaryTeleporters.Contains(teleporter); } } public static void MarkPendingInit(TeleporterInteraction teleporter) { if (!PluginConfig.Instance.EnableObjectPersistence.Value || (Object)(object)teleporter == (Object)null) { return; } lock (_lock) { _pendingInit.Add(teleporter); } } public static void Clear() { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return; } lock (_lock) { _primaryTeleporter = null; _secondaryTeleporters.Clear(); _pendingInit.Clear(); InvalidateCache(); Log.Debug("[MultiTeleporterTracker] Cleared teleporter registry"); } } public static void InvalidateCache() { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return; } lock (_lock) { _teleportersDirty = true; } } public static List GetTeleporters() { if (!PluginConfig.Instance.EnableObjectPersistence.Value) { return new List(); } lock (_lock) { if (_teleportersDirty) { _cachedTeleporters = Object.FindObjectsByType((FindObjectsSortMode)0).ToList(); _teleportersDirty = false; } return _cachedTeleporters; } } } public static class SlamDamageCalculator { public const float DefaultBaseDamageCoef = 2.8f; public const float DefaultMassScaling = 5f; public static float GetPredictedDamage(DrifterBagController? bagController, GameObject? target) { if ((Object)(object)bagController == (Object)null || (Object)(object)target == (Object)null) { return 0f; } CharacterBody component = ((Component)bagController).GetComponent(); if (!Object.op_Implicit((Object)(object)component)) { return 0f; } float num = GetEffectiveCoefficient(bagController); if (PluginConfig.Instance.EnableBalance.Value && PluginConfig.Instance.AoEDamageDistribution.Value != 0 && PluginConfig.Instance.StateCalculationMode.Value == StateCalculationMode.All && PluginConfig.Instance.AoEDamageDistribution.Value == AoEDamageMode.Split) { BagState state = BagPatches.GetState(bagController); int num2 = state.BaggedObjects?.Count ?? 1; if (num2 > 1) { num /= (float)num2; } } float num3 = component.damage * num; float itemDamageMultiplier = GetItemDamageMultiplier(component); float num4 = num3 * itemDamageMultiplier; CharacterBody component2 = target.GetComponent(); if ((Object)(object)component2 != (Object)null) { float armor = component2.armor; float num5 = ((armor >= 0f) ? (100f / (100f + armor)) : (2f - 100f / (100f - armor))); num4 = Mathf.Max(1f, num4 * num5); } return num4; } public static float GetPredictedDamageFraction(DrifterBagController? bagController, GameObject? target) { if ((Object)(object)bagController == (Object)null || (Object)(object)target == (Object)null) { return 0f; } JunkCubeController component = target.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { if (ReflectionCache.JunkCubeController.MaxActivationCount != null) { int num = (int)ReflectionCache.JunkCubeController.MaxActivationCount.GetValue(component); if (num > 0) { return 1f / (float)num; } } return 0.334f; } CharacterBody component2 = target.GetComponent(); if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.healthComponent)) { float fullCombinedHealth = component2.healthComponent.fullCombinedHealth; if (fullCombinedHealth <= 0f) { return 1f; } float predictedDamage = GetPredictedDamage(bagController, target); return Mathf.Clamp01(predictedDamage / fullCombinedHealth); } SpecialObjectAttributes component3 = target.GetComponent(); if (Object.op_Implicit((Object)(object)component3) && component3.maxDurability > 0) { return 1f / (float)component3.maxDurability; } return 0f; } public static float GetEffectiveCoefficient(DrifterBagController? bagController) { float num = bagController?.baggedMass ?? 0f; if (!PluginConfig.Instance.EnableBalance.Value) { return 2.8f + 5f * num / DrifterBagController.maxMass; } CharacterBody body = ((bagController != null) ? ((Component)bagController).GetComponent() : null); float num2 = (((Object)(object)bagController != (Object)null) ? CapacityScalingSystem.CalculateMassCapacity(bagController) : DrifterBagController.maxMass); Dictionary localVars = new Dictionary { { "BASE_COEF", 2.8f }, { "MASS_SCALING", 5f }, { "BM", num }, { "MC", num2 } }; string value = PluginConfig.Instance.SlamDamageFormula.Value; float num3 = FormulaParser.Evaluate(value, body, localVars); if (float.IsNaN(num3)) { Log.Warning("[SlamDamageCalculator] Formula '" + value + "' returned NaN. Using default calculation."); num3 = 2.8f + 5f * num / num2; } else if (float.IsInfinity(num3)) { Log.Warning("[SlamDamageCalculator] Formula '" + value + "' returned Infinity. Using default calculation."); num3 = 2.8f + 5f * num / num2; } return num3; } private static float GetItemDamageMultiplier(CharacterBody attackerBody) { if ((Object)(object)attackerBody == (Object)null || (Object)(object)attackerBody.inventory == (Object)null) { return 1f; } float num = 1f; int itemCountEffective = attackerBody.inventory.GetItemCountEffective(Items.FragileDamageBonus); if (itemCountEffective > 0) { num *= 1f + (float)itemCountEffective * 0.2f; } int itemCountEffective2 = attackerBody.inventory.GetItemCountEffective(Items.NearbyDamageBonus); if (itemCountEffective2 > 0) { num *= 1f + (float)itemCountEffective2 * 0.2f; } return num; } public static void LogDetails(DrifterBagController? bagController, GameObject? target) { if (!PluginConfig.Instance.EnableDebugLogs.Value) { return; } float num = 2.8f; float num2 = 5f; bool flag = false; if ((Object)(object)bagController != (Object)null) { EntityStateMachine[] components = ((Component)bagController).GetComponents(); EntityStateMachine[] array = components; foreach (EntityStateMachine val in array) { EntityState state = val.state; SuffocateSlam val2 = (SuffocateSlam)(object)((state is SuffocateSlam) ? state : null); if (val2 != null) { num = ((BasicMeleeAttack)val2).damageCoefficient; num2 = val2.damageCoefficientIncreaseWithMass; flag = true; break; } } } float num3 = (((Object)(object)bagController != (Object)null) ? bagController.baggedMass : 0f); float num4 = (((Object)(object)bagController != (Object)null) ? CapacityScalingSystem.CalculateMassCapacity(bagController) : DrifterBagController.maxMass); float num5 = (((Object)(object)bagController != (Object)null && num4 > 0f) ? (bagController.baggedMass / num4) : 0f); float num6 = (flag ? num : (num + num2 * num5)); CharacterBody val3 = (Object.op_Implicit((Object)(object)bagController) ? ((Component)bagController).GetComponent() : null); float num7 = (Object.op_Implicit((Object)(object)val3) ? val3.damage : 0f); float num8 = num7 * num6; float predictedDamage = GetPredictedDamage(bagController, target); if ((Object)(object)target == (Object)null) { return; } JunkCubeController component = target.GetComponent(); CharacterBody component2 = target.GetComponent(); if (Object.op_Implicit((Object)(object)component)) { FieldInfo field = typeof(JunkCubeController).GetField("_maxActivationCount", BindingFlags.Instance | BindingFlags.NonPublic); int num9 = ((field != null) ? ((int)field.GetValue(component)) : 3); float num10 = ((num9 > 0) ? (1f / (float)num9) : 0f); Log.Debug($" FractionPath: JUNK_CUBE (ActivationCount logic: 1/{num9} = {num10:F3})"); } else if (Object.op_Implicit((Object)(object)component2) && Object.op_Implicit((Object)(object)component2.healthComponent)) { float fullCombinedHealth = component2.healthComponent.fullCombinedHealth; float num11 = ((fullCombinedHealth > 0f) ? Mathf.Clamp01(predictedDamage / fullCombinedHealth) : 1f); Log.Debug($" FractionPath: HEALTH (hp={component2.healthComponent.combinedHealth:F1}/{fullCombinedHealth:F1}, previewFrac={num11:F3})"); } else { SpecialObjectAttributes component3 = target.GetComponent(); if (Object.op_Implicit((Object)(object)component3) && component3.maxDurability > 0) { Log.Debug($" FractionPath: DURABILITY (durability={component3.durability}/{component3.maxDurability}, previewFrac={1f / (float)component3.maxDurability:F3})"); } else { Log.Debug($" FractionPath: NONE (hasAttributes={(Object)(object)component3 != (Object)null}, hasBody={(Object)(object)component2 != (Object)null}, hasHC={(Object)(object)((component2 != null) ? component2.healthComponent : null) != (Object)null})"); } } } } public static class StateCalculator { public static BaggedObjectStateData CalculateState(DrifterBagController controller, GameObject targetObject, StateCalculationMode mode) { if (mode == StateCalculationMode.Current || (Object)(object)targetObject == (Object)null) { return GetIndividualObjectState(controller, targetObject); } return GetAggregateState(controller); } public static BaggedObjectStateData GetIndividualObjectState(DrifterBagController controller, GameObject targetObject) { if ((Object)(object)targetObject == (Object)null) { Log.Debug("[STATE CREATION] GetIndividualObjectState returning empty state for null targetObject"); return new BaggedObjectStateData(); } Log.Debug("[GetIndividualObjectState] Checking for existing state for " + ((Object)targetObject).name); float num = 0f; float num2 = 0f; float num3 = 0f; bool flag = false; BaggedObject currentBaggedObjectState = GetCurrentBaggedObjectState(controller); if (currentBaggedObjectState != null && (Object)(object)currentBaggedObjectState.targetObject == (Object)(object)targetObject) { flag = true; if (ReflectionCache.BaggedObject.BreakoutTime != null) { num = (float)ReflectionCache.BaggedObject.BreakoutTime.GetValue(currentBaggedObjectState); } if (ReflectionCache.BaggedObject.BreakoutAttempts != null) { num2 = (float)ReflectionCache.BaggedObject.BreakoutAttempts.GetValue(currentBaggedObjectState); } if (ReflectionCache.EntityState.FixedAge != null) { num3 = (float)ReflectionCache.EntityState.FixedAge.GetValue(currentBaggedObjectState); } } AdditionalSeatBreakoutTimer component = targetObject.GetComponent(); if ((Object)(object)component != (Object)null) { flag = true; num = component.breakoutTime; num2 = component.breakoutAttempts; num3 = component.GetElapsedBreakoutTime(); } BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(controller, targetObject); BaggedObjectStateData baggedObjectStateData2; if (baggedObjectStateData != null) { Log.Debug($"[STATE REUSE] GetIndividualObjectState reusing stored state for {((Object)targetObject).name}: baseMaxHealth={baggedObjectStateData.baseMaxHealth}"); baggedObjectStateData2 = baggedObjectStateData; } else { Log.Debug("[STATE CREATION] GetIndividualObjectState creating new state for " + ((Object)targetObject).name); baggedObjectStateData2 = new BaggedObjectStateData(); baggedObjectStateData2.CalculateFromObject(targetObject, controller); } if (flag) { if (num > 0f || baggedObjectStateData2.breakoutTime == 0f) { baggedObjectStateData2.breakoutTime = num; } if (num2 > 0f || baggedObjectStateData2.breakoutAttempts == 0f) { baggedObjectStateData2.breakoutAttempts = num2; } if (num3 > baggedObjectStateData2.elapsedBreakoutTime) { baggedObjectStateData2.elapsedBreakoutTime = num3; } } return baggedObjectStateData2; } public static BaggedObjectStateData GetAggregateState(DrifterBagController controller) { //IL_021c: Unknown result type (might be due to invalid IL or missing references) //IL_0221: Unknown result type (might be due to invalid IL or missing references) List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { Log.Debug("[STATE CREATION] GetAggregateState returning empty state - baggedObjects is null"); return new BaggedObjectStateData(); } float num = 0f; float num2 = 0f; float num3 = 0f; BaggedObject currentBaggedObjectState = GetCurrentBaggedObjectState(controller); if (currentBaggedObjectState != null) { if (ReflectionCache.BaggedObject.BreakoutTime != null) { num = (float)ReflectionCache.BaggedObject.BreakoutTime.GetValue(currentBaggedObjectState); } if (ReflectionCache.BaggedObject.BreakoutAttempts != null) { num2 = (float)ReflectionCache.BaggedObject.BreakoutAttempts.GetValue(currentBaggedObjectState); } if (ReflectionCache.EntityState.FixedAge != null) { num3 = (float)ReflectionCache.EntityState.FixedAge.GetValue(currentBaggedObjectState); } if ((Object)(object)currentBaggedObjectState.targetObject != (Object)null) { BaggedObjectStateData baggedObjectStateData = BaggedObjectPatches.LoadObjectState(controller, currentBaggedObjectState.targetObject); if (baggedObjectStateData != null && baggedObjectStateData.elapsedBreakoutTime > num3) { num3 = baggedObjectStateData.elapsedBreakoutTime; } } } BaggedObjectStateData baggedObjectStateData2 = new BaggedObjectStateData(); GameObject val = BagPatches.GetMainSeatObject(controller); if ((Object)(object)val == (Object)null) { val = BaggedObjectPatches.GetMainSeatOccupant(controller); } if ((Object)(object)val != (Object)null) { BaggedObjectStateData baggedObjectStateData3 = BaggedObjectPatches.LoadObjectState(controller, val); if (baggedObjectStateData3 != null) { Log.Debug($"[GetAggregateState] Using stored state for main passenger {((Object)val).name}: level={baggedObjectStateData3.level}"); baggedObjectStateData2.targetObject = baggedObjectStateData3.targetObject ?? val; baggedObjectStateData2.targetBody = baggedObjectStateData3.targetBody; baggedObjectStateData2.isBody = baggedObjectStateData3.isBody; baggedObjectStateData2.vehiclePassengerAttributes = baggedObjectStateData3.vehiclePassengerAttributes; baggedObjectStateData2.baseMaxHealth = baggedObjectStateData3.baseMaxHealth; baggedObjectStateData2.baseRegen = baggedObjectStateData3.baseRegen; baggedObjectStateData2.baseMaxShield = baggedObjectStateData3.baseMaxShield; baggedObjectStateData2.baseMoveSpeed = baggedObjectStateData3.baseMoveSpeed; baggedObjectStateData2.baseDamage = baggedObjectStateData3.baseDamage; baggedObjectStateData2.baseAttackSpeed = baggedObjectStateData3.baseAttackSpeed; baggedObjectStateData2.baseArmor = baggedObjectStateData3.baseArmor; baggedObjectStateData2.baseCrit = baggedObjectStateData3.baseCrit; baggedObjectStateData2.level = baggedObjectStateData3.level; baggedObjectStateData2.experience = baggedObjectStateData3.experience; baggedObjectStateData2.teamIndex = baggedObjectStateData3.teamIndex; baggedObjectStateData2.isElite = baggedObjectStateData3.isElite; baggedObjectStateData2.bodyFlags = baggedObjectStateData3.bodyFlags; baggedObjectStateData2.subtitleNameToken = baggedObjectStateData3.subtitleNameToken; baggedObjectStateData2.skinIndex = baggedObjectStateData3.skinIndex; } else { Log.Debug("[GetAggregateState] No stored state for " + ((Object)val).name + ", calculating from object"); baggedObjectStateData2.CalculateFromObject(val, controller); } } else { baggedObjectStateData2.targetObject = null; } baggedObjectStateData2.baggedMass = controller.baggedMass; float num4 = 0f; float num5 = 0f; float num6 = 0f; float num7 = 0f; int num8 = 0; int num9 = 0; foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && !ProjectileRecoveryPatches.IsInProjectileState(item)) { BaggedObjectStateData baggedObjectStateData4 = BaggedObjectPatches.LoadObjectState(controller, item); if (baggedObjectStateData4 != null) { num4 += baggedObjectStateData4.damageStat; num5 += baggedObjectStateData4.attackSpeedStat; num6 += baggedObjectStateData4.critStat; num7 += baggedObjectStateData4.moveSpeedStat; num8 += baggedObjectStateData4.junkSpawnCount; num9++; } } } if (num9 > 0) { baggedObjectStateData2.damageStat = num4 / (float)num9; baggedObjectStateData2.attackSpeedStat = num5 / (float)num9; baggedObjectStateData2.critStat = num6 / (float)num9; baggedObjectStateData2.moveSpeedStat = num7 / (float)num9; baggedObjectStateData2.junkSpawnCount = num8; } baggedObjectStateData2.movespeedPenalty = CalculateMovespeedPenalty(controller, baggedObjectStateData2.baggedMass); GameObject mainSeatObject = BagPatches.GetMainSeatObject(controller); if ((Object)(object)mainSeatObject != (Object)null) { baggedObjectStateData2.targetObject = mainSeatObject; HealthComponent component = mainSeatObject.GetComponent(); baggedObjectStateData2.targetBody = component?.body; baggedObjectStateData2.isBody = (Object)(object)component != (Object)null; baggedObjectStateData2.vehiclePassengerAttributes = mainSeatObject.GetComponent(); } baggedObjectStateData2.bagScale01 = CalculateBagScale01(controller, baggedObjectStateData2.baggedMass); if (num > 0f || baggedObjectStateData2.breakoutTime == 0f) { baggedObjectStateData2.breakoutTime = num; } if (num2 > 0f || baggedObjectStateData2.breakoutAttempts == 0f) { baggedObjectStateData2.breakoutAttempts = num2; } baggedObjectStateData2.elapsedBreakoutTime = num3; return baggedObjectStateData2; } private static BaggedObject? GetCurrentBaggedObjectState(DrifterBagController controller) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if ((Object)(object)controller == (Object)null) { return null; } EntityStateMachine[] componentsInChildren = ((Component)controller).GetComponentsInChildren(true); EntityStateMachine[] array = componentsInChildren; foreach (EntityStateMachine val in array) { if (val.state != null && ((object)val.state).GetType() == typeof(BaggedObject)) { return (BaggedObject)val.state; } } return null; } public static float CalculateMovespeedPenalty(DrifterBagController controller, float totalMass) { float result = 0f; if (PluginConfig.Instance.EnableBalance.Value) { CharacterBody component = ((Component)controller).GetComponent(); float value = (((Object)(object)component != (Object)null) ? component.maxHealth : 0f); float value2 = (((Object)(object)component != (Object)null) ? component.level : 1f); float num = (((Object)(object)component != (Object)null && (Object)(object)component.skillLocator != (Object)null && (Object)(object)component.skillLocator.utility != (Object)null) ? ((float)component.skillLocator.utility.maxStock) : 1f); float value3 = CapacityScalingSystem.CalculateMassCapacity(controller); float value4 = CapacityScalingSystem.GetTotalCapacity(controller); float result2 = 700f; string value5 = PluginConfig.Instance.MassCap.Value; if (string.Equals(value5, "INF", StringComparison.OrdinalIgnoreCase) || string.Equals(value5, "Infinity", StringComparison.OrdinalIgnoreCase)) { result2 = float.MaxValue; } else if (!float.TryParse(value5, out result2)) { result2 = 700f; } Dictionary variables = new Dictionary { ["T"] = totalMass, ["M"] = value3, ["C"] = value4, ["H"] = value, ["L"] = value2, ["MC"] = result2, ["S"] = ((!Object.op_Implicit((Object)(object)Run.instance)) ? 1 : (Run.instance.stageClearCount + 1)) }; result = FormulaParser.Evaluate(PluginConfig.Instance.MovespeedPenaltyFormula.Value, variables); } return result; } public static float CalculateBagScale01(DrifterBagController controller, float mass) { float num = (((Object)(object)controller != (Object)null) ? CapacityScalingSystem.CalculateMassCapacity(controller) : DrifterBagController.maxMass); float num2 = mass; num2 = ((PluginConfig.Instance.EnableBalance.Value && PluginConfig.Instance.IsBagScaleCapInfinite) ? Mathf.Max(mass, 1f) : Mathf.Clamp(mass, 1f, num)); float num3 = (num2 - 1f) / (num - 1f); return 0.5f + 0.5f * num3; } } public static class VisualRefreshUtility { public static void Refresh(GameObject target) { if ((Object)(object)target == (Object)null) { return; } Log.Debug("[VisualRefreshUtility] Starting refresh for " + ((Object)target).name); try { ModelLocator component = target.GetComponent(); Transform val = (((Object)(object)component != (Object)null && (Object)(object)component.modelTransform != (Object)null) ? component.modelTransform : target.transform); if (((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); ((Component)val).gameObject.SetActive(true); } CharacterModel component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.UpdateMaterials(); } FixBrokenMaterials(target, val); CleanupStuckVisualEffects(target); } catch (Exception ex) { Log.Error("[VisualRefreshUtility] Error during refresh of " + ((Object)target).name + ": " + ex.Message); } } private static void FixBrokenMaterials(GameObject target, Transform modelTransform) { Renderer[] componentsInChildren = ((Component)modelTransform).GetComponentsInChildren(true); Renderer[] array = componentsInChildren; foreach (Renderer val in array) { if ((Object)(object)val == (Object)null || !val.enabled || !((Component)val).gameObject.activeInHierarchy) { continue; } Material[] sharedMaterials = val.sharedMaterials; if (sharedMaterials == null || sharedMaterials.Length == 0) { continue; } for (int j = 0; j < sharedMaterials.Length; j++) { if ((Object)(object)sharedMaterials[j] == (Object)null || !IsValidMaterial(sharedMaterials[j])) { if (PluginConfig.Instance.EnableDebugLogs.Value) { string text = (((Object)(object)sharedMaterials[j] == (Object)null) ? "NULL" : ((Object)sharedMaterials[j]).name); Log.Debug($"[VisualRefreshUtility] Renderer '{((Object)val).name}' on {((Object)target).name} has invalid material at slot {j} (Mat: {text}). Disabling renderer."); } val.enabled = false; break; } } } } private static bool IsValidMaterial(Material? mat) { if ((Object)(object)mat == (Object)null) { return false; } if ((Object)(object)mat.shader == (Object)null) { return false; } string name = ((Object)mat.shader).name; if (!name.Contains("InternalError") && !name.Contains("Error")) { return name != "Hidden/InternalErrorShader"; } return false; } private static void CleanupStuckVisualEffects(GameObject target) { PrintController[] componentsInChildren = target.GetComponentsInChildren(true); PrintController[] array = componentsInChildren; foreach (PrintController val in array) { Log.Debug("[VisualRefreshUtility] Removing stuck PrintController from " + ((Object)target).name); Object.Destroy((Object)(object)val); } DitherModel[] componentsInChildren2 = target.GetComponentsInChildren(true); DitherModel[] array2 = componentsInChildren2; foreach (DitherModel val2 in array2) { Log.Debug("[VisualRefreshUtility] Removing stuck DitherModel from " + ((Object)target).name); Object.Destroy((Object)(object)val2); } } } } namespace DrifterBossGrabMod.Config { public static class PresetDefinitions { public static readonly Dictionary> Presets; static PresetDefinitions() { //IL_0409: Unknown result type (might be due to invalid IL or missing references) //IL_04fd: Unknown result type (might be due to invalid IL or missing references) //IL_0526: Unknown result type (might be due to invalid IL or missing references) //IL_054f: Unknown result type (might be due to invalid IL or missing references) //IL_0578: Unknown result type (might be due to invalid IL or missing references) //IL_05a1: Unknown result type (might be due to invalid IL or missing references) //IL_05ca: Unknown result type (might be due to invalid IL or missing references) //IL_0643: Unknown result type (might be due to invalid IL or missing references) //IL_0fed: Unknown result type (might be due to invalid IL or missing references) Dictionary> obj = new Dictionary> { [PresetType.Vanilla] = new Dictionary { ["General.EnableBossGrabbing"] = false, ["General.EnableNPCGrabbing"] = false, ["General.EnableEnvironmentGrabbing"] = false, ["General.EnableLockedObjectGrabbing"] = false, ["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.None, ["General.EnableDebugLogs"] = false, ["General.EnableConfigSync"] = true, ["General.BodyBlacklist"] = "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang", ["General.RecoveryObjectBlacklist"] = "", ["General.GrabbableComponentTypes"] = "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController", ["General.GrabbableKeywordBlacklist"] = "Master,Controller", ["General.ComponentChooserSortMode"] = ComponentChooserSortMode.ByFrequency, ["General.ComponentChooserDummy"] = ComponentChooserDummy.SelectToToggle, ["Recovery.EnableRecoveryFeature"] = false, ["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Kill, ["Recovery.RecoverBaggedBosses"] = false, ["Recovery.RecoverBaggedNPCs"] = false, ["Recovery.RecoverBaggedEnvironmentObjects"] = false, ["Persistence.EnableObjectPersistence"] = false, ["Persistence.EnableAutoGrab"] = false, ["Persistence.PersistBaggedBosses"] = true, ["Persistence.PersistBaggedNPCs"] = true, ["Persistence.PersistBaggedEnvironmentObjects"] = true, ["Persistence.PersistenceBlacklist"] = "", ["Persistence.AutoGrabDelay"] = 1f, ["BottomlessBag.EnableBottomlessBag"] = false, ["BottomlessBag.EnableStockRefreshClamping"] = false, ["BottomlessBag.EnableSuccessiveGrabStockRefresh"] = false, ["BottomlessBag.CycleCooldown"] = 0.2f, ["BottomlessBag.PlayAnimationOnCycle"] = false, ["BottomlessBag.EnableMouseWheelScrolling"] = true, ["BottomlessBag.InverseMouseWheelScrolling"] = false, ["BottomlessBag.AutoPromoteMainSeat"] = true, ["BottomlessBag.PrioritizeMainSeat"] = false, ["Hud.EnableCarouselHUD"] = false, ["Hud.CarouselSpacing"] = 45f, ["Hud.CarouselAnimationDuration"] = 0.4f, ["Hud.CenterSlotX"] = 25f, ["Hud.CenterSlotY"] = 50f, ["Hud.CenterSlotScale"] = 1f, ["Hud.CenterSlotOpacity"] = 1f, ["Hud.CenterSlotShowIcon"] = true, ["Hud.CenterSlotShowWeightIcon"] = true, ["Hud.CenterSlotShowName"] = true, ["Hud.CenterSlotShowHealthBar"] = true, ["Hud.CenterSlotShowSlotNumber"] = true, ["Hud.SideSlotX"] = 20f, ["Hud.SideSlotY"] = 5f, ["Hud.SideSlotScale"] = 0.8f, ["Hud.SideSlotOpacity"] = 0.3f, ["Hud.SideSlotShowIcon"] = true, ["Hud.SideSlotShowWeightIcon"] = true, ["Hud.SideSlotShowName"] = true, ["Hud.SideSlotShowHealthBar"] = true, ["Hud.SideSlotShowSlotNumber"] = true, ["Hud.EnableDamagePreview"] = false, ["Hud.DamagePreviewColor"] = (object)new Color(1f, 0.15f, 0.15f, 0.8f), ["Hud.UseNewWeightIcon"] = false, ["Hud.WeightDisplayMode"] = WeightDisplayMode.Multiplier, ["Hud.ScaleWeightColor"] = true, ["Hud.ShowTotalMassOnWeightIcon"] = false, ["Hud.ShowOverencumberIcon"] = false, ["Hud.EnableMassCapacityUI"] = false, ["Hud.MassCapacityUIPositionX"] = -20f, ["Hud.MassCapacityUIPositionY"] = 0f, ["Hud.MassCapacityUIScale"] = 0.8f, ["Hud.EnableSeparators"] = true, ["Hud.GradientIntensity"] = 1f, ["Hud.CapacityGradientColorStart"] = (object)new Color(0f, 1f, 0f, 1f), ["Hud.CapacityGradientColorMid"] = (object)new Color(1f, 1f, 0f, 1f), ["Hud.CapacityGradientColorEnd"] = (object)new Color(1f, 0f, 0f, 1f), ["Hud.OverencumbranceGradientColorStart"] = (object)new Color(0f, 1f, 1f, 1f), ["Hud.OverencumbranceGradientColorMid"] = (object)new Color(0f, 0f, 0.5f, 1f), ["Hud.OverencumbranceGradientColorEnd"] = (object)new Color(0f, 0f, 1f, 1f), ["Hud.EnableBaggedObjectInfo"] = false, ["Hud.BaggedObjectInfoX"] = 450f, ["Hud.BaggedObjectInfoY"] = 85f, ["Hud.BaggedObjectInfoScale"] = 1f, ["Hud.BaggedObjectInfoColor"] = (object)new Color(1f, 1f, 1f, 0.9f), ["Balance.EnableBalance"] = false, ["Balance.BreakoutTimeMultiplier"] = 1f, ["Balance.MaxSmacks"] = 3, ["Balance.MaxLaunchSpeed"] = "30", ["General.SearchRadiusMultiplier"] = 1f, ["Balance.AoEDamageDistribution"] = AoEDamageMode.Full, ["BottomlessBag.SlotScalingFormula"] = "0", ["Balance.MassCapacityFormula"] = "", ["Character Flags.EliteFlagMultiplier"] = "1", ["Character Flags.BossFlagMultiplier"] = "1", ["Character Flags.ChampionFlagMultiplier"] = "1", ["Character Flags.PlayerFlagMultiplier"] = "1", ["Character Flags.MinionFlagMultiplier"] = "1", ["Character Flags.DroneFlagMultiplier"] = "1", ["Character Flags.MechanicalFlagMultiplier"] = "1", ["Character Flags.VoidFlagMultiplier"] = "1", ["Character Flags.AllFlagMultiplier"] = "1", ["Balance.OverencumbranceMax"] = 0f, ["Balance.StateCalculationMode"] = StateCalculationMode.Current, ["Balance.MovespeedPenaltyFormula"] = "0", ["Balance.BagScaleCap"] = "1", ["Balance.MassCap"] = "700", ["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)" }, [PresetType.Intended] = new Dictionary { ["General.EnableBossGrabbing"] = true, ["General.EnableNPCGrabbing"] = false, ["General.EnableEnvironmentGrabbing"] = false, ["General.EnableLockedObjectGrabbing"] = false, ["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.None, ["General.EnableDebugLogs"] = false, ["General.EnableConfigSync"] = true, ["General.BodyBlacklist"] = "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang", ["General.RecoveryObjectBlacklist"] = "", ["General.GrabbableComponentTypes"] = "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController", ["General.GrabbableKeywordBlacklist"] = "Master,Controller", ["General.ComponentChooserSortMode"] = ComponentChooserSortMode.ByFrequency, ["General.ComponentChooserDummy"] = ComponentChooserDummy.SelectToToggle, ["Recovery.EnableRecoveryFeature"] = false, ["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Kill, ["Recovery.RecoverBaggedBosses"] = false, ["Recovery.RecoverBaggedNPCs"] = false, ["Recovery.RecoverBaggedEnvironmentObjects"] = false, ["Persistence.EnableObjectPersistence"] = false, ["Persistence.PersistenceBlacklist"] = "", ["BottomlessBag.EnableBottomlessBag"] = false, ["Hud.EnableCarouselHUD"] = false, ["Hud.EnableDamagePreview"] = false, ["Hud.EnableMassCapacityUI"] = false, ["Hud.EnableBaggedObjectInfo"] = false, ["Balance.EnableBalance"] = false, ["Balance.BreakoutTimeMultiplier"] = 1f, ["Balance.MaxSmacks"] = 3, ["Balance.MaxLaunchSpeed"] = "30", ["Balance.AoEDamageDistribution"] = AoEDamageMode.Full, ["BottomlessBag.SlotScalingFormula"] = "C + 2", ["Balance.MassCapacityFormula"] = "", ["Balance.OverencumbranceMax"] = 0f, ["Balance.StateCalculationMode"] = StateCalculationMode.Current, ["Balance.MovespeedPenaltyFormula"] = "clamp((T/M) * 0.25, 0, 0.5)", ["Balance.BagScaleCap"] = "1", ["Balance.MassCap"] = "700", ["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)" }, [PresetType.Default] = new Dictionary { ["General.EnableBossGrabbing"] = true, ["General.EnableNPCGrabbing"] = true, ["General.EnableEnvironmentGrabbing"] = true, ["General.EnableLockedObjectGrabbing"] = true, ["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.SurvivorOnly, ["General.EnableDebugLogs"] = false, ["General.EnableConfigSync"] = true, ["General.BodyBlacklist"] = "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang", ["General.RecoveryObjectBlacklist"] = "", ["General.GrabbableComponentTypes"] = "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController", ["General.GrabbableKeywordBlacklist"] = "Master,Controller", ["General.ComponentChooserSortMode"] = ComponentChooserSortMode.ByFrequency, ["General.ComponentChooserDummy"] = ComponentChooserDummy.SelectToToggle, ["Recovery.EnableRecoveryFeature"] = true, ["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Recover, ["Recovery.RecoverBaggedBosses"] = true, ["Recovery.RecoverBaggedNPCs"] = true, ["Recovery.RecoverBaggedEnvironmentObjects"] = true, ["Persistence.EnableObjectPersistence"] = true, ["Persistence.EnableAutoGrab"] = true, ["Persistence.PersistBaggedBosses"] = true, ["Persistence.PersistBaggedNPCs"] = true, ["Persistence.PersistBaggedEnvironmentObjects"] = true, ["Persistence.PersistenceBlacklist"] = "", ["BottomlessBag.EnableBottomlessBag"] = true, ["BottomlessBag.EnableStockRefreshClamping"] = true, ["BottomlessBag.EnableSuccessiveGrabStockRefresh"] = true, ["Hud.EnableCarouselHUD"] = true, ["Hud.EnableDamagePreview"] = true, ["Hud.EnableMassCapacityUI"] = true, ["Hud.EnableSeparators"] = true, ["Hud.EnableBaggedObjectInfo"] = true, ["Hud.ShowTotalMassOnWeightIcon"] = false, ["Hud.ShowOverencumberIcon"] = false, ["Balance.EnableBalance"] = false, ["Balance.BreakoutTimeMultiplier"] = 1f, ["Balance.MaxSmacks"] = 3, ["Balance.MaxLaunchSpeed"] = "30", ["Balance.AoEDamageDistribution"] = AoEDamageMode.Full, ["BottomlessBag.SlotScalingFormula"] = "C + 2", ["Balance.MassCapacityFormula"] = "", ["Balance.OverencumbranceMax"] = 0f, ["Balance.StateCalculationMode"] = StateCalculationMode.Current, ["Balance.MovespeedPenaltyFormula"] = "clamp((T/M) * 0.25, 0, 0.5)", ["Balance.BagScaleCap"] = "1", ["Balance.MassCap"] = "700", ["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)" } }; Dictionary dictionary = new Dictionary(); dictionary["General.EnableBossGrabbing"] = true; dictionary["General.EnableNPCGrabbing"] = true; dictionary["General.EnableEnvironmentGrabbing"] = true; dictionary["General.EnableLockedObjectGrabbing"] = true; dictionary["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.SurvivorOnly; dictionary["General.EnableDebugLogs"] = false; dictionary["General.EnableConfigSync"] = true; dictionary["General.BodyBlacklist"] = "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang"; dictionary["General.RecoveryObjectBlacklist"] = ""; dictionary["General.GrabbableComponentTypes"] = "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController"; dictionary["General.GrabbableKeywordBlacklist"] = "Master,Controller"; dictionary["General.ComponentChooserSortMode"] = ComponentChooserSortMode.ByFrequency; dictionary["General.ComponentChooserDummy"] = ComponentChooserDummy.SelectToToggle; dictionary["Recovery.EnableRecoveryFeature"] = true; dictionary["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Recover; dictionary["Recovery.RecoverBaggedBosses"] = true; dictionary["Recovery.RecoverBaggedNPCs"] = true; dictionary["Recovery.RecoverBaggedEnvironmentObjects"] = true; dictionary["Persistence.EnableObjectPersistence"] = true; dictionary["Persistence.EnableAutoGrab"] = true; dictionary["Persistence.PersistBaggedBosses"] = true; dictionary["Persistence.PersistBaggedNPCs"] = true; dictionary["Persistence.PersistBaggedEnvironmentObjects"] = true; dictionary["Persistence.PersistenceBlacklist"] = ""; dictionary["BottomlessBag.EnableBottomlessBag"] = true; dictionary["BottomlessBag.EnableStockRefreshClamping"] = true; dictionary["BottomlessBag.EnableSuccessiveGrabStockRefresh"] = true; dictionary["Hud.EnableCarouselHUD"] = true; dictionary["Hud.EnableDamagePreview"] = true; dictionary["Hud.EnableMassCapacityUI"] = true; dictionary["Hud.EnableBaggedObjectInfo"] = true; dictionary["Hud.SideSlotShowIcon"] = true; dictionary["Hud.SideSlotShowWeightIcon"] = false; dictionary["Hud.EnableDamagePreview"] = false; dictionary["Hud.DamagePreviewColor"] = (object)new Color(1f, 0.15f, 0.15f, 0.8f); dictionary["Hud.UseNewWeightIcon"] = true; dictionary["Hud.WeightDisplayMode"] = WeightDisplayMode.KiloGrams; dictionary["Hud.ScaleWeightColor"] = true; dictionary["Hud.ShowTotalMassOnWeightIcon"] = true; dictionary["Balance.EnableBalance"] = true; dictionary["Balance.AoEDamageDistribution"] = AoEDamageMode.Split; dictionary["BottomlessBag.SlotScalingFormula"] = "INF"; dictionary["Balance.MassCapacityFormula"] = "700*C + H*S*0.1 + L*50"; dictionary["Character Flags.EliteFlagMultiplier"] = "1"; dictionary["Character Flags.BossFlagMultiplier"] = "1"; dictionary["Character Flags.ChampionFlagMultiplier"] = "1"; dictionary["Character Flags.PlayerFlagMultiplier"] = "1"; dictionary["Character Flags.MinionFlagMultiplier"] = "1"; dictionary["Character Flags.DroneFlagMultiplier"] = "1"; dictionary["Character Flags.MechanicalFlagMultiplier"] = "1"; dictionary["Character Flags.VoidFlagMultiplier"] = "1"; dictionary["Character Flags.AllFlagMultiplier"] = "H/max(B,1)"; dictionary["Balance.OverencumbranceMax"] = 100f; dictionary["Balance.StateCalculationMode"] = StateCalculationMode.All; dictionary["Balance.MovespeedPenaltyFormula"] = "clamp((T/M) * 0.25, 0, 0.5)"; dictionary["Balance.BagScaleCap"] = "1"; dictionary["Balance.MassCap"] = "999"; dictionary["Balance.MaxLaunchSpeed"] = "30"; dictionary["Balance.BreakoutTimeMultiplier"] = 1f; dictionary["Balance.SearchRadiusMultiplier"] = 1f; dictionary["Balance.MaxSmacks"] = 3; dictionary["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)"; obj[PresetType.Balance] = dictionary; Dictionary dictionary2 = new Dictionary(); dictionary2["General.EnableBossGrabbing"] = true; dictionary2["General.EnableNPCGrabbing"] = true; dictionary2["General.EnableEnvironmentGrabbing"] = true; dictionary2["General.EnableLockedObjectGrabbing"] = true; dictionary2["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.None; dictionary2["General.EnableDebugLogs"] = false; dictionary2["General.EnableConfigSync"] = true; dictionary2["General.BodyBlacklist"] = "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang"; dictionary2["General.RecoveryObjectBlacklist"] = ""; dictionary2["General.GrabbableComponentTypes"] = "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController"; dictionary2["General.GrabbableKeywordBlacklist"] = "Master,Controller"; dictionary2["General.ComponentChooserSortMode"] = ComponentChooserSortMode.ByFrequency; dictionary2["General.ComponentChooserDummy"] = ComponentChooserDummy.SelectToToggle; dictionary2["Recovery.EnableRecoveryFeature"] = false; dictionary2["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Kill; dictionary2["Recovery.RecoverBaggedBosses"] = false; dictionary2["Recovery.RecoverBaggedNPCs"] = false; dictionary2["Recovery.RecoverBaggedEnvironmentObjects"] = false; dictionary2["Persistence.EnableObjectPersistence"] = false; dictionary2["Persistence.PersistenceBlacklist"] = ""; dictionary2["BottomlessBag.EnableBottomlessBag"] = false; dictionary2["BottomlessBag.SlotScalingFormula"] = "C + 2"; dictionary2["Hud.EnableCarouselHUD"] = false; dictionary2["Hud.EnableDamagePreview"] = false; dictionary2["Hud.EnableMassCapacityUI"] = false; dictionary2["Hud.EnableBaggedObjectInfo"] = false; dictionary2["Balance.EnableBalance"] = false; dictionary2["Balance.BreakoutTimeMultiplier"] = 1f; dictionary2["Balance.MaxSmacks"] = 3; dictionary2["Balance.MaxLaunchSpeed"] = "30"; dictionary2["Balance.AoEDamageDistribution"] = AoEDamageMode.Full; dictionary2["BottomlessBag.SlotScalingFormula"] = "C + 2"; dictionary2["Balance.MassCapacityFormula"] = ""; dictionary2["Balance.OverencumbranceMax"] = 0f; dictionary2["Balance.StateCalculationMode"] = StateCalculationMode.Current; dictionary2["Balance.MovespeedPenaltyFormula"] = "clamp((T/M) * 0.25, 0, 0.5)"; dictionary2["Balance.BagScaleCap"] = "1"; dictionary2["Balance.MassCap"] = "700"; dictionary2["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)"; obj[PresetType.Minimal] = dictionary2; obj[PresetType.Hardcore] = new Dictionary { ["General.EnableBossGrabbing"] = false, ["General.EnableNPCGrabbing"] = true, ["General.EnableEnvironmentGrabbing"] = true, ["General.EnableLockedObjectGrabbing"] = false, ["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.None, ["General.EnableDebugLogs"] = false, ["General.EnableConfigSync"] = true, ["General.BodyBlacklist"] = "HeaterPodBodyNoRespawn,ThrownObjectProjectile,ThrownObjectProjectileNoStun,GenericPickup,MultiShopTerminal,MultiShopLargeTerminal,MultiShopEquipmentTerminal,RailgunnerPistolProjectile,FMJRamping,SyringeProjectile,EngiGrenadeProjectile,CrocoSpit,CaptainTazer,LunarSpike,LunarNeedleProjectile,StickyBomb,RocketProjectile,StunAndPierceBoomerang", ["General.RecoveryObjectBlacklist"] = "", ["General.GrabbableComponentTypes"] = "PurchaseInteraction,TeleporterInteraction,GenericInteraction,ProxyInteraction,DummyPingableInteraction,MealPrepController", ["General.GrabbableKeywordBlacklist"] = "Master,Controller", ["General.ComponentChooserSortMode"] = ComponentChooserSortMode.ByFrequency, ["General.ComponentChooserDummy"] = ComponentChooserDummy.SelectToToggle, ["Recovery.EnableRecoveryFeature"] = false, ["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Kill, ["Recovery.RecoverBaggedBosses"] = false, ["Recovery.RecoverBaggedNPCs"] = false, ["Recovery.RecoverBaggedEnvironmentObjects"] = false, ["Persistence.EnableObjectPersistence"] = false, ["Persistence.PersistenceBlacklist"] = "", ["BottomlessBag.EnableBottomlessBag"] = true, ["BottomlessBag.EnableStockRefreshClamping"] = true, ["BottomlessBag.EnableSuccessiveGrabStockRefresh"] = false, ["Hud.EnableCarouselHUD"] = true, ["Hud.EnableDamagePreview"] = true, ["Hud.EnableMassCapacityUI"] = true, ["Hud.EnableSeparators"] = true, ["Hud.EnableBaggedObjectInfo"] = true, ["Balance.EnableBalance"] = true, ["Balance.BreakoutTimeMultiplier"] = 0.7f, ["Balance.MaxSmacks"] = 3, ["Balance.MaxLaunchSpeed"] = "50", ["Balance.SearchRadiusMultiplier"] = 1f, ["Balance.AoEDamageDistribution"] = AoEDamageMode.Full, ["BottomlessBag.SlotScalingFormula"] = "max(0, (C + floor(S/2)) - floor(L/5) - floor(H/2000))", ["Balance.MassCapacityFormula"] = "max(100, 700 + S*100 - L*50 - H/20)", ["Character Flags.EliteFlagMultiplier"] = "1.25", ["Character Flags.BossFlagMultiplier"] = "2", ["Character Flags.ChampionFlagMultiplier"] = "2", ["Character Flags.PlayerFlagMultiplier"] = "1", ["Character Flags.MinionFlagMultiplier"] = "1", ["Character Flags.DroneFlagMultiplier"] = "1", ["Character Flags.MechanicalFlagMultiplier"] = "1.5", ["Character Flags.VoidFlagMultiplier"] = "1", ["Character Flags.AllFlagMultiplier"] = "H/max(B,1)", ["Balance.OverencumbranceMax"] = 75f, ["Balance.StateCalculationMode"] = StateCalculationMode.All, ["Balance.MovespeedPenaltyFormula"] = "clamp((T/M) * 0.34, 0, 0.99)", ["Balance.BagScaleCap"] = "1", ["Balance.MassCap"] = "INF", ["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)" }; obj[PresetType.Caveman] = new Dictionary { ["General.EnableBossGrabbing"] = true, ["General.EnableNPCGrabbing"] = true, ["General.EnableEnvironmentGrabbing"] = true, ["General.EnableLockedObjectGrabbing"] = true, ["General.ProjectileGrabbingMode"] = ProjectileGrabbingMode.AllProjectiles, ["General.EnableDebugLogs"] = false, ["General.EnableConfigSync"] = true, ["General.BodyBlacklist"] = "", ["General.RecoveryObjectBlacklist"] = "", ["General.GrabbableComponentTypes"] = "MeshRenderer", ["General.GrabbableKeywordBlacklist"] = "", ["Recovery.EnableRecoveryFeature"] = true, ["Recovery.EnemyRecoveryMode"] = EnemyRecoveryMode.Recover, ["Recovery.RecoverBaggedBosses"] = true, ["Recovery.RecoverBaggedNPCs"] = true, ["Recovery.RecoverBaggedEnvironmentObjects"] = true, ["Persistence.EnableObjectPersistence"] = true, ["Persistence.EnableAutoGrab"] = true, ["Persistence.PersistBaggedBosses"] = true, ["Persistence.PersistBaggedNPCs"] = true, ["Persistence.PersistBaggedEnvironmentObjects"] = true, ["Persistence.PersistenceBlacklist"] = "", ["BottomlessBag.EnableBottomlessBag"] = true, ["BottomlessBag.EnableStockRefreshClamping"] = false, ["BottomlessBag.EnableSuccessiveGrabStockRefresh"] = true, ["Hud.EnableCarouselHUD"] = true, ["Hud.EnableDamagePreview"] = true, ["Hud.EnableMassCapacityUI"] = true, ["Hud.EnableSeparators"] = true, ["Hud.EnableBaggedObjectInfo"] = true, ["Balance.EnableBalance"] = true, ["Balance.BreakoutTimeMultiplier"] = 100f, ["Balance.MaxSmacks"] = 100, ["Balance.MaxLaunchSpeed"] = "INF", ["Balance.SearchRadiusMultiplier"] = 50f, ["Balance.AoEDamageDistribution"] = AoEDamageMode.Full, ["BottomlessBag.SlotScalingFormula"] = "INF", ["Balance.MassCapacityFormula"] = "", ["Character Flags.EliteFlagMultiplier"] = "1", ["Character Flags.BossFlagMultiplier"] = "1", ["Character Flags.ChampionFlagMultiplier"] = "1", ["Character Flags.PlayerFlagMultiplier"] = "1", ["Character Flags.MinionFlagMultiplier"] = "1", ["Character Flags.DroneFlagMultiplier"] = "1", ["Character Flags.MechanicalFlagMultiplier"] = "1", ["Character Flags.VoidFlagMultiplier"] = "1", ["Character Flags.AllFlagMultiplier"] = "1", ["Balance.OverencumbranceMax"] = 0f, ["Balance.StateCalculationMode"] = StateCalculationMode.All, ["Balance.MovespeedPenaltyFormula"] = "0", ["Balance.BagScaleCap"] = "INF", ["Balance.MassCap"] = "INF", ["Balance.SlamDamageFormula"] = "BASE_COEF + (MASS_SCALING * BM / MC)" }; obj[PresetType.Custom] = new Dictionary(); Presets = obj; } } public static class PresetManager { private static bool _isApplyingPreset; public static void ApplyPreset(PresetType presetType) { //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) if (presetType == PresetType.Custom) { return; } if (!PresetDefinitions.Presets.ContainsKey(presetType)) { Log.Warning($"[ConfigPreset] Preset {presetType} not found in definitions."); return; } _isApplyingPreset = true; Dictionary dictionary = PresetDefinitions.Presets[presetType]; try { int num = 0; foreach (KeyValuePair item in dictionary) { ConfigEntryBase configEntry = GetConfigEntry(item.Key); if (configEntry == null) { continue; } try { if (item.Value is bool value) { if (configEntry is ConfigEntry val) { val.Value = value; num++; } continue; } if (item.Value is float value2) { if (configEntry is ConfigEntry val2) { val2.Value = value2; num++; } continue; } if (item.Value is int value3) { if (configEntry is ConfigEntry val3) { val3.Value = value3; num++; } continue; } if (item.Value is string value4) { if (configEntry is ConfigEntry val4) { val4.Value = value4; num++; } continue; } if (item.Value is Color value5) { if (configEntry is ConfigEntry val5) { val5.Value = value5; num++; } continue; } Type type = ((object)configEntry).GetType().GetGenericArguments().FirstOrDefault(); if (type != null && type.IsEnum && item.Value.GetType() == type) { PropertyInfo property = ((object)configEntry).GetType().GetProperty("Value"); if (property != null) { property.SetValue(configEntry, item.Value); num++; } } } catch (Exception ex) { Log.Warning("[ConfigPreset] Failed to apply setting " + item.Key + ": " + ex.Message); } } PluginConfig.Instance.SelectedPreset.Value = presetType; PluginConfig.Instance.LastSelectedPreset.Value = presetType; CharacterFlagType value6 = PluginConfig.Instance.SelectedFlag.Value; ConfigEntry flagMultiplierConfig = PluginConfig.GetFlagMultiplierConfig(value6); if (flagMultiplierConfig != null) { PluginConfig.Instance.SelectedFlagMultiplier.Value = flagMultiplierConfig.Value; } RefreshAllBagControllers(); RefreshAllRiskOfOptionsUI(); } finally { _isApplyingPreset = false; } } public static void CheckAndApplyPresetOnStartup() { PresetType value = PluginConfig.Instance.SelectedPreset.Value; PresetType value2 = PluginConfig.Instance.LastSelectedPreset.Value; if (value != value2) { ApplyPreset(value); } } private static void RefreshAllRiskOfOptionsUI() { if (DrifterBossGrabPlugin.RooInstalled) { RefreshAllRiskOfOptionsUIInternal(); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void RefreshAllRiskOfOptionsUIInternal() { ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); ModSetting[] array2 = array; foreach (ModSetting val in array2) { GameObject gameObject = ((Component)val).gameObject; if ((Object)(object)gameObject != (Object)null && gameObject.activeSelf) { gameObject.SetActive(false); gameObject.SetActive(true); } } } public static void OnSettingModified() { if (!_isApplyingPreset && PluginConfig.Instance.SelectedPreset.Value != PresetType.Custom) { PluginConfig.Instance.SelectedPreset.Value = PresetType.Custom; } } public static void RefreshPresetDropdownUI() { if (DrifterBossGrabPlugin.RooInstalled) { RefreshPresetDropdownUIInternal(); } } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] private static void RefreshPresetDropdownUIInternal() { ModSetting[] array = Object.FindObjectsByType((FindObjectsSortMode)0); ModSetting[] array2 = array; foreach (ModSetting val in array2) { GameObject gameObject = ((Component)val).gameObject; if ((Object)(object)gameObject != (Object)null && gameObject.activeSelf) { gameObject.SetActive(false); gameObject.SetActive(true); } } } private static ConfigEntryBase? GetConfigEntry(string settingKey) { string[] array = settingKey.Split('.'); if (array.Length != 2) { return null; } string text = array[0]; string key = array[1]; return (ConfigEntryBase?)(text switch { "General" => GetGeneralConfigEntry(key), "Recovery" => GetRecoveryConfigEntry(key), "Persistence" => GetPersistenceConfigEntry(key), "BottomlessBag" => GetBottomlessBagConfigEntry(key), "Hud" => GetHudConfigEntry(key), "Balance" => GetBalanceConfigEntry(key), "Character Flags" => GetCharacterFlagsConfigEntry(key), _ => null, }); } private static ConfigEntryBase? GetRecoveryConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EnableRecoveryFeature" => instance.EnableRecoveryFeature, "EnemyRecoveryMode" => instance.EnemyRecoveryMode, "RecoverBaggedBosses" => instance.RecoverBaggedBosses, "RecoverBaggedNPCs" => instance.RecoverBaggedNPCs, "RecoverBaggedEnvironmentObjects" => instance.RecoverBaggedEnvironmentObjects, _ => null, }); } private static ConfigEntryBase? GetGeneralConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EnableBossGrabbing" => instance.EnableBossGrabbing, "EnableNPCGrabbing" => instance.EnableNPCGrabbing, "EnableEnvironmentGrabbing" => instance.EnableEnvironmentGrabbing, "EnableLockedObjectGrabbing" => instance.EnableLockedObjectGrabbing, "ProjectileGrabbingMode" => instance.ProjectileGrabbingMode, "SearchRadiusMultiplier" => instance.SearchRadiusMultiplier, "BodyBlacklist" => instance.BodyBlacklist, "RecoveryObjectBlacklist" => instance.RecoveryObjectBlacklist, "GrabbableComponentTypes" => instance.GrabbableComponentTypes, "GrabbableKeywordBlacklist" => instance.GrabbableKeywordBlacklist, "ComponentChooserSortMode" => instance.ComponentChooserSortModeEntry, "ComponentChooserDummy" => instance.ComponentChooserDummyEntry, "EnableDebugLogs" => instance.EnableDebugLogs, "EnableConfigSync" => instance.EnableConfigSync, _ => null, }); } private static ConfigEntryBase? GetPersistenceConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EnableObjectPersistence" => instance.EnableObjectPersistence, "EnableAutoGrab" => instance.EnableAutoGrab, "PersistBaggedBosses" => instance.PersistBaggedBosses, "PersistBaggedNPCs" => instance.PersistBaggedNPCs, "PersistBaggedEnvironmentObjects" => instance.PersistBaggedEnvironmentObjects, "PersistenceBlacklist" => instance.PersistenceBlacklist, "AutoGrabDelay" => instance.AutoGrabDelay, _ => null, }); } private static ConfigEntryBase? GetBottomlessBagConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EnableBottomlessBag" => instance.BottomlessBagEnabled, "EnableStockRefreshClamping" => instance.EnableStockRefreshClamping, "EnableSuccessiveGrabStockRefresh" => instance.EnableSuccessiveGrabStockRefresh, "CycleCooldown" => instance.CycleCooldown, "PlayAnimationOnCycle" => instance.PlayAnimationOnCycle, "EnableMouseWheelScrolling" => instance.EnableMouseWheelScrolling, "InverseMouseWheelScrolling" => instance.InverseMouseWheelScrolling, "AutoPromoteMainSeat" => instance.AutoPromoteMainSeat, "PrioritizeMainSeat" => instance.PrioritizeMainSeat, "SlotScalingFormula" => instance.SlotScalingFormula, _ => null, }); } private static ConfigEntryBase? GetHudConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EnableCarouselHUD" => instance.EnableCarouselHUD, "CarouselSpacing" => instance.CarouselSpacing, "CarouselAnimationDuration" => instance.CarouselAnimationDuration, "SelectedHudElement" => instance.SelectedHudElement, "CenterSlotX" => instance.CenterSlotX, "CenterSlotY" => instance.CenterSlotY, "CenterSlotScale" => instance.CenterSlotScale, "CenterSlotOpacity" => instance.CenterSlotOpacity, "CenterSlotShowIcon" => instance.CenterSlotShowIcon, "CenterSlotShowWeightIcon" => instance.CenterSlotShowWeightIcon, "CenterSlotShowName" => instance.CenterSlotShowName, "CenterSlotShowHealthBar" => instance.CenterSlotShowHealthBar, "CenterSlotShowSlotNumber" => instance.CenterSlotShowSlotNumber, "SideSlotX" => instance.SideSlotX, "SideSlotY" => instance.SideSlotY, "SideSlotScale" => instance.SideSlotScale, "SideSlotOpacity" => instance.SideSlotOpacity, "SideSlotShowIcon" => instance.SideSlotShowIcon, "SideSlotShowWeightIcon" => instance.SideSlotShowWeightIcon, "SideSlotShowName" => instance.SideSlotShowName, "SideSlotShowHealthBar" => instance.SideSlotShowHealthBar, "SideSlotShowSlotNumber" => instance.SideSlotShowSlotNumber, "EnableDamagePreview" => instance.EnableDamagePreview, "DamagePreviewColor" => instance.DamagePreviewColor, "UseNewWeightIcon" => instance.UseNewWeightIcon, "WeightDisplayMode" => instance.WeightDisplayMode, "ScaleWeightColor" => instance.ScaleWeightColor, "ShowTotalMassOnWeightIcon" => instance.ShowTotalMassOnWeightIcon, "ShowOverencumberIcon" => instance.ShowOverencumberIcon, "EnableMassCapacityUI" => instance.EnableMassCapacityUI, "MassCapacityUIPositionX" => instance.MassCapacityUIPositionX, "MassCapacityUIPositionY" => instance.MassCapacityUIPositionY, "MassCapacityUIScale" => instance.MassCapacityUIScale, "EnableSeparators" => instance.EnableSeparators, "GradientIntensity" => instance.GradientIntensity, "CapacityGradientColorStart" => instance.CapacityGradientColorStart, "CapacityGradientColorMid" => instance.CapacityGradientColorMid, "CapacityGradientColorEnd" => instance.CapacityGradientColorEnd, "OverencumbranceGradientColorStart" => instance.OverencumbranceGradientColorStart, "OverencumbranceGradientColorMid" => instance.OverencumbranceGradientColorMid, "OverencumbranceGradientColorEnd" => instance.OverencumbranceGradientColorEnd, "EnableBaggedObjectInfo" => instance.EnableBaggedObjectInfo, "BaggedObjectInfoX" => instance.BaggedObjectInfoX, "BaggedObjectInfoY" => instance.BaggedObjectInfoY, "BaggedObjectInfoScale" => instance.BaggedObjectInfoScale, "BaggedObjectInfoColor" => instance.BaggedObjectInfoColor, _ => null, }); } private static ConfigEntryBase? GetBalanceConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EnableBalance" => instance.EnableBalance, "BreakoutTimeMultiplier" => instance.BreakoutTimeMultiplier, "MaxSmacks" => instance.MaxSmacks, "AoEDamageDistribution" => instance.AoEDamageDistribution, "MassCapacityFormula" => instance.MassCapacityFormula, "SlamDamageFormula" => instance.SlamDamageFormula, "OverencumbranceMax" => instance.OverencumbranceMax, "StateCalculationMode" => instance.StateCalculationMode, "MovespeedPenaltyFormula" => instance.MovespeedPenaltyFormula, "BagScaleCap" => instance.BagScaleCap, "MassCap" => instance.MassCap, "MaxLaunchSpeed" => instance.MaxLaunchSpeed, "SearchRadiusMultiplier" => instance.SearchRadiusMultiplier, _ => null, }); } private static ConfigEntryBase? GetCharacterFlagsConfigEntry(string key) { PluginConfig instance = PluginConfig.Instance; return (ConfigEntryBase?)(key switch { "EliteFlagMultiplier" => instance.EliteFlagMultiplier, "BossFlagMultiplier" => instance.BossFlagMultiplier, "ChampionFlagMultiplier" => instance.ChampionFlagMultiplier, "PlayerFlagMultiplier" => instance.PlayerFlagMultiplier, "MinionFlagMultiplier" => instance.MinionFlagMultiplier, "DroneFlagMultiplier" => instance.DroneFlagMultiplier, "MechanicalFlagMultiplier" => instance.MechanicalFlagMultiplier, "VoidFlagMultiplier" => instance.VoidFlagMultiplier, "AllFlagMultiplier" => instance.AllFlagMultiplier, _ => null, }); } private static void RefreshAllBagControllers() { DrifterBagController[] array = Object.FindObjectsByType((FindObjectsSortMode)0); DrifterBagController[] array2 = array; foreach (DrifterBagController val in array2) { CapacityScalingSystem.RecalculateCapacity(val); CapacityScalingSystem.RecalculateMass(val); CapacityScalingSystem.RecalculateState(val); CapacityScalingSystem.RecalculatePenalty(val); BagPassengerManager.ForceRecalculateMass(val); } } } } namespace DrifterBossGrabMod.Config.UI { public class ComponentChooserOption : ChoiceOption { private string _customName; private string _customDescription; private string _customCategory; public ComponentChooserOption(ConfigEntryBase configEntry, string name, string description, string category = "General") : base(configEntry) { _customName = name; _customDescription = description; _customCategory = category; } public override BaseOptionConfig GetConfig() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown return (BaseOptionConfig)new ChoiceConfig { name = _customName, category = _customCategory, description = _customDescription }; } public override GameObject CreateOptionGameObject(GameObject prefab, Transform parent) { GameObject val = Object.Instantiate(prefab, parent); DropDownController componentInChildren = val.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { ((Behaviour)componentInChildren).enabled = false; Object.DestroyImmediate((Object)(object)componentInChildren); } DynamicDropDownController dynamicDropDownController = val.AddComponent(); ((ModSetting)dynamicDropDownController).nameToken = ((BaseOption)this).GetNameToken(); Transform val2 = val.transform.Find("Label"); if (Object.op_Implicit((Object)(object)val2)) { TextMeshProUGUI component = ((Component)val2).GetComponent(); if ((Object)(object)component != (Object)null) { ((TMP_Text)component).text = _customName; } } ((Object)val).name = "Mod Option ComponentChooser, " + _customName; return val; } } public class DropdownPointerClickListener : MonoBehaviour, IPointerDownHandler, IEventSystemHandler { public Action OnClick; public void OnPointerDown(PointerEventData eventData) { OnClick?.Invoke(); } } public class DynamicDropDownController : ModSetting { public RooDropdown dropdown; private static List? _cachedComponentNames; private static string[]? _dropdownChoices; protected override void Awake() { dropdown = ((Component)this).GetComponentInChildren(true); base.nameLabel = ((Component)this).GetComponentInChildren(true); if ((Object)(object)dropdown != (Object)null) { DropdownPointerClickListener dropdownPointerClickListener = ((Component)dropdown).gameObject.AddComponent(); dropdownPointerClickListener.OnClick = OnDropdownClicked; } } private void OnEnable() { if ((Object)(object)base.nameLabel != (Object)null) { base.nameLabel.token = base.nameToken; } if ((Object)(object)dropdown != (Object)null) { if (_dropdownChoices == null) { dropdown.choices = new string[1] { "-- Click to Load & Select --" }; } else { dropdown.choices = _dropdownChoices; } ((UnityEvent)(object)dropdown.OnValueChanged).AddListener((UnityAction)OnChoiceChanged); dropdown.SetChoice(0); } } private void OnDisable() { if ((Object)(object)dropdown != (Object)null) { ((UnityEvent)(object)dropdown.OnValueChanged).RemoveListener((UnityAction)OnChoiceChanged); } } public override bool HasChanged() { return false; } public override void Revert() { } public override void CheckIfDisabled() { } protected override void Disable() { } protected override void Enable() { } private void OnDropdownClicked() { LoadComponents(); if ((Object)(object)dropdown != (Object)null) { dropdown.choices = _dropdownChoices ?? Array.Empty(); dropdown.SetChoice(0); } } private void LoadComponents() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Log.Debug("[DynamicDropDownController] Scanning active scene for component types..."); _cachedComponentNames = new List { "-- Select to Toggle --" }; try { Component[] source = Object.FindObjectsByType((FindObjectsInactive)1, (FindObjectsSortMode)0); switch (PluginConfig.Instance.ComponentChooserSortModeEntry.Value) { case ComponentChooserSortMode.ByProximity: { Vector3 referencePos = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.position : Vector3.zero); List collection2 = (from x in (from c in source where (Object)(object)c != (Object)null && (Object)(object)c.gameObject != (Object)null select new { Component = c, Distance = Vector3.Distance(c.transform.position, referencePos) } into x group x by ((object)x.Component).GetType().Name into g select new { Name = g.Key, MinDistance = g.Min(x => x.Distance) } into x orderby x.MinDistance select x).Take(500) select $"{x.Name} ({Mathf.RoundToInt(x.MinDistance)}m)").ToList(); _cachedComponentNames.AddRange(collection2); break; } case ComponentChooserSortMode.ByRaycast: { Camera main = Camera.main; if (!((Object)(object)main != (Object)null)) { break; } Ray val = default(Ray); ((Ray)(ref val))..ctor(((Component)main).transform.position, ((Component)main).transform.forward); RaycastHit[] source2 = Physics.RaycastAll(val, 1000f, -5, (QueryTriggerInteraction)2); List collection3 = (from x in (from x in source2.Where((RaycastHit h) => (Object)(object)((RaycastHit)(ref h)).collider != (Object)null).SelectMany((RaycastHit h) => from c in ((Component)((RaycastHit)(ref h)).collider).GetComponentsInParent() select new { Component = c, Distance = ((RaycastHit)(ref h)).distance, GameObjectName = ((Object)c.gameObject).name }) where (Object)(object)x.Component != (Object)null && ((object)x.Component).GetType().Name != "Transform" && ((object)x.Component).GetType().Name != "MeshRenderer" && ((object)x.Component).GetType().Name != "MeshFilter" group x by new { ((object)x.Component).GetType().Name, x.GameObjectName } into g select new { Name = g.Key.Name, GameObjectName = g.Key.GameObjectName, MinDistance = g.Min(x => x.Distance) } into x orderby x.MinDistance select x).Take(500) select $"{x.Name} ({x.GameObjectName} - {Mathf.RoundToInt(x.MinDistance)}m)").ToList(); _cachedComponentNames.AddRange(collection3); break; } default: { List collection = (from x in (from c in source where (Object)(object)c != (Object)null group c by ((object)c).GetType().Name into g select new { Name = g.Key, Count = g.Count() } into x orderby x.Count descending select x).Take(500) select $"{x.Name} ({x.Count})").ToList(); _cachedComponentNames.AddRange(collection); break; } } } catch (Exception arg) { Log.Error($"[DynamicDropDownController] Failed to scan scene components: {arg}"); } _dropdownChoices = _cachedComponentNames.ToArray(); Log.Debug($"[DynamicDropDownController] Loaded {_dropdownChoices.Length} component types from the scene."); } private void OnChoiceChanged(int newValue) { if (_cachedComponentNames != null && newValue != 0) { string text = _cachedComponentNames[newValue]; int num = text.IndexOf(" ("); if (num > 0) { text = text.Substring(0, num); } string value = PluginConfig.Instance.GrabbableComponentTypes.Value; List list = (from s in value.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries) select s.Trim()).ToList(); if (list.Contains(text)) { list.Remove(text); Log.Debug("[DynamicDropDownController] Removed " + text + " from GrabbableComponentTypes."); } else { list.Add(text); Log.Debug("[DynamicDropDownController] Added " + text + " to GrabbableComponentTypes."); } PluginConfig.Instance.GrabbableComponentTypes.Value = string.Join(",", list); if ((Object)(object)dropdown != (Object)null) { dropdown.SetChoice(0); } PresetManager.RefreshPresetDropdownUI(); } } } } namespace DrifterBossGrabMod.API { public abstract class APISerializerBase : IObjectSerializerPlugin { public abstract int Priority { get; } public abstract string PluginName { get; } public bool CanHandle(GameObject obj) { return CanHandleObject(obj); } public Dictionary? CaptureState(GameObject obj) { Dictionary dictionary = new Dictionary(); try { CaptureObjectState(obj, dictionary); return (dictionary.Count > 0) ? dictionary : null; } catch (Exception ex) { Log.Error("[" + PluginName + "] Failed to capture state for " + ((Object)obj).name + ": " + ex.Message); return null; } } public bool RestoreState(GameObject obj, Dictionary state) { try { RestoreObjectState(obj, state); return true; } catch (Exception ex) { Log.Error("[" + PluginName + "] Failed to restore state for " + ((Object)obj).name + ": " + ex.Message); return false; } } protected abstract bool CanHandleObject(GameObject obj); protected abstract void CaptureObjectState(GameObject obj, Dictionary state); protected abstract void RestoreObjectState(GameObject obj, Dictionary state); protected bool TryGetValue(Dictionary state, string key, out T? value) { if (state.TryGetValue(key, out object value2) && value2 != null) { try { if (!typeof(T).IsEnum) { value = (T)Convert.ChangeType(value2, typeof(T)); return true; } if (value2 is int) { int value3 = (int)value2; value = (T)Enum.ToObject(typeof(T), value3); return true; } } catch { value = default(T); return false; } } value = default(T); return false; } } public class ComponentAPISerializer : APISerializerBase where TComponent : Component { private class SerializerAction { public string Key { get; set; } = string.Empty; public Action> Capture { get; set; } = delegate { }; public Action> Restore { get; set; } = delegate { }; } private readonly int _priority; private readonly List _actions = new List(); public override int Priority => _priority; public override string PluginName => "ComponentAPISerializer<" + typeof(TComponent).Name + ">"; public ComponentAPISerializer(int priority) { _priority = priority; } protected override bool CanHandleObject(GameObject obj) { return (Object)(object)obj.GetComponent() != (Object)null; } protected override void CaptureObjectState(GameObject obj, Dictionary state) { TComponent component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return; } state["ObjectType"] = ((Object)obj).name.Replace("(Clone)", "").Trim(); foreach (SerializerAction action in _actions) { action.Capture(component, state); } Log.Debug($"[ComponentAPISerializer<{typeof(TComponent).Name}>] Captured {state.Count} values for {((Object)obj).name}"); } protected override void RestoreObjectState(GameObject obj, Dictionary state) { TComponent component = obj.GetComponent(); if ((Object)(object)component == (Object)null) { return; } foreach (SerializerAction action in _actions) { action.Restore(component, state); } Log.Debug("[ComponentAPISerializer<" + typeof(TComponent).Name + ">] Successfully restored " + ((Object)obj).name); } public ComponentAPISerializer AddAction(string key, Func getter, Action? setter = null, bool asInt = false) { Func getter2 = getter; string key2 = key; Action setter2 = setter; _actions.Add(new SerializerAction { Key = key2, Capture = delegate(TComponent component, Dictionary state) { TValue val3 = getter2(component); string text = key2; object obj4 = val3?.ToString(); if (obj4 == null) { obj4 = "null"; } Log.Debug(" - Capturing field '" + text + "': " + (string?)obj4); if (asInt && (object)val3 is Enum value2) { state[key2] = Convert.ToInt32(value2); } else { state[key2] = val3; } }, Restore = delegate(TComponent component, Dictionary state) { if (setter2 == null || !TryGetValue(state, key2, out TValue value)) { return; } TValue val; string[] obj; TValue val2; object obj2; if (PluginConfig.Instance.EnableDebugLogs.Value) { val = getter2(component); obj = new string[6] { " - Restoring field '", key2, "': ", null, null, null }; ref TValue reference = ref value; val2 = default(TValue); if (val2 == null) { val2 = reference; reference = ref val2; if (val2 == null) { obj2 = null; goto IL_0095; } } obj2 = reference.ToString(); goto IL_0095; } goto IL_00ee; IL_00ee: setter2(component, value); return; IL_00da: object obj3; if (obj3 == null) { obj3 = "null"; } obj[5] = (string)obj3; Log.Debug(string.Concat(obj)); goto IL_00ee; IL_0095: if (obj2 == null) { obj2 = "null"; } obj[3] = (string)obj2; obj[4] = " -> "; ref TValue reference2 = ref val; val2 = default(TValue); if (val2 == null) { val2 = reference2; reference2 = ref val2; if (val2 == null) { obj3 = null; goto IL_00da; } } obj3 = reference2.ToString(); goto IL_00da; } }); return this; } public ComponentAPISerializer AddCustomAction(Action> capture, Action> restore) { _actions.Add(new SerializerAction { Capture = capture, Restore = restore }); return this; } } public static class BuiltInSerializersAPI { public static IObjectSerializerPlugin ForChest() { return new ComponentAPISerializer(100).AddAction("isChestOpened", (ChestBehavior c) => c.isChestOpened, delegate(ChestBehavior c, bool v) { c.NetworkisChestOpened = v; }).AddAction("isCommandChest", (ChestBehavior c) => c.isCommandChest, delegate(ChestBehavior c, bool v) { c.NetworkisCommandChest = v; }).AddAction("isChestReset", (ChestBehavior c) => c.isChestReset, delegate(ChestBehavior c, bool v) { c.NetworkisChestReset = v; }) .AddAction("dropCount", (ChestBehavior c) => c.dropCount) .AddAction("minDropCount", (ChestBehavior c) => c.minDropCount) .AddAction("maxDropCount", (ChestBehavior c) => c.maxDropCount) .AddCustomAction(CapturePurchaseInteraction, RestorePurchaseInteraction) .AddCustomAction(CaptureEntityStateMachine, RestoreEntityStateMachine); } public static IObjectSerializerPlugin ForDuplicator() { return new ComponentAPISerializer(100).AddAction("hasBeenPurchased", (ShopTerminalBehavior c) => c.hasBeenPurchased, delegate(ShopTerminalBehavior c, bool v) { c.NetworkhasBeenPurchased = v; }).AddAction("hidden", (ShopTerminalBehavior c) => c.hidden, delegate(ShopTerminalBehavior c, bool v) { c.Networkhidden = v; }).AddAction("itemTier", (ShopTerminalBehavior c) => c.itemTier, null, asInt: true) .AddAction("dropAmount", (ShopTerminalBehavior c) => c.dropAmount) .AddCustomAction(CapturePickup, RestorePickup) .AddCustomAction(CapturePurchaseInteraction, RestorePurchaseInteraction); } private static void CapturePickup(T component, Dictionary state) where T : Component { object obj = component; ShopTerminalBehavior val = (ShopTerminalBehavior)((obj is ShopTerminalBehavior) ? obj : null); if ((Object)(object)val != (Object)null) { state["pickupIndex"] = ((object)(PickupIndex)(ref val.pickup.pickupIndex)).ToString(); state["pickupDecayValue"] = val.pickup.decayValue; } } private static void RestorePickup(T component, Dictionary state) where T : Component { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) object obj = component; ShopTerminalBehavior val = (ShopTerminalBehavior)((obj is ShopTerminalBehavior) ? obj : null); if ((Object)(object)val == (Object)null || !state.TryGetValue("pickupIndex", out object value) || !state.TryGetValue("pickupDecayValue", out object value2)) { return; } string text = value?.ToString(); if (!string.IsNullOrEmpty(text)) { PickupIndex val2 = PickupCatalog.FindPickupIndex(text); if (val2 != PickupIndex.none) { uint num2 = ((value2 is uint num) ? num : 0u); val.SetPickup(new UniquePickup { pickupIndex = val2, decayValue = num2 }, false); } } } public static IObjectSerializerPlugin ForShrine() { return new ComponentAPISerializer(90).AddCustomAction(CapturePurchaseInteraction, RestorePurchaseInteraction).AddCustomAction(CaptureEntityStateMachine, RestoreEntityStateMachine); } public static IObjectSerializerPlugin ForPurchaseInteraction() { return new ComponentAPISerializer(70).AddAction("cost", (PurchaseInteraction c) => c.cost, delegate(PurchaseInteraction c, int v) { c.Networkcost = v; }).AddAction("costType", (PurchaseInteraction c) => c.costType, null, asInt: true).AddAction("purchaseAvailable", (PurchaseInteraction c) => c.available, delegate(PurchaseInteraction c, bool v) { c.SetAvailable(v); }) .AddAction("purchaseLocked", (PurchaseInteraction c) => c.lockGameObject); } public static IObjectSerializerPlugin ForSpecialObjectAttributes() { ComponentAPISerializer result = new ComponentAPISerializer(85).AddAction("durability", (SpecialObjectAttributes c) => c.durability, delegate(SpecialObjectAttributes c, int v) { c.Networkdurability = v; }).AddAction("locked", (SpecialObjectAttributes c) => c.locked, delegate(SpecialObjectAttributes c, bool v) { c.Networklocked = v; }).AddAction("maxDurability", (SpecialObjectAttributes c) => c.maxDurability, delegate(SpecialObjectAttributes c, int v) { c.maxDurability = v; }) .AddAction("grabbable", (SpecialObjectAttributes c) => c.grabbable, delegate(SpecialObjectAttributes c, bool v) { c.grabbable = v; }) .AddAction("massOverride", (SpecialObjectAttributes c) => c.massOverride, delegate(SpecialObjectAttributes c, float v) { c.massOverride = v; }) .AddAction("damageOverride", (SpecialObjectAttributes c) => c.damageOverride, delegate(SpecialObjectAttributes c, float v) { c.damageOverride = v; }) .AddAction("hullClassification", (SpecialObjectAttributes c) => c.hullClassification, null, asInt: true) .AddAction("orientToFloor", (SpecialObjectAttributes c) => c.orientToFloor, delegate(SpecialObjectAttributes c, bool v) { c.orientToFloor = v; }) .AddAction("isVoid", (SpecialObjectAttributes c) => c.isVoid, delegate(SpecialObjectAttributes c, bool v) { c.isVoid = v; }) .AddAction("bestName", (SpecialObjectAttributes c) => c.bestName, delegate(SpecialObjectAttributes c, string v) { c.bestName = v; }); Log.Debug("[BuiltInSerializersAPI] Created SpecialObjectAttributes serializer"); return result; } public static IObjectSerializerPlugin ForCharacterBody() { return new ComponentAPISerializer(110).AddAction("baseMaxHealth", (CharacterBody c) => c.baseMaxHealth, delegate(CharacterBody c, float v) { c.baseMaxHealth = v; }).AddAction("baseMaxShield", (CharacterBody c) => c.baseMaxShield, delegate(CharacterBody c, float v) { c.baseMaxShield = v; }).AddAction("baseRegen", (CharacterBody c) => c.baseRegen, delegate(CharacterBody c, float v) { c.baseRegen = v; }) .AddAction("baseDamage", (CharacterBody c) => c.baseDamage, delegate(CharacterBody c, float v) { c.baseDamage = v; }) .AddAction("baseMoveSpeed", (CharacterBody c) => c.baseMoveSpeed, delegate(CharacterBody c, float v) { c.baseMoveSpeed = v; }) .AddAction("baseAttackSpeed", (CharacterBody c) => c.baseAttackSpeed, delegate(CharacterBody c, float v) { c.baseAttackSpeed = v; }) .AddAction("baseArmor", (CharacterBody c) => c.baseArmor, delegate(CharacterBody c, float v) { c.baseArmor = v; }) .AddAction("baseCrit", (CharacterBody c) => c.baseCrit, delegate(CharacterBody c, float v) { c.baseCrit = v; }) .AddAction("level", (CharacterBody c) => c.level, delegate(CharacterBody c, float v) { c.level = v; }) .AddAction("experience", (CharacterBody c) => c.experience, delegate(CharacterBody c, float v) { c.experience = v; }) .AddAction("bodyFlags", (CharacterBody c) => c.bodyFlags, delegate(CharacterBody c, BodyFlags v) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) c.bodyFlags = v; }, asInt: true) .AddAction("skinIndex", (CharacterBody c) => c.skinIndex, delegate(CharacterBody c, uint v) { c.skinIndex = v; }) .AddAction("subtitleNameToken", (CharacterBody c) => c.subtitleNameToken, delegate(CharacterBody c, string v) { c.subtitleNameToken = v; }) .AddCustomAction(CaptureHealthComponent, RestoreHealthComponentAndRecalculateStats); } public static IObjectSerializerPlugin ForCharacterMaster() { return new ComponentAPISerializer(115).AddAction("teamIndex", (CharacterMaster c) => c.teamIndex, delegate(CharacterMaster c, TeamIndex v) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) c.teamIndex = v; }, asInt: true).AddCustomAction(CaptureMasterInventory, RestoreMasterInventory); } public static IObjectSerializerPlugin ForInventory() { return new ComponentAPISerializer(120).AddCustomAction(delegate(Inventory c, Dictionary s) { CaptureInventory(c, s); }, delegate(Inventory c, Dictionary s) { RestoreInventory(c, s); }); } public static IObjectSerializerPlugin ForJunkCubeController() { ComponentAPISerializer componentAPISerializer = new ComponentAPISerializer(95); FieldInfo _maxActivationCountField = typeof(JunkCubeController).GetField("_maxActivationCount", BindingFlags.Instance | BindingFlags.NonPublic); componentAPISerializer.AddAction("ActivationCount", (JunkCubeController c) => c.ActivationCount, delegate(JunkCubeController c, int v) { c.ActivationCount = v; }); componentAPISerializer.AddAction("_maxActivationCount", (JunkCubeController c) => (_maxActivationCountField?.GetValue(c) as int?) ?? c.ActivationCount, delegate(JunkCubeController c, int v) { _maxActivationCountField?.SetValue(c, v); }); componentAPISerializer.AddCustomAction(CaptureJunkCubeHealth, RestoreJunkCubeHealth); return componentAPISerializer; } private static void CaptureJunkCubeHealth(T component, Dictionary state) where T : Component { object obj = component; JunkCubeController val = (JunkCubeController)((obj is JunkCubeController) ? obj : null); if (!((Object)(object)val == (Object)null)) { HealthComponent component2 = ((Component)val).GetComponent(); if ((Object)(object)component2 != (Object)null) { state["healthFraction"] = component2.healthFraction; state["shieldFraction"] = ((component2.shield > 0f) ? (component2.shield / component2.fullHealth) : 0f); state["barrierFraction"] = ((component2.barrier > 0f) ? (component2.barrier / component2.fullHealth) : 0f); } } } private static void RestoreJunkCubeHealth(T component, Dictionary state) where T : Component { object obj = component; JunkCubeController val = (JunkCubeController)((obj is JunkCubeController) ? obj : null); if ((Object)(object)val == (Object)null) { return; } HealthComponent component2 = ((Component)val).GetComponent(); if (!((Object)(object)component2 == (Object)null)) { float num = 1f; if (state.TryGetValue("healthFraction", out object value)) { num = (float)value; } CharacterBody component3 = ((Component)val).GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.RecalculateStats(); } if (component2.fullHealth > 0f && num >= 0f) { float num2 = Mathf.Clamp01(num) * component2.fullHealth; num2 = Mathf.Clamp(num2, 0f, component2.fullHealth); component2.Networkhealth = num2; Log.Debug($"[RestoreJunkCubeHealth] Restored health: {component2.health}/{component2.fullHealth} (fraction: {num:F3}, activation: {val.ActivationCount})"); } if (state.TryGetValue("shieldFraction", out object value2)) { component2.Networkshield = Mathf.Clamp01((float)value2) * component2.fullHealth; } if (state.TryGetValue("barrierFraction", out object value3)) { component2.Networkbarrier = Mathf.Clamp01((float)value3) * component2.fullHealth; } } } public static IObjectSerializerPlugin ForHalcyoniteShrineInteractable() { return new ComponentAPISerializer(95).AddAction("interactions", (HalcyoniteShrineInteractable c) => c.interactions, delegate(HalcyoniteShrineInteractable c, int v) { c.Networkinteractions = v; }).AddAction("goldDrained", (HalcyoniteShrineInteractable c) => c.goldDrained).AddAction("isDraining", (HalcyoniteShrineInteractable c) => c.isDraining, delegate(HalcyoniteShrineInteractable c, bool v) { c.NetworkisDraining = v; }) .AddAction("maxTargets", (HalcyoniteShrineInteractable c) => c.maxTargets, delegate(HalcyoniteShrineInteractable c, int v) { c.NetworkmaxTargets = v; }) .AddAction("goldMaterialModifier", (HalcyoniteShrineInteractable c) => c.goldMaterialModifier, delegate(HalcyoniteShrineInteractable c, float v) { c.NetworkgoldMaterialModifier = v; }) .AddCustomAction(CapturePurchaseInteraction, RestorePurchaseInteraction) .AddCustomAction(CaptureEntityStateMachine, RestoreEntityStateMachine); } public static IObjectSerializerPlugin ForTinkerableObjectAttributes() { return new ComponentAPISerializer(90).AddAction("tinkers", (TinkerableObjectAttributes c) => c.tinkers, delegate(TinkerableObjectAttributes c, int v) { c.Networktinkers = v; }).AddAction("maxTinkers", (TinkerableObjectAttributes c) => c.maxTinkers).AddCustomAction(CapturePurchaseInteraction, RestorePurchaseInteraction); } public static IObjectSerializerPlugin ForTeleporterInteraction() { return new ComponentAPISerializer(90).AddCustomAction(CaptureTeleporterInteraction, RestoreTeleporterInteraction); } public static IObjectSerializerPlugin ForQualityIntegration() { return new QualityIntegration(); } public static IObjectSerializerPlugin ForGenericComponentSerializer() { return new GenericComponentSerializerPlugin(); } private static void CaptureTeleporterInteraction(T component, Dictionary state) where T : Component { object obj = component; TeleporterInteraction val = (TeleporterInteraction)((obj is TeleporterInteraction) ? obj : null); if (!((Object)(object)val == (Object)null)) { if (ReflectionCache.TeleporterInteraction.BossShrineCounter != null && ReflectionCache.TeleporterInteraction.BossShrineCounter.GetValue(val) is int num) { state["bossShrineCounter"] = num; } state["shrineBonusStacks"] = val.shrineBonusStacks; } } private static void RestoreTeleporterInteraction(T component, Dictionary state) where T : Component { object obj = component; TeleporterInteraction val = (TeleporterInteraction)((obj is TeleporterInteraction) ? obj : null); if ((Object)(object)val == (Object)null) { return; } int num = 0; if (state.TryGetValue("shrineBonusStacks", out object value)) { try { num = (val.Network_shrineBonusStacks = Convert.ToInt32(value)); } catch (Exception ex) { Log.Error("[RestoreTeleporterInteraction] Failed to restore shrineBonusStacks: " + ex.Message); } } if (state.TryGetValue("bossShrineCounter", out object value2)) { try { int num3 = Convert.ToInt32(value2); if (ReflectionCache.TeleporterInteraction.BossShrineCounter != null) { ReflectionCache.TeleporterInteraction.BossShrineCounter.SetValue(val, num3); } } catch (Exception ex2) { Log.Error("[RestoreTeleporterInteraction] Failed to restore bossShrineCounter: " + ex2.Message); } } BossGroup val2 = ((Component)val).GetComponent() ?? val.bossGroup; if ((Object)(object)val2 != (Object)null) { val2.bonusRewardCount = num; Log.Debug($"[RestoreTeleporterInteraction] Successfully synced bossGroup.bonusRewardCount to {num}"); } } private static void CapturePurchaseInteraction(T component, Dictionary state) where T : Component { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Expected I4, but got Unknown PurchaseInteraction component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 != (Object)null) { state["purchaseCost"] = component2.cost; state["purchaseCostType"] = (int)component2.costType; state["purchaseAvailable"] = component2.available; state["purchaseLocked"] = component2.lockGameObject; } } private static void RestorePurchaseInteraction(T component, Dictionary state) where T : Component { PurchaseInteraction component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null) { return; } if (state.TryGetValue("purchaseCost", out object value)) { component2.Networkcost = (int)value; } if (state.TryGetValue("purchaseAvailable", out object value2)) { component2.SetAvailable((bool)value2); } if (state.TryGetValue("purchaseLocked", out object value3)) { bool? flag = value3 as bool?; if (flag.HasValue) { component2.lockGameObject = (flag.Value ? component2.lockGameObject : null); } } } private static void CaptureHealthComponent(T component, Dictionary state) where T : Component { HealthComponent component2 = ((Component)component).GetComponent(); if (!((Object)(object)component2 == (Object)null)) { object obj = component; CharacterBody val = (CharacterBody)((obj is CharacterBody) ? obj : null); state["healthFraction"] = component2.healthFraction; state["shieldFraction"] = ((component2.shield > 0f) ? (component2.shield / component2.fullHealth) : 0f); state["barrierFraction"] = ((component2.barrier > 0f) ? (component2.barrier / component2.fullHealth) : 0f); } } private static void RestoreHealthComponentAndRecalculateStats(T component, Dictionary state) where T : Component { HealthComponent component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 == (Object)null) { return; } object obj = component; CharacterBody val = (CharacterBody)((obj is CharacterBody) ? obj : null); if (component2.health > component2.fullHealth && component2.fullHealth > 0f) { component2.health = component2.fullHealth; } if (component2.fullHealth <= 0f && (Object)(object)val != (Object)null) { val.RecalculateStats(); if (component2.fullHealth <= 0f) { return; } } float num = 1f; if (state.TryGetValue("healthFraction", out object value)) { num = (float)value; } if ((Object)(object)val != (Object)null) { val.RecalculateStats(); } if (num >= 0f && component2.fullHealth > 0f) { float num2 = Mathf.Clamp01(num) * component2.fullHealth; num2 = Mathf.Clamp(num2, 0f, component2.fullHealth); component2.Networkhealth = num2; } else if (component2.fullHealth > 0f) { component2.Networkhealth = Mathf.Min(component2.health, component2.fullHealth); } if (state.TryGetValue("shieldFraction", out object value2)) { component2.Networkshield = Mathf.Clamp01((float)value2) * component2.fullHealth; } if (state.TryGetValue("barrierFraction", out object value3)) { component2.Networkbarrier = Mathf.Clamp01((float)value3) * component2.fullHealth; } } private static void CaptureEntityStateMachine(T component, Dictionary state) where T : Component { EntityStateMachine component2 = ((Component)component).GetComponent(); if ((Object)(object)component2 != (Object)null && component2.state != null) { Type type = ((object)component2.state).GetType(); if (type != null && !string.IsNullOrEmpty(type.FullName)) { state["EntityStateType"] = type.FullName; state["EntityStateMachineName"] = component2.customName; } } } private static void RestoreEntityStateMachine(T component, Dictionary state) where T : Component { if (!state.TryGetValue("EntityStateType", out object value) || !state.TryGetValue("EntityStateMachineName", out object value2)) { return; } string text = value?.ToString(); string targetMachineName = value2?.ToString(); if (string.IsNullOrEmpty(text) || string.IsNullOrEmpty(targetMachineName)) { return; } try { EntityStateMachine[] componentsInChildren = ((Component)component).GetComponentsInChildren(); EntityStateMachine val = null; if (!string.IsNullOrEmpty(targetMachineName)) { val = Array.Find(componentsInChildren, (EntityStateMachine sm) => sm.customName == targetMachineName); } if ((Object)(object)val == (Object)null && componentsInChildren.Length != 0) { val = componentsInChildren[0]; } if ((Object)(object)val == (Object)null) { Log.Warning("[EntityStateMachine] Could not find state machine on " + ((Object)((Component)component).gameObject).name); return; } Type type = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type[] types = assembly.GetTypes(); Type[] array = types; foreach (Type type2 in array) { if (type2.FullName == text && typeof(EntityState).IsAssignableFrom(type2)) { type = type2; break; } } if (type != null) { break; } } catch (ReflectionTypeLoadException) { } } if (type != null) { EntityState val2 = EntityStateCatalog.InstantiateState(type); if (val2 != null) { Log.Debug("[EntityStateMachine] Setting state " + text + " on " + ((Object)((Component)component).gameObject).name); val.SetState(val2); Log.Debug("[EntityStateMachine] Restored " + ((Object)((Component)component).gameObject).name + " to state " + text); } } else { Log.Warning("[EntityStateMachine] Could not find state type '" + text + "' for " + ((Object)((Component)component).gameObject).name); } } catch (Exception ex2) { Log.Error("[EntityStateMachine] Failed to restore state for " + ((Object)((Component)component).gameObject).name + ": " + ex2.Message); } } private static void CaptureMasterInventory(CharacterMaster master, Dictionary state) { if ((Object)(object)master.inventory != (Object)null) { CaptureInventory(master.inventory, state, "inventory."); } } private static void RestoreMasterInventory(CharacterMaster master, Dictionary state) { if ((Object)(object)master.inventory != (Object)null) { RestoreInventory(master.inventory, state, "inventory."); } } private static void CaptureInventory(Inventory inventory, Dictionary state, string prefix = "") { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected I4, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) List list = new List(); for (int i = 0; i < ItemCatalog.itemCount; i++) { int itemCountPermanent = inventory.GetItemCountPermanent((ItemIndex)i); if (itemCountPermanent > 0) { list.Add(i); list.Add(itemCountPermanent); } } state[prefix + "itemStacks"] = list; EquipmentState equipment = inventory.GetEquipment(0u, 0u); if ((int)equipment.equipmentIndex != -1) { state[prefix + "equipmentIndex"] = (int)equipment.equipmentIndex; state[prefix + "equipmentCharges"] = (int)equipment.charges; } state[prefix + "infusionBonus"] = (int)inventory.infusionBonus; } private static void RestoreInventory(Inventory inventory, Dictionary state, string prefix = "") { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (state.TryGetValue(prefix + "itemStacks", out object value) && value is List list) { for (int i = 0; i < ItemCatalog.itemCount; i++) { inventory.RemoveItemPermanent((ItemIndex)i, inventory.GetItemCountPermanent((ItemIndex)i)); } for (int j = 0; j < list.Count; j += 2) { ItemIndex val = (ItemIndex)list[j]; int num = list[j + 1]; inventory.GiveItemPermanent(val, num); } } if (state.TryGetValue(prefix + "equipmentIndex", out object value2)) { EquipmentIndex val2 = (EquipmentIndex)Convert.ToInt32(value2); object value3; int num2 = (state.TryGetValue(prefix + "equipmentCharges", out value3) ? Convert.ToInt32(value3) : 0); inventory.SetEquipmentIndex(val2, false); inventory.SetEquipment(new EquipmentState(val2, FixedTimeStamp.now, (byte)num2, false), 0u, 0u); } if (state.TryGetValue(prefix + "infusionBonus", out object value4)) { inventory.infusionBonus = (uint)Convert.ToInt32(value4); } } } public enum EncumbranceLevel { None, Light, Heavy, Over } public static class DrifterBagAPI { private class AutoGrabCoroutineRunner : MonoBehaviour { public IEnumerator? runningCoroutine; public void StartCoroutine(IEnumerator coroutine) { runningCoroutine = coroutine; ((MonoBehaviour)this).StartCoroutine(coroutine); } private void OnDestroy() { if (runningCoroutine != null) { ((MonoBehaviour)this).StopCoroutine(runningCoroutine); } } } [CompilerGenerated] private sealed class d__23 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public float delay; public GameObject obj; public DrifterBagController controller; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(delay); <>1__state = 1; return true; case 1: <>1__state = -1; if ((Object)(object)obj != (Object)null && obj.activeInHierarchy) { AddBaggedObject(controller, obj); } 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 readonly List _queryBuffer = new List(); private static readonly List _detailsBuffer = new List(); private static readonly Dictionary _countsBuffer = new Dictionary(StringComparer.OrdinalIgnoreCase); public static event Action? OnObjectGrabbed; public static event Action? OnObjectReleased; public static event Action? OnBagFull; public static event Action? OnOverencumbered; public static event Action? OnBagCleared; public static event Action? OnMainPassengerChanged; public static event Action? OnMassRecalculated; public static List GetBaggedObjects(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return new List(); } return new List(BagPatches.GetState(controller).BaggedObjects ?? new List()); } public static IReadOnlyList GetBaggedObjectsReadOnly(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return Array.Empty(); } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; return baggedObjects ?? new List(Array.Empty()); } public static void ForEachBaggedObject(DrifterBagController controller, Action action) { if ((Object)(object)controller == (Object)null || action == null) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null) { action(item); } } } public static void GetBaggedObjectsInto(DrifterBagController controller, List buffer) { if (buffer == null) { return; } buffer.Clear(); if ((Object)(object)controller == (Object)null) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null) { buffer.Add(item); } } } public static int GetBagCount(DrifterBagController controller) { return BagCapacityCalculator.GetCurrentBaggedCount(controller); } public static int GetBagCapacity(DrifterBagController controller) { return BagCapacityCalculator.GetUtilityMaxStock(controller); } public static bool HasRoom(DrifterBagController controller) { return BagCapacityCalculator.HasRoomForGrab(controller); } public static float GetTotalMass(DrifterBagController controller) { return BagCapacityCalculator.GetBaggedObjectMass(controller); } public static float GetObjectMass(DrifterBagController controller, GameObject obj) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return 0f; } return controller.CalculateBaggedObjectMass(obj); } public static string GetObjectName(GameObject obj) { if ((Object)(object)obj == (Object)null) { return "Unknown"; } CharacterBody component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { return component.GetDisplayName(); } return ((Object)obj).name; } public static Texture? GetObjectIcon(GameObject obj) { if ((Object)(object)obj == (Object)null) { return null; } CharacterBody component = obj.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component.portraitIcon != (Object)null) { return component.portraitIcon; } SpecialObjectAttributes component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null && (Object)(object)component2.portraitIcon != (Object)null) { return component2.portraitIcon; } return null; } public static bool IsObjectInBag(DrifterBagController controller, GameObject obj) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return false; } return BagPatches.GetState(controller).BaggedObjects?.Contains(obj) ?? false; } public static GameObject? GetMainPassenger(DrifterBagController controller) { return BagPatches.GetMainSeatObject(controller); } public static bool IsBlacklisted(string objectName) { return PluginConfig.IsBlacklisted(objectName); } public static bool SetMainPassenger(DrifterBagController controller, GameObject objRef) { if ((Object)(object)controller == (Object)null || (Object)(object)objRef == (Object)null) { return false; } List baggedObjects = GetBaggedObjects(controller); if (!baggedObjects.Contains(objRef)) { return false; } if ((Object)(object)GetMainPassenger(controller) == (Object)(object)objRef) { return true; } DelayedAutoPromote.Schedule(controller, objRef); return true; } public static bool AddBaggedObject(DrifterBagController controller, GameObject obj) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return false; } GrabbableObjectPatches.AddSpecialObjectAttributesToGrabbableObject(obj); controller.AssignPassenger(obj); if ((Object)(object)BagPatches.GetMainSeatObject(controller) == (Object)(object)obj) { CharacterBody componentInParent = ((Component)controller).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { EntityStateMachine val = EntityStateMachine.FindByCustomName(((Component)componentInParent).gameObject, "Bag"); if ((Object)(object)val != (Object)null) { Log.Debug("[DrifterBagAPI] Setting BaggedObject state on " + ((Object)componentInParent).name + " for " + ((Object)obj).name); BaggedObject val2 = new BaggedObject(); val2.targetObject = obj; val.SetNextState((EntityState)(object)val2); } } } return true; } public static void RemoveBaggedObject(DrifterBagController controller, GameObject obj, bool isDestroying = false) { if (!((Object)(object)controller == (Object)null) && !((Object)(object)obj == (Object)null)) { BagPassengerManager.RemoveBaggedObject(controller, obj, isDestroying); } } public static void ForceRecalculateMass(DrifterBagController controller) { if (!((Object)(object)controller == (Object)null)) { BagPassengerManager.ForceRecalculateMass(controller); } } public static void ClearBag(DrifterBagController controller, bool isDestroying = false) { if ((Object)(object)controller == (Object)null) { return; } List baggedObjects = GetBaggedObjects(controller); foreach (GameObject item in baggedObjects) { RemoveBaggedObject(controller, item, isDestroying); } InvokeOnBagCleared(controller, isDestroying); } public static void ScheduleAutoGrab(DrifterBagController controller, GameObject obj, float delay = 0.5f) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown if (!((Object)(object)controller == (Object)null) && !((Object)(object)obj == (Object)null)) { GameObject val = new GameObject("AutoGrabRunner_" + ((Object)obj).GetInstanceID()); AutoGrabCoroutineRunner autoGrabCoroutineRunner = val.AddComponent(); autoGrabCoroutineRunner.StartCoroutine(DelayedAutoGrabCoroutine(controller, obj, delay)); } } [IteratorStateMachine(typeof(d__23))] private static IEnumerator DelayedAutoGrabCoroutine(DrifterBagController controller, GameObject obj, float delay) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__23(0) { controller = controller, obj = obj, delay = delay }; } public static float GetMassRatio(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 0f; } float totalMass = GetTotalMass(controller); float maxMassCapacity = GetMaxMassCapacity(controller); if (maxMassCapacity == float.MaxValue || maxMassCapacity <= 0f) { return 0f; } return totalMass / maxMassCapacity; } public static float GetMassCapacity(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 0f; } return CapacityScalingSystem.CalculateMassCapacity(controller); } public static float GetMaxMassCapacity(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 0f; } return CapacityScalingSystem.CalculateMaxMassCapacity(controller); } public static EncumbranceLevel GetEncumbranceLevel(DrifterBagController controller) { float massRatio = GetMassRatio(controller); if (massRatio < 0.5f) { return EncumbranceLevel.None; } if (massRatio < 0.75f) { return EncumbranceLevel.Light; } if (massRatio < 1f) { return EncumbranceLevel.Heavy; } return EncumbranceLevel.Over; } public static bool IsOverencumbered(DrifterBagController controller) { return GetMassRatio(controller) > 1f; } public static float GetMoveSpeedPenalty(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 1f; } return StateCalculator.CalculateMovespeedPenalty(controller, GetTotalMass(controller)); } public static float GetDamageMultiplier(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return 1f; } return SlamDamageCalculator.GetEffectiveCoefficient(controller); } public static void RegisterFormulaVariable(string name, float value, string? description = null) { FormulaRegistry.RegisterVariable(name, value, description); } public static void RegisterFormulaVariable(string name, Func provider, string? description = null, float? fallbackValue = null) { FormulaRegistry.RegisterVariable(name, provider, description, fallbackValue); } public static bool RegisterFormulaVariableSafe(string name, float value, string? description = null, bool overwrite = false) { return FormulaRegistry.RegisterVariableSafe(name, value, description, overwrite); } public static bool RegisterFormulaVariableSafe(string name, Func provider, string? description = null, float? fallbackValue = null, bool overwrite = false) { return FormulaRegistry.RegisterVariableSafe(name, provider, description, fallbackValue, overwrite); } public static IEnumerable GetFormulaVariableNames() { return FormulaRegistry.GetRegisteredVariableNames(); } public static bool UnregisterFormulaVariable(string name) { return FormulaRegistry.UnregisterVariable(name); } public static bool IsFormulaVariableRegistered(string name) { return FormulaRegistry.IsVariableRegistered(name); } public static VariableInfo? GetFormulaVariableInfo(string name) { return FormulaRegistry.GetVariableInfo(name); } public static List GetBaggedObjectsByComponent(DrifterBagController controller) where T : Component { List list = new List(); TryGetBaggedObjectsByComponent(controller, list); return list; } public static void TryGetBaggedObjectsByComponent(DrifterBagController controller, List buffer) where T : Component { if (buffer == null) { return; } buffer.Clear(); if ((Object)(object)controller == (Object)null) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && (Object)(object)item.GetComponent() != (Object)null) { buffer.Add(item); } } } public static List GetBaggedCharacterBodies(DrifterBagController controller) { return DrifterBagAPI.GetBaggedObjectsByComponent(controller); } public static void TryGetBaggedCharacterBodies(DrifterBagController controller, List buffer) { DrifterBagAPI.TryGetBaggedObjectsByComponent(controller, buffer); } public static List GetBaggedObjectsByName(DrifterBagController controller, string nameContains) { List list = new List(); TryGetBaggedObjectsByName(controller, nameContains, list); return list; } public static void TryGetBaggedObjectsByName(DrifterBagController controller, string nameContains, List buffer) { if (buffer == null) { return; } buffer.Clear(); if ((Object)(object)controller == (Object)null || nameContains == null) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && ((Object)item).name.IndexOf(nameContains, StringComparison.OrdinalIgnoreCase) >= 0) { buffer.Add(item); } } } public static List GetBaggedObjectsByExactName(DrifterBagController controller, string exactName) { List list = new List(); TryGetBaggedObjectsByExactName(controller, exactName, list); return list; } public static void TryGetBaggedObjectsByExactName(DrifterBagController controller, string exactName, List buffer) { if (buffer == null) { return; } buffer.Clear(); if ((Object)(object)controller == (Object)null || exactName == null) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null && string.Equals(((Object)item).name, exactName, StringComparison.OrdinalIgnoreCase)) { buffer.Add(item); } } } public static List GetBaggedObjectsByMassRange(DrifterBagController controller, float minMass, float maxMass) { List list = new List(); TryGetBaggedObjectsByMassRange(controller, minMass, maxMass, list); return list; } public static void TryGetBaggedObjectsByMassRange(DrifterBagController controller, float minMass, float maxMass, List buffer) { if (buffer == null) { return; } buffer.Clear(); if ((Object)(object)controller == (Object)null) { return; } List baggedObjects = BagPatches.GetState(controller).BaggedObjects; if (baggedObjects == null) { return; } foreach (GameObject item in baggedObjects) { if ((Object)(object)item != (Object)null) { float objectMass = GetObjectMass(controller, item); if (objectMass >= minMass && objectMass <= maxMass) { buffer.Add(item); } } } } public static GameObject? GetHeaviestObject(DrifterBagController controller) { DrifterBagController controller2 = controller; GameObject heaviest = null; float maxMass = 0f; ForEachBaggedObject(controller2, delegate(GameObject obj) { float objectMass = GetObjectMass(controller2, obj); if (objectMass > maxMass) { maxMass = objectMass; heaviest = obj; } }); return heaviest; } public static GameObject? GetLightestObject(DrifterBagController controller) { DrifterBagController controller2 = controller; GameObject lightest = null; float minMass = float.MaxValue; ForEachBaggedObject(controller2, delegate(GameObject obj) { float objectMass = GetObjectMass(controller2, obj); if (objectMass < minMass) { minMass = objectMass; lightest = obj; } }); return lightest; } public static bool TryGrab(DrifterBagController controller, GameObject obj) { if ((Object)(object)controller == (Object)null || (Object)(object)obj == (Object)null) { return false; } if (!HasRoom(controller)) { return false; } return AddBaggedObject(controller, obj); } public static bool TryReleaseMainPassenger(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return false; } GameObject mainPassenger = GetMainPassenger(controller); if ((Object)(object)mainPassenger == (Object)null) { return false; } RemoveBaggedObject(controller, mainPassenger); return true; } public static int ReleaseObjectsByType(DrifterBagController controller) where T : Component { if ((Object)(object)controller == (Object)null) { return 0; } List baggedObjectsByComponent = GetBaggedObjectsByComponent(controller); int num = 0; foreach (GameObject item in baggedObjectsByComponent) { RemoveBaggedObject(controller, item); num++; } return num; } public static string GetFormattedBagSummary(DrifterBagController controller) { if ((Object)(object)controller == (Object)null) { return "Bag: N/A"; } int bagCount = GetBagCount(controller); int bagCapacity = GetBagCapacity(controller); float totalMass = GetTotalMass(controller); float massCapacity = GetMassCapacity(controller); float massRatio = GetMassRatio(controller); string text = ((bagCapacity == int.MaxValue) ? $"{bagCount}/∞" : $"{bagCount}/{bagCapacity}"); string text2 = ((massCapacity == float.MaxValue) ? "∞" : massCapacity.ToString("F0")); return $"Bag: {text} | Mass: {totalMass:F0}/{text2} ({massRatio:P0})"; } public static List GetBaggedObjectDetails(DrifterBagController controller) { DrifterBagController controller2 = controller; _detailsBuffer.Clear(); if ((Object)(object)controller2 == (Object)null) { return new List(_detailsBuffer); } int index = 1; ForEachBaggedObject(controller2, delegate(GameObject obj) { string objectName = GetObjectName(obj); float objectMass = GetObjectMass(controller2, obj); _detailsBuffer.Add($"{index}. {objectName} ({objectMass:F1}kg)"); index++; }); return new List(_detailsBuffer); } public static void TryGetBaggedObjectDetails(DrifterBagController controller, List buffer) { DrifterBagController controller2 = controller; List buffer2 = buffer; if (buffer2 == null) { return; } buffer2.Clear(); if (!((Object)(object)controller2 == (Object)null)) { int index = 1; ForEachBaggedObject(controller2, delegate(GameObject obj) { string objectName = GetObjectName(obj); float objectMass = GetObjectMass(controller2, obj); buffer2.Add($"{index}. {objectName} ({objectMass:F1}kg)"); index++; }); } } public static Dictionary GetBaggedObjectCounts(DrifterBagController controller) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); GetBaggedObjectCountsInto(controller, dictionary); return dictionary; } public static void GetBaggedObjectCountsInto(DrifterBagController controller, Dictionary buffer) { Dictionary buffer2 = buffer; if (buffer2 == null) { return; } buffer2.Clear(); if ((Object)(object)controller == (Object)null) { return; } ForEachBaggedObject(controller, delegate(GameObject obj) { string objectName = GetObjectName(obj); if (!buffer2.ContainsKey(objectName)) { buffer2[objectName] = 0; } buffer2[objectName]++; }); } internal static void InvokeOnObjectGrabbed(DrifterBagController controller, GameObject obj, int slotIndex) { DrifterBagAPI.OnObjectGrabbed?.Invoke(controller, obj, slotIndex); } internal static void InvokeOnObjectReleased(DrifterBagController controller, GameObject obj, bool wasDestroyed) { DrifterBagAPI.OnObjectReleased?.Invoke(controller, obj, wasDestroyed); } internal static void InvokeOnBagFull(DrifterBagController controller) { DrifterBagAPI.OnBagFull?.Invoke(controller); } internal static void InvokeOnOverencumbered(DrifterBagController controller, float massRatio) { DrifterBagAPI.OnOverencumbered?.Invoke(controller, massRatio); } internal static void InvokeOnBagCleared(DrifterBagController controller, bool wasDestroyed) { DrifterBagAPI.OnBagCleared?.Invoke(controller, wasDestroyed); } internal static void InvokeOnMainPassengerChanged(DrifterBagController controller, GameObject? previousObj, GameObject? newObj) { DrifterBagAPI.OnMainPassengerChanged?.Invoke(controller, previousObj, newObj); } internal static void InvokeOnMassRecalculated(DrifterBagController controller, float newTotalMass, float previousTotalMass) { DrifterBagAPI.OnMassRecalculated?.Invoke(controller, newTotalMass, previousTotalMass); } public static void RegisterSerializerPlugin(IObjectSerializerPlugin plugin) { ProperSaveIntegration.RegisterPlugin(plugin); } public static List GetSerializerPlugins() { return ProperSaveIntegration.GetSerializerPlugins(); } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }