Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PracticeSandbox v0.1.79
BepInEx\plugins\PracticeSandbox\PracticeSandbox.dll
Decompiled a week ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Logging; using GameNetcodeStuff; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("com.github.goshujinsama.PracticeSandbox")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("0.1.0.0")] [assembly: AssemblyInformationalVersion("0.1.0")] [assembly: AssemblyProduct("com.github.goshujinsama.PracticeSandbox")] [assembly: AssemblyTitle("PracticeSandbox")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.1.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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")] [Embedded] 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")] [Embedded] internal sealed class PatcherAutoPluginAttribute : Attribute { public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null) { } } } namespace Microsoft.CodeAnalysis { [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace PracticeSandbox { [BepInPlugin("com.github.goshujinsama.PracticeSandbox", "Practice Sandbox", "0.1.79.8")] public class Plugin : BaseUnityPlugin { public const string ModGuid = "com.github.goshujinsama.PracticeSandbox"; public const string ModName = "Practice Sandbox"; public const string ModVersion = "0.1.79.8"; internal static ManualLogSource Log; private readonly Harmony harmony = new Harmony("com.github.goshujinsama.PracticeSandbox"); private void Awake() { Log = ((BaseUnityPlugin)this).Logger; Log.LogInfo((object)"Practice Sandbox 0.1.79.8 loaded (stable: persistent multi-Fox mold / BushWolf rescue recovery / terminal restore)."); harmony.PatchAll(); PracticeController.PatchEnemyNoiseDetection(harmony); PracticeController.PatchBrackenKillAnimationGuard(harmony); } private void Update() { PracticeController.RuntimeFrameTick("Plugin.Update"); } } internal static class PracticeDiagnosticFile { private static readonly object Gate = new object(); private static StreamWriter writer; internal static string LogPath { get; private set; } = ""; internal static void Initialize() { LogPath = ""; } [Conditional("PRACTICE_SANDBOX_DIAGNOSTICS")] internal static void Write(string tag, string message) { } } internal enum PracticeSpawnMode { Normal, CircuitBees, GiantSapsucker, KidnapperFox } internal enum EnemyOnlyCageMode { Off, Floor, Full } internal enum PracticeJesterSpawnMode { Default, PreCrank, Popped } internal sealed class EnemyDefinition { public string DisplayName { get; } public string PrimaryAlias { get; } public string[] Aliases { get; } public string[] SearchWords { get; } public string[] ExcludeWords { get; } public EnemyType? EnemyType { get; set; } public bool PreferOutside { get; } public PracticeSpawnMode SpawnMode { get; } public EnemyDefinition(string displayName, string primaryAlias, bool preferOutside, PracticeSpawnMode spawnMode, string[] searchWords, string[]? extraAliases = null, string[]? excludeWords = null) { DisplayName = displayName; PrimaryAlias = PracticeController.Normalize(primaryAlias); PreferOutside = preferOutside; SpawnMode = spawnMode; List<string> list = new List<string> { PrimaryAlias }; if (extraAliases != null) { list.AddRange(extraAliases.Select(PracticeController.Normalize)); } Aliases = list.Where((string alias) => !string.IsNullOrWhiteSpace(alias)).Distinct().ToArray(); List<string> list2 = new List<string> { displayName }; list2.AddRange(searchWords ?? Array.Empty<string>()); SearchWords = list2.Where((string word) => !string.IsNullOrWhiteSpace(word)).Select(PracticeController.Normalize).Distinct() .ToArray(); ExcludeWords = (excludeWords ?? Array.Empty<string>()).Where((string word) => !string.IsNullOrWhiteSpace(word)).Select(PracticeController.Normalize).Distinct() .ToArray(); } } internal sealed class PracticeItemDefinition { public string DisplayName { get; } public string NormalizedName { get; } public string Alias { get; } public Item Item { get; } public bool IsBuyable { get; } public bool IsScrap { get; } public PracticeItemDefinition(Item item, string alias, bool isBuyable, bool isScrap) { Item = item; DisplayName = item.itemName ?? ((Object)item).name ?? "Unknown item"; NormalizedName = PracticeController.Normalize(DisplayName); Alias = PracticeController.Normalize(alias); IsBuyable = isBuyable; IsScrap = isScrap; } } internal readonly struct ParsedCommand { public string Name { get; } public int Count { get; } public ParsedCommand(string name, int count) { Name = name; Count = count; } } internal sealed class PracticeSpecialSpawnGroup { public int GroupId; public int EnemyInstanceId; public string Origin = ""; public Vector3 Center; public EnemyAI? Enemy; public readonly List<GameObject> StructuralObjects = new List<GameObject>(); public readonly List<Vector3> StructuralPositions = new List<Vector3>(); public readonly List<GrabbableObject> LootObjects = new List<GrabbableObject>(); public readonly HashSet<int> RegisteredObjectIds = new HashSet<int>(); public float ResolveUntilTime; public bool LayoutApplied; public float NextDiagnosticTime; } internal sealed class PracticeBoundsBoxVisual { public GameObject? Root; public Mesh? Mesh; public Renderer? Renderer; public Material? Material; public Vector3[] Vertices = (Vector3[])(object)new Vector3[96]; public float Thickness; public string RenderMethod = "CombinedMeshEdges/CreateVisibleMaterial"; } internal sealed class PracticeSpecialLootRecord { public GrabbableObject? Item; public int GroupId; public string Origin = ""; public PracticeBoundsBoxVisual? Marker; public string MarkerBoundsSource = "uninitialized"; public float NextMarkerDiagnosticTime; } internal sealed class PracticeHitboxVisual { public Collider? Collider; public PracticeBoundsBoxVisual? Box; public bool Attack; } internal static class PracticeController { internal static bool PracticeQueued = false; internal static bool PracticeActive = false; internal static bool ManualEnemySpawnInProgress = false; internal static bool ArenaCreated = false; internal static readonly List<EnemyAI> SpawnedEnemies = new List<EnemyAI>(); private static readonly List<GameObject> ArenaObjects = new List<GameObject>(); private static readonly List<GameObject> PracticeSpawnedUtilityObjects = new List<GameObject>(); private static readonly List<PracticeSpecialSpawnGroup> PracticeSpecialSpawnGroups = new List<PracticeSpecialSpawnGroup>(); private static readonly Dictionary<int, PracticeSpecialLootRecord> PracticeSpecialLootByInstanceId = new Dictionary<int, PracticeSpecialLootRecord>(); private static readonly List<GameObject> PracticeSpecialStructuralObjects = new List<GameObject>(); private static readonly List<PracticeHitboxVisual> PracticeHitboxVisuals = new List<PracticeHitboxVisual>(); private static readonly Dictionary<int, Vector3> PracticeGiantKiwiNestTargets = new Dictionary<int, Vector3>(); private static readonly HashSet<int> PracticeGiantKiwiNestOverrideLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, Vector3> PracticeGiantKiwiNestOriginalPositions = new Dictionary<int, Vector3>(); private static readonly Dictionary<int, Vector3> PracticeGiantKiwiNestMoveDeltas = new Dictionary<int, Vector3>(); private static readonly HashSet<int> PracticeGiantKiwiNestRelocatedIds = new HashSet<int>(); private static readonly HashSet<int> PracticeGiantKiwiEggRelocatedIds = new HashSet<int>(); private static readonly Dictionary<int, Vector3> PracticeGiantKiwiHomePositions = new Dictionary<int, Vector3>(); private static readonly Dictionary<int, float> PracticeGiantKiwiHomeRestoreDueTimes = new Dictionary<int, float>(); private static readonly HashSet<int> PracticeGiantKiwiHomeRestoreLoggedIds = new HashSet<int>(); private static readonly HashSet<int> PracticeGiantKiwiKillStackLoggedIds = new HashSet<int>(); internal static bool PracticeManualMoldGenerationInProgress = false; private static float nextInvAbyssRescueAllowedTime = 0f; private static int nextSpecialSpawnGroupId = 1; private static bool PracticeStatsOverlayEnabled = true; private static bool PracticeHitboxOverlayEnabled = false; private static float nextSpecialSpawnResolveTime = 0f; private static bool hitboxRefreshDirty = false; private static string hitboxDirtyReason = "initial"; private static float nextHitboxTransformUpdateTime = 0f; private static float nextHitboxPlayerRosterCheckTime = 0f; private static int lastHitboxRemotePlayerCount = -1; private static float nextSpecialLootVisualUpdateTime = 0f; private static float nextFastBoundaryTickTime = 0f; private static float nextPlayerFacilityFlagTime = 0f; private static float nextAwarenessFastTickTime = 0f; private static GUIStyle? practiceHpGuiStyle; private static GUIStyle? practiceStGuiStyle; private static GUIStyle? practiceShadowGuiStyle; private static float nextStatsOverlayDiagTime = 0f; private static float nextHitboxRuntimeDiagTime = 0f; private static bool statsOverlayFirstDrawLogged = false; private static int hitboxCreateFailureCount = 0; private static string hitboxLastCreateError = ""; private const bool TargetedChatDebugEnabled = false; private const bool TargetedHitboxDebugEnabled = false; private const bool TargetedOldBirdThreatDebugEnabled = false; private static bool practiceChatHandledThisSubmit = false; private static string practicePendingChatResult = ""; private static string practicePendingChatRaw = ""; private static int practiceChatSequence = 0; private static readonly Dictionary<string, float> OldBirdThreatEventNextLogTimes = new Dictionary<string, float>(); private static readonly Dictionary<string, float> GiantKiwiThreatEventNextLogTimes = new Dictionary<string, float>(); private static readonly Dictionary<int, float> OldBirdThreatSnapshotNextTimes = new Dictionary<int, float>(); private static readonly Dictionary<Type, MemberInfo[]> OldBirdThreatMembersByType = new Dictionary<Type, MemberInfo[]>(); private static readonly Dictionary<int, string> OldBirdThreatCapabilityByEnemyId = new Dictionary<int, string>(); private static readonly Dictionary<int, float> OldBirdNonPlayerThreatSeenSince = new Dictionary<int, float>(); private static readonly Dictionary<int, float> OldBirdEntityAlertAssistCooldownUntil = new Dictionary<int, float>(); private static readonly Dictionary<int, float> OldBirdEntityAttackSeenSince = new Dictionary<int, float>(); private static readonly Dictionary<int, float> OldBirdEntityAttackAssistCooldownUntil = new Dictionary<int, float>(); private static readonly HashSet<int> BrackenMemberInventoryLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, int> BrackenLastBehaviourStateById = new Dictionary<int, int>(); private static readonly Dictionary<int, float> BrackenLastStateLogTimeById = new Dictionary<int, float>(); private static bool baboonGroupRefreshPending = false; private static float baboonGroupRefreshAt = 0f; private static string baboonGroupLastSignature = ""; private static GameObject? PracticeBaboonCampObject; private static bool practiceAmbientEffectsDisabled = false; private static readonly HashSet<int> PracticeManuallySpawnedItemIds = new HashSet<int>(); private static readonly List<GameObject> PendingFoxGrassObjects = new List<GameObject>(); private static Vector3 PendingFoxGrassCenter = Vector3.zero; private static bool ambientSourceInventoryLogged = false; private static bool initialLooseItemCleanupDone = false; private static float initialLooseItemCleanupAt = 0f; private static int lastRuntimeFrameTick = -1; private static float nextRuntimeDriverDiagTime = 0f; private static string lastRuntimeDriverSource = "none"; private static GameObject? practiceStatsCanvasObject; private static Component? practiceStatsTextComponent; private static RectTransform? practiceStatsTextRect; private static float nextStatsHudDiagTime = 0f; private static float nextStatsHudUpdateTime = 0f; private static bool practiceStatsFixedPositionCaptured = false; private static Vector2 practiceStatsFixedAnchoredPosition = new Vector2(210f, -70f); private static bool statsHudCreatedLogged = false; private static string practiceStatsLastRenderedText = ""; private static readonly List<Renderer> DisabledMapRenderers = new List<Renderer>(); private static readonly List<Collider> DisabledMapColliders = new List<Collider>(); private static readonly List<Terrain> DisabledTerrains = new List<Terrain>(); private static readonly List<NavMeshData> PracticeNavMeshDataList = new List<NavMeshData>(); private static readonly List<NavMeshDataInstance> PracticeNavMeshInstances = new List<NavMeshDataInstance>(); private static readonly Dictionary<int, float> EnemyBarrierPushCooldown = new Dictionary<int, float>(); private static readonly HashSet<int> JesterPracticePoppedIds = new HashSet<int>(); private static readonly HashSet<int> JesterPracticeNoResetArmedIds = new HashSet<int>(); private static readonly HashSet<int> JesterPracticePreCrankIds = new HashSet<int>(); private static readonly HashSet<int> JesterInitializationSeenIds = new HashSet<int>(); private static readonly HashSet<int> JesterCrankStartedIds = new HashSet<int>(); private static readonly Dictionary<int, float> JesterSequenceNextDiagTimes = new Dictionary<int, float>(); private static readonly HashSet<int> JesterMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> ForcedAdultManeaterIds = new HashSet<int>(); private static readonly Dictionary<int, float> MouthDogDirectLungeNextTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> DogDeepDiagNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> DogMethodInventoryLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, float> ManeaterRecoveryUntilTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> ManeaterDeepDiagNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> ManeaterMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> ManeaterDeferredResetIds = new HashSet<int>(); private static readonly HashSet<int> ManeaterResetInProgressIds = new HashSet<int>(); private static readonly Dictionary<int, string> ManeaterDeferredResetReasons = new Dictionary<int, string>(); private static readonly Dictionary<int, float> OldBirdDiagNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> OldBirdMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> OldBirdWakeAttemptedIds = new HashSet<int>(); private static readonly Dictionary<int, float> ForestGiantDiagNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> ForestGiantMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> EnemyPostSpawnIdentityLoggedIds = new HashSet<int>(); private static readonly HashSet<int> DogKeywordMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> OldBirdKeywordMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> ForestGiantKeywordMethodInventoryLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, int> ForestGiantZeroAnimatorMotionFrames = new Dictionary<int, int>(); private static readonly Dictionary<int, float> ForestGiantAnimatorFixNextLogTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> ForestGiantLifecycleHookNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> ForestGiantStaleEatRecoveryAttemptedIds = new HashSet<int>(); private static readonly Dictionary<int, float> ForestGiantVisionAssistNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> DogSpawnAnimatorRecoveredIds = new HashSet<int>(); private static readonly Dictionary<int, float> OldBirdSpawnRealtimeById = new Dictionary<int, float>(); private static readonly Dictionary<int, float> OldBirdEarlyKillLogNextTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> MaskedDiagNextTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> MaskedLifecycleHookNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> MaskedMethodInventoryLoggedIds = new HashSet<int>(); private static readonly HashSet<int> MaskedKeywordMethodInventoryLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, float> MaskedResetDueTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, string> MaskedResetReasons = new Dictionary<int, string>(); private static readonly HashSet<int> MaskedPendingPostFinishResetIds = new HashSet<int>(); private static readonly HashSet<int> MaskedCancelStackLoggedIds = new HashSet<int>(); private static readonly HashSet<int> OldBirdDespawnStackLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, float> ForestGiantPassiveDiagNextTimes = new Dictionary<int, float>(); private static readonly List<GameObject> PracticeOldBirdNestObjects = new List<GameObject>(); private static readonly Dictionary<int, float> ForestGiantVisionProbeNextTimes = new Dictionary<int, float>(); private static readonly HashSet<int> ForestGiantSpawnFinishedLoggedIds = new HashSet<int>(); private static readonly Dictionary<int, float> MaskedCollisionSuppressUntil = new Dictionary<int, float>(); private static readonly Dictionary<int, string> MaskedNextFrameRearmReasons = new Dictionary<int, string>(); private static bool PracticeDeletionInProgress = false; private static readonly Dictionary<string, PracticeItemDefinition> CachedItemsByNormalizedName = new Dictionary<string, PracticeItemDefinition>(); private static readonly Dictionary<string, int> StoreItemOrderByNormalizedName = new Dictionary<string, int>(); private static readonly HashSet<string> LevelSpawnableScrapNormalizedNames = new HashSet<string>(); private static readonly List<PracticeItemDefinition> CachedPracticeItems = new List<PracticeItemDefinition>(); internal static Vector3 PracticeAreaCenter; internal static float PracticeAreaHalfSize = 60f; internal static Vector3 EnemyAreaCenter; internal static float EnemyAreaHalfSize = 25f; private static Vector3 EnemyAreaForward = Vector3.forward; private static Vector3 EnemyAreaRight = Vector3.right; private static bool UseInvertedShipRightAsFront = true; private static float nextRuntimeTickTime = 0f; private static float nextSlowTickTime = 0f; private static float nextEnemyRescanTime = 0f; private static float nextArenaAttemptTime = 0f; private static float arenaCreationAllowedTime = 0f; private static float nextTerminalInteractionRepairTime = 0f; private static readonly HashSet<int> ShipTerminalProtectedObjectIds = new HashSet<int>(); private static float lateWorldCleanupDueTime = 0f; private static bool lateWorldCleanupPending = false; private static readonly Dictionary<int, float> OldBirdDeepDiagNextTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> BushWolfPostRescueResetDueTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, int> BushWolfPostRescueResetAttempts = new Dictionary<int, int>(); private static GameObject PracticeFoxGrassTemplate = null; private static readonly Dictionary<int, float> BushWolfOriginalBaseOffsets = new Dictionary<int, float>(); private static readonly Dictionary<int, int> BushWolfGrowlCounts = new Dictionary<int, int>(); private static readonly Dictionary<int, float> BushWolfGrowlLastTimes = new Dictionary<int, float>(); private static float nextNoonTimeForceTime = 0f; private static float localPlayerPostHealCleanupUntilTime = 0f; private const bool DiagnosticLoggingEnabled = false; private static float nextPluginUpdateDiagnosticTime = 0f; private static float nextArenaDiagnosticLogTime = 0f; private static float nextNavMeshDiagnosticLogTime = 0f; private static float nextEnemySummaryDiagnosticTime = 0f; private static readonly Dictionary<int, float> EnemyDiagnosticNextLogTimes = new Dictionary<int, float>(); private static bool floorPostProcessingArenaAttempted = false; private static bool LocalPlayerInvincible = false; private static float nextInvincibleDetailedDiagTime = 0f; private static bool lastInvincibleObservedDeadState = false; private static bool invincibleFieldInventoryLogged = false; private static bool AutoRescueEnabled = true; private static bool PracticeCriticalInjuryEnabled = true; private static bool CriticalVisualHealthGateEnabled = true; private const int CriticalVisualClearHealthThreshold = 20; private static float nextCriticalVisualHealthGateTime = 0f; private static int lastCriticalGateObservedHealth = -1; private static bool lastCriticalGateObservedCritical = false; private static bool criticalVisualClearAppliedForHealthyState = false; private static bool ManeaterHardRefreshEnabled = false; private static bool ManeaterForceAdultVisualEnabled = false; private static bool ManeaterAdultRespawnFromAdultEnabled = true; private static bool JesterPracticeAggroEnabled = true; private static bool JesterPracticeNoResetEnabled = true; private static bool MouthDogPracticeChargeEnabled = true; private const float JesterPracticeCrankDelaySeconds = 2.5f; private const float JesterPracticePopDelaySeconds = 4f; private const float MouthDogPracticeChargeSpeed = 18f; private const float MouthDogDirectLungeDistance = 24f; private const float ManeaterPracticeMinimumChaseSpeed = 18f; private const float ManeaterPracticeAttackSpeed = 26f; private const float EnemyBoundaryInnerMargin = 4f; private static bool EnemyRedBoundaryGuardEnabled = true; private static bool EnemyLeashEnabled = false; private static bool TulipContinuousCollisionDiagnostics = false; private static bool TulipBoundaryGuardEnabled = true; private static bool HidePlayersOutsideEnemyAreaFromEnemies = true; private static bool pendingLocalPlayerRescueScheduled = false; private static float pendingLocalPlayerRescueTime = 0f; private static string pendingLocalPlayerRescueReason = ""; private static float nextAwarenessSuppressionTime = 0f; private static EnemyOnlyCageMode CurrentEnemyOnlyCageMode = EnemyOnlyCageMode.Off; private static readonly List<GameObject> EnemyOnlyCageObjects = new List<GameObject>(); private static readonly List<Collider> EnemyOnlyCageColliders = new List<Collider>(); private static readonly List<Collider> EnemyBoundaryWallColliders = new List<Collider>(); private const float EnemyBoundaryEmergencyReturnOvershoot = 3f; private static readonly Dictionary<int, float> CageDiagnosticNextLogTimes = new Dictionary<int, float>(); private static readonly Dictionary<int, float> TulipBoundaryGuardNextTimes = new Dictionary<int, float>(); private static bool roundManagerRefreshAttempted = false; private static bool itemCacheDirty = true; private const float PlatformWidth = 120f; private const float PlatformLength = 120f; private const float PlatformThickness = 0.6f; private const float EnemySpawnHeightAbovePlatform = 2f; private const float EnemyAreaWidth = 52f; private const float EnemyAreaLength = 52f; private const float PlatformTopOffsetFromShip = -2.05f; private const float EnemyAreaNearEdgeFromShip = 20f; private const float PlayerRespawnDistanceFromShip = 14f; private const int PracticeNavMeshAreaMask = 1; private const float PracticeNavMeshHeightTolerance = 0.45f; private static readonly List<EnemyDefinition> EnemyDefinitions = new List<EnemyDefinition> { new EnemyDefinition("masked", "mas", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "masked" }), new EnemyDefinition("nutcracker", "nut", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "nutcracker" }), new EnemyDefinition("bracken", "bra", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "bracken", "flowerman" }, new string[1] { "da-" }), new EnemyDefinition("coilhead", "coi", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "coilhead", "springman", "spring" }), new EnemyDefinition("thumper", "thu", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "thumper", "crawler" }, new string[1] { "tam" }), new EnemyDefinition("spider", "spi", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "spider", "bunkerspider", "bunker spider" }), new EnemyDefinition("hoarder", "hoa", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "hoarder", "hoardingbug", "hoarding bug" }), new EnemyDefinition("hygrodere", "hyg", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "hygrodere", "slime", "blob" }), new EnemyDefinition("jester", "jes", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "jester" }), new EnemyDefinition("butler", "but", preferOutside: false, PracticeSpawnMode.Normal, new string[1] { "butler" }), new EnemyDefinition("dog", "dog", preferOutside: true, PracticeSpawnMode.Normal, new string[5] { "mouthdog", "mouth dog", "eyelessdog", "eyeless dog", "dog" }, new string[5] { "eye", "mouthdog", "mouth dog", "eyelessdog", "eyeless dog" }), new EnemyDefinition("baboonhawk", "bab", preferOutside: true, PracticeSpawnMode.Normal, new string[3] { "baboonhawk", "baboon hawk", "baboon" }), new EnemyDefinition("forestgiant", "for", preferOutside: true, PracticeSpawnMode.Normal, new string[3] { "forestgiant", "forest giant", "giant" }), new EnemyDefinition("oldbird", "old", preferOutside: true, PracticeSpawnMode.Normal, new string[4] { "oldbird", "old bird", "radmech", "rad mech" }, new string[5] { "bird", "oldbird", "old bird", "radmech", "rad mech" }), new EnemyDefinition("maneater", "man", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "maneater", "maneaterbaby", "maneater baby" }), new EnemyDefinition("barber", "bar", preferOutside: false, PracticeSpawnMode.Normal, new string[3] { "barber", "claysurgeon", "clay surgeon" }), new EnemyDefinition("tulipsnake", "tul", preferOutside: true, PracticeSpawnMode.Normal, new string[2] { "tulipsnake", "tulip snake" }), new EnemyDefinition("kidnapperfox", "kid", preferOutside: true, PracticeSpawnMode.KidnapperFox, new string[5] { "kidnapperfox", "kidnapper fox", "bushwolf", "bush wolf", "fox" }, new string[1] { "fox" }), new EnemyDefinition("circuitbees", "cir", preferOutside: true, PracticeSpawnMode.CircuitBees, new string[6] { "redlocustbees", "red locust bees", "redlocust", "circuitbees", "circuit bees", "circuit" }, new string[1] { "bee" }, new string[2] { "docile", "roaming" }), new EnemyDefinition("giantsapsucker", "gia", preferOutside: true, PracticeSpawnMode.GiantSapsucker, new string[7] { "giantsapsucker", "giant sapsucker", "sapsucker", "giantkiwi", "giant kiwi", "kiwi", "giantkiwiai" }, new string[1] { "sap" }), new EnemyDefinition("roaminglocust", "roa", preferOutside: true, PracticeSpawnMode.Normal, new string[5] { "docilelocustbees", "docile locust bees", "docilelocust", "roaminglocust", "roaming locust" }, new string[1] { "loc" }, new string[2] { "redlocust", "circuit" }), new EnemyDefinition("maskhornets", "hor", preferOutside: true, PracticeSpawnMode.Normal, new string[4] { "maskhornets", "mask hornets", "butlerbees", "butler bees" }), new EnemyDefinition("cadaverbloom", "blo", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "cadaverbloom", "cadaver bloom" }, new string[1] { "cad" }), new EnemyDefinition("lassoman", "las", preferOutside: false, PracticeSpawnMode.Normal, new string[2] { "lassoman", "lasso man" }), new EnemyDefinition("redpill", "red", preferOutside: false, PracticeSpawnMode.Normal, new string[5] { "redpill", "red pill", "redpillanomaly", "testenemy", "test enemy" }), new EnemyDefinition("ghostgirl", "gho", preferOutside: false, PracticeSpawnMode.Normal, new string[5] { "ghostgirl", "ghost girl", "dressgirl", "dress girl", "girl" }, new string[1] { "gir" }) }; private static readonly Dictionary<string, string> SpecialItemAliases = new Dictionary<string, string> { { "shovel", "sho" }, { "shotgun", "shot" }, { "goldbar", "gbar" }, { "goldencup", "gcup" }, { "hairbrush", "hbru" }, { "hairdryer", "hdry" }, { "plasticcup", "pcup" }, { "plasticfish", "pfis" }, { "toycube", "toyc" }, { "toytrain", "toyt" }, { "toyrobot", "toyr" }, { "eggbeater", "eggb" }, { "clownhorn", "clow" }, { "clock", "cloc" }, { "magic7ball", "m7b" }, { "magnifyingglass", "magn" }, { "shotgunshells", "shs" }, { "beehive", "beh" }, { "hive", "beh" }, { "oldphone", "phon" }, { "brassbell", "bell" }, { "vtypeengine", "vte" }, { "doublebarrelshotgun", "dbsg" }, { "yieldsign", "yie" }, { "stopsign", "sto" }, { "largeaxle", "lar" }, { "tatteredmetalsheet", "tat" }, { "diyflashbang", "diy" }, { "whoopiecushion", "who" }, { "jarchofpickles", "jar" }, { "jarofpickles", "jar" }, { "cashregister", "cas" }, { "apparatus", "app" } }; private static readonly HashSet<string> SpecialOrSystemScrapNormalizedNames = new HashSet<string> { "apparatus", "key", "keys", "beehive", "hive", "shotgun", "doublebarrelshotgun", "shotgunshells", "knife" }; private static readonly int[] BoundsBoxTriangleTemplate = BuildBoundsBoxTriangleTemplate(); private static readonly string[] ManeaterDiagnosticKeywords = new string[19] { "attack", "kill", "charge", "lunge", "eat", "eating", "maul", "grab", "held", "hold", "target", "player", "animation", "state", "baby", "anger", "rage", "cooldown", "timer" }; private static readonly Dictionary<int, float> DogAnimationCalculationNextTimes = new Dictionary<int, float>(); private static readonly string[] MaskedDiagnosticKeywords = new string[11] { "kill", "animation", "player", "target", "special", "coroutine", "cooldown", "stun", "chase", "mimic", "mask" }; internal static bool DiagnosticsEnabled => false; internal static void LogFeatureContractDiagnostics() { try { string[] value = new string[4] { DescribeRuntimeMemberContract("RedLocustBees", new string[4] { "hive", "hasSpawnedHive", "lastKnownHivePosition", "syncedLastKnownHivePosition" }), DescribeRuntimeMemberContract("GiantKiwiAI", new string[7] { "birdNest", "birdNestPrefab", "eggPrefab", "eggs", "hasSpawnedEggs", "nestPosition", "newNestPosition" }), DescribeRuntimeMemberContract(typeof(PlayerControllerB).FullName, new string[4] { "health", "sprintMeter", "sprintMeterUI", "isPlayerControlled" }), DescribeRuntimeMemberContract(typeof(Terminal).FullName, new string[2] { "screenText", "textAdded" }) }; string text = string.Join(" || ", value); Plugin.Log.LogInfo((object)("[DllContract] " + text)); } catch (Exception ex) { string text2 = "contract diagnostic failed " + ex.GetType().Name + ":" + ex.Message; Plugin.Log.LogWarning((object)("[DllContract] " + text2)); } } private static string DescribeRuntimeMemberContract(string typeName, IEnumerable<string> memberNames) { Type type = AccessTools.TypeByName(typeName); if (type == null) { return typeName + "=<TYPE NOT FOUND>"; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic; List<string> list = new List<string>(); foreach (string memberName in memberNames) { FieldInfo field = type.GetField(memberName, bindingAttr); if (field != null) { list.Add(memberName + ":field:" + field.FieldType.FullName); continue; } PropertyInfo property = type.GetProperty(memberName, bindingAttr); if (property != null) { list.Add(memberName + ":property:" + property.PropertyType.FullName); } else { list.Add(memberName + ":MISSING"); } } return type.FullName + "[" + string.Join(",", list) + "]"; } internal static void RuntimeFrameTick(string source) { int frameCount = Time.frameCount; if (lastRuntimeFrameTick == frameCount) { return; } lastRuntimeFrameTick = frameCount; lastRuntimeDriverSource = (string.IsNullOrWhiteSpace(source) ? "unknown" : source); try { PluginVisualTick(); PluginFastBoundaryTick(); PluginTick(); UpdatePracticeStatsHud(forceLog: false); } catch (Exception ex) { string text = "RuntimeFrameTick EXCEPTION source=" + lastRuntimeDriverSource + " " + ex.GetType().Name + ":" + ex.Message; Plugin.Log.LogWarning((object)("[RuntimeTick] " + text)); } } internal static void PluginTick() { if (!PracticeActive) { return; } ResolvePendingSpecialSpawnGroupsIfNeeded(); ProcessPendingGiantKiwiHomeRestores(); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { TryRescueInvinciblePlayerFromAbyss(val); } MaintainLocalPlayerInvincibleFastIfEnabled(); ProcessPendingLocalPlayerRescue(); ProcessPendingBushWolfPostRescueResets(); ProcessPendingMaskedKillResets(); ApplyCriticalVisualHealthGate(); MaintainPracticePlayerFacilityFlags(); MaintainShipTerminalInteraction(); SuppressEnemyAwarenessIfPlayerOutsideRedArea(); if (!(Time.realtimeSinceStartup < nextRuntimeTickTime)) { nextRuntimeTickTime = Time.realtimeSinceStartup + 0.25f; if (Time.realtimeSinceStartup < localPlayerPostHealCleanupUntilTime) { CleanupLocalPlayerAfterFullHeal(); } KeepEnemiesInsideEnemyArea(); MaintainSpecialEnemyPracticeBehaviour(); MaintainPendingBaboonHawkGrouping(); MaintainPracticeInitialLooseItemCleanup(); KeepLocalPlayerAliveButNotAlwaysHealed(); MaintainLocalPlayerInvincibleIfEnabled(); if (Time.realtimeSinceStartup >= nextNoonTimeForceTime) { nextNoonTimeForceTime = Time.realtimeSinceStartup + 1f; ForcePracticeTimeNoon(); } if (Time.realtimeSinceStartup >= nextEnemyRescanTime) { nextEnemyRescanTime = Time.realtimeSinceStartup + 5f; RefreshEnemyTracking(force: false); RefreshEnemyBoundaryWallCollisionIgnores("periodic refresh"); } if (lateWorldCleanupPending && Time.realtimeSinceStartup >= lateWorldCleanupDueTime) { lateWorldCleanupPending = false; DisableExistingMapVisualsAndColliders(); DisableVanillaPracticeVisualRoots(includeGeneratedDungeon: true, "delayed post-generation cleanup"); nextTerminalInteractionRepairTime = 0f; MaintainShipTerminalInteraction(); Plugin.Log.LogInfo((object)"[WorldCleanup] Completed one delayed post-generation cleanup pass including generated-root deactivation."); } if (!ArenaCreated && Time.realtimeSinceStartup >= arenaCreationAllowedTime) { TryCreatePracticeArenaSafely("PluginTick delayed creation", ignoreDelay: false, clearOldArena: true); } if (Time.realtimeSinceStartup >= nextSlowTickTime) { nextSlowTickTime = Time.realtimeSinceStartup + 0.75f; RescueLocalPlayerIfNeeded(); } } } internal static bool HandleUnityDebugLog(object message) { if (!PracticeActive || message == null) { return true; } string text = message.ToString() ?? ""; if (!string.Equals(text.Trim(), "Path to exit could not be calculated", StringComparison.Ordinal)) { return true; } return false; } internal static string Normalize(string text) { if (string.IsNullOrWhiteSpace(text)) { return ""; } string input = text.ToLowerInvariant(); return Regex.Replace(input, "[^a-z0-9]", ""); } internal static bool ShouldForcePlayerTargetable(EnemyAI enemy, PlayerControllerB player) { //IL_005a: 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) //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) //IL_0071: 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 (!PracticeActive || (Object)(object)player == (Object)null) { return false; } if (player.isPlayerDead) { return false; } if (ShouldHidePlayerFromPracticeEnemy(enemy, player)) { return false; } if (!ArenaCreated) { return true; } Vector3 position = ((Component)player).transform.position; float num = Vector3.Distance(new Vector3(position.x, 0f, position.z), new Vector3(PracticeAreaCenter.x, 0f, PracticeAreaCenter.z)); return num <= 140f; } internal static bool ShouldHidePlayerFromPracticeEnemy(EnemyAI enemy, PlayerControllerB player) { //IL_0047: 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) if (!PracticeActive || !ArenaCreated || !HidePlayersOutsideEnemyAreaFromEnemies || (Object)(object)enemy == (Object)null || (Object)(object)player == (Object)null) { return false; } if (player.isPlayerDead) { return false; } if (!IsPointInsideEnemyArea(((Component)enemy).transform.position, 1f)) { return false; } return !IsPointInsideEnemyArea(((Component)player).transform.position, 0.15f); } private static bool IsPointInsideEnemyArea(Vector3 position, float margin) { //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) //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_0021: 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_002d: 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) if (!ArenaCreated) { return false; } Vector3 val = position - EnemyAreaCenter; float num = Vector3.Dot(val, EnemyAreaRight); float num2 = Vector3.Dot(val, EnemyAreaForward); float num3 = EnemyAreaHalfSize + margin; return num >= 0f - num3 && num <= num3 && num2 >= 0f - num3 && num2 <= num3; } private static bool IsPointInsidePracticePlatform(Vector3 position, float margin) { //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) //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_0021: 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_002d: 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_005b: Unknown result type (might be due to invalid IL or missing references) if (!ArenaCreated) { return false; } Vector3 val = position - PracticeAreaCenter; float num = Vector3.Dot(val, EnemyAreaRight); float num2 = Vector3.Dot(val, EnemyAreaForward); float num3 = PracticeAreaHalfSize + margin; bool flag = num >= 0f - num3 && num <= num3 && num2 >= 0f - num3 && num2 <= num3; bool flag2 = Mathf.Abs(position.y - GetEnemyFloorY()) <= 5f; return flag && flag2; } private static void MaintainPracticePlayerFacilityFlags() { //IL_0072: Unknown result type (might be due to invalid IL or missing references) float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < nextPlayerFacilityFlagTime) { return; } nextPlayerFacilityFlagTime = realtimeSinceStartup + 0.25f; if (!PracticeActive || !ArenaCreated) { return; } try { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && IsPointInsideEnemyArea(((Component)val).transform.position, 1.5f)) { SetBoolFieldIfExists(val, "isInsideFactory", value: true); SetBoolFieldIfExists(val, "isInHangarShipRoom", value: false); SetBoolFieldIfExists(val, "isInsidePlayerShip", value: false); } } catch { } } private static void AddShipTerminalHierarchyToProtectionCache(GameObject root) { if ((Object)(object)root == (Object)null) { return; } try { Transform[] componentsInChildren = root.GetComponentsInChildren<Transform>(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { ShipTerminalProtectedObjectIds.Add(((Object)((Component)val).gameObject).GetInstanceID()); } } } catch { } } private static void RefreshShipTerminalProtectionCache() { //IL_0049: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) ShipTerminalProtectedObjectIds.Clear(); try { Terminal[] array = Resources.FindObjectsOfTypeAll<Terminal>(); foreach (Terminal val in array) { if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } Scene scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).IsValid()) { continue; } scene = ((Component)val).gameObject.scene; if (!((Scene)(ref scene)).isLoaded) { continue; } AddShipTerminalHierarchyToProtectionCache(((Component)val).gameObject); object fieldOrPropertyValue = GetFieldOrPropertyValue(val, "terminalTrigger"); Component val2 = (Component)((fieldOrPropertyValue is Component) ? fieldOrPropertyValue : null); if (val2 != null && (Object)(object)val2.gameObject != (Object)null) { AddShipTerminalHierarchyToProtectionCache(val2.gameObject); continue; } GameObject val3 = (GameObject)((fieldOrPropertyValue is GameObject) ? fieldOrPropertyValue : null); if (val3 != null) { AddShipTerminalHierarchyToProtectionCache(val3); } } } catch { } } private static void MaintainShipTerminalInteraction() { if (!PracticeActive) { return; } float realtimeSinceStartup = Time.realtimeSinceStartup; if (realtimeSinceStartup < nextTerminalInteractionRepairTime) { return; } nextTerminalInteractionRepairTime = realtimeSinceStartup + 0.5f; try { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && val.inTerminalMenu) { return; } Terminal val2 = ((IEnumerable<Terminal>)Resources.FindObjectsOfTypeAll<Terminal>()).FirstOrDefault((Func<Terminal, bool>)delegate(Terminal candidate) { //IL_001d: 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: 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) int result; if ((Object)(object)candidate != (Object)null && (Object)(object)((Component)candidate).gameObject != (Object)null) { Scene scene = ((Component)candidate).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { scene = ((Component)candidate).gameObject.scene; result = (((Scene)(ref scene)).isLoaded ? 1 : 0); goto IL_0042; } } result = 0; goto IL_0042; IL_0042: return (byte)result != 0; }); if ((Object)(object)val2 == (Object)null) { return; } if (ShipTerminalProtectedObjectIds.Count == 0) { RefreshShipTerminalProtectionCache(); } if (!((Component)val2).gameObject.activeSelf) { ((Component)val2).gameObject.SetActive(true); } if (!((Behaviour)val2).enabled) { ((Behaviour)val2).enabled = true; } object fieldOrPropertyValue = GetFieldOrPropertyValue(val2, "terminalTrigger"); Component val3 = (Component)((fieldOrPropertyValue is Component) ? fieldOrPropertyValue : null); GameObject val4 = (GameObject)(((Object)(object)val3 != (Object)null) ? val3.gameObject : ((fieldOrPropertyValue is GameObject) ? fieldOrPropertyValue : null)); if ((Object)(object)val4 == (Object)null) { return; } if (!val4.activeSelf) { val4.SetActive(true); } Behaviour val5 = (Behaviour)(object)((val3 is Behaviour) ? val3 : null); if (val5 != null && !val5.enabled) { val5.enabled = true; } SetFieldOrPropertyValue(fieldOrPropertyValue, "interactable", true); Collider[] componentsInChildren = val4.GetComponentsInChildren<Collider>(true); foreach (Collider val6 in componentsInChildren) { if ((Object)(object)val6 != (Object)null && !val6.enabled) { val6.enabled = true; } } } catch { } } internal static void PluginUpdateDiagnosticHeartbeat(string source) { } private static void LogArenaDiagnosticState(string context) { bool flag = true; } private static bool ShouldLogGlobalDiagnostic(ref float nextTime, float intervalSeconds) { bool flag = true; return false; } private static bool ShouldLogEnemyDiagnostic(int instanceId, float intervalSeconds) { bool flag = true; return false; } private static string FormatVector3(Vector3 value) { //IL_0006: 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_001c: Unknown result type (might be due to invalid IL or missing references) return $"({value.x:F2},{value.y:F2},{value.z:F2})"; } internal static void QueuePracticeRoute() { PracticeQueued = true; SelectableLevel val = FindFallbackLevel(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogError((object)"Could not find a fallback moon for practice."); return; } try { Terminal val2 = Object.FindObjectOfType<Terminal>(); int num = (((Object)(object)val2 != (Object)null) ? val2.groupCredits : 0); StartOfRound.Instance.ChangeLevelServerRpc(val.levelID, num); Plugin.Log.LogInfo((object)$"Practice route queued. Fallback level id: {val.levelID}, planet: {val.PlanetName}"); } catch (Exception arg) { Plugin.Log.LogError((object)$"Failed to route to practice fallback level: {arg}"); } } private static SelectableLevel? FindFallbackLevel() { if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.levels == null || StartOfRound.Instance.levels.Length == 0) { return null; } SelectableLevel val = ((IEnumerable<SelectableLevel>)StartOfRound.Instance.levels).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel level) => (Object)(object)level != (Object)null && Normalize(level.PlanetName).Contains("experimentation"))); return val ?? ((IEnumerable<SelectableLevel>)StartOfRound.Instance.levels).FirstOrDefault((Func<SelectableLevel, bool>)((SelectableLevel level) => (Object)(object)level != (Object)null)); } internal static void ApplyPracticeLevelSettings(SelectableLevel newLevel) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) if (PracticeQueued) { PracticeQueued = false; PracticeActive = true; Plugin.Log.LogInfo((object)$"[Session] PracticeActive=TRUE levelId={newLevel.levelID} planet={newLevel.PlanetName}"); ArenaCreated = false; SpawnedEnemies.Clear(); PracticeSpawnedUtilityObjects.Clear(); ClearPracticeSpecialSessionState(destroyStructural: false, "ApplyPracticeLevelSettings begin"); PracticeStatsOverlayEnabled = true; practiceStatsLastRenderedText = ""; PracticeHitboxOverlayEnabled = false; statsOverlayFirstDrawLogged = false; nextStatsOverlayDiagTime = 0f; nextHitboxRuntimeDiagTime = 0f; hitboxRefreshDirty = false; hitboxDirtyReason = "session-reset"; nextHitboxTransformUpdateTime = 0f; nextHitboxPlayerRosterCheckTime = 0f; lastHitboxRemotePlayerCount = -1; nextSpecialLootVisualUpdateTime = 0f; nextFastBoundaryTickTime = 0f; nextPlayerFacilityFlagTime = 0f; nextAwarenessFastTickTime = 0f; nextStatsHudDiagTime = 0f; nextStatsHudUpdateTime = 0f; practiceStatsFixedPositionCaptured = false; practiceStatsFixedAnchoredPosition = new Vector2(210f, -70f); statsHudCreatedLogged = false; lastRuntimeFrameTick = -1; nextRuntimeDriverDiagTime = 0f; lastRuntimeDriverSource = "session-start"; lastCriticalGateObservedHealth = -1; lastCriticalGateObservedCritical = false; criticalVisualClearAppliedForHealthyState = false; ClearPracticeStatsHud("ApplyPracticeLevelSettings begin"); PracticeGiantKiwiNestTargets.Clear(); PracticeGiantKiwiNestOverrideLoggedIds.Clear(); PracticeGiantKiwiNestOriginalPositions.Clear(); PracticeGiantKiwiNestMoveDeltas.Clear(); PracticeGiantKiwiNestRelocatedIds.Clear(); PracticeGiantKiwiEggRelocatedIds.Clear(); PracticeGiantKiwiHomePositions.Clear(); PracticeGiantKiwiHomeRestoreDueTimes.Clear(); PracticeGiantKiwiHomeRestoreLoggedIds.Clear(); PracticeGiantKiwiKillStackLoggedIds.Clear(); PracticeManualMoldGenerationInProgress = false; nextInvAbyssRescueAllowedTime = 0f; EnemyBarrierPushCooldown.Clear(); JesterPracticePoppedIds.Clear(); JesterPracticeNoResetArmedIds.Clear(); JesterPracticePreCrankIds.Clear(); JesterInitializationSeenIds.Clear(); JesterCrankStartedIds.Clear(); JesterSequenceNextDiagTimes.Clear(); JesterMethodInventoryLoggedIds.Clear(); MouthDogDirectLungeNextTimes.Clear(); DogDeepDiagNextTimes.Clear(); DogMethodInventoryLoggedIds.Clear(); ForcedAdultManeaterIds.Clear(); ManeaterRecoveryUntilTimes.Clear(); ManeaterDeepDiagNextTimes.Clear(); ManeaterMethodInventoryLoggedIds.Clear(); ManeaterDeferredResetIds.Clear(); ManeaterResetInProgressIds.Clear(); ManeaterDeferredResetReasons.Clear(); OldBirdDiagNextTimes.Clear(); OldBirdMethodInventoryLoggedIds.Clear(); OldBirdWakeAttemptedIds.Clear(); OldBirdThreatEventNextLogTimes.Clear(); GiantKiwiThreatEventNextLogTimes.Clear(); OldBirdThreatSnapshotNextTimes.Clear(); OldBirdThreatCapabilityByEnemyId.Clear(); OldBirdNonPlayerThreatSeenSince.Clear(); OldBirdEntityAlertAssistCooldownUntil.Clear(); OldBirdEntityAttackSeenSince.Clear(); OldBirdEntityAttackAssistCooldownUntil.Clear(); OldBirdDeepDiagNextTimes.Clear(); BushWolfPostRescueResetDueTimes.Clear(); BushWolfPostRescueResetAttempts.Clear(); BushWolfOriginalBaseOffsets.Clear(); BushWolfGrowlCounts.Clear(); BushWolfGrowlLastTimes.Clear(); BrackenMemberInventoryLoggedIds.Clear(); BrackenLastBehaviourStateById.Clear(); BrackenLastStateLogTimeById.Clear(); baboonGroupRefreshPending = false; baboonGroupRefreshAt = 0f; baboonGroupLastSignature = ""; PracticeBaboonCampObject = null; practiceAmbientEffectsDisabled = false; PracticeManuallySpawnedItemIds.Clear(); PendingFoxGrassObjects.Clear(); PendingFoxGrassCenter = Vector3.zero; ambientSourceInventoryLogged = false; initialLooseItemCleanupDone = false; initialLooseItemCleanupAt = 0f; ForestGiantDiagNextTimes.Clear(); ForestGiantMethodInventoryLoggedIds.Clear(); EnemyPostSpawnIdentityLoggedIds.Clear(); DogKeywordMethodInventoryLoggedIds.Clear(); OldBirdKeywordMethodInventoryLoggedIds.Clear(); ForestGiantKeywordMethodInventoryLoggedIds.Clear(); ForestGiantZeroAnimatorMotionFrames.Clear(); ForestGiantAnimatorFixNextLogTimes.Clear(); TulipBoundaryGuardNextTimes.Clear(); pendingLocalPlayerRescueScheduled = false; pendingLocalPlayerRescueTime = 0f; pendingLocalPlayerRescueReason = ""; nextAwarenessSuppressionTime = 0f; nextRuntimeTickTime = 0f; nextSlowTickTime = 0f; nextEnemyRescanTime = 0f; nextArenaAttemptTime = 0f; arenaCreationAllowedTime = Time.realtimeSinceStartup + 5f; lateWorldCleanupDueTime = 0f; lateWorldCleanupPending = false; nextNoonTimeForceTime = 0f; localPlayerPostHealCleanupUntilTime = 0f; nextInvincibleDetailedDiagTime = 0f; lastInvincibleObservedDeadState = false; invincibleFieldInventoryLogged = false; nextCriticalVisualHealthGateTime = 0f; roundManagerRefreshAttempted = false; itemCacheDirty = true; nextPluginUpdateDiagnosticTime = 0f; nextArenaDiagnosticLogTime = 0f; nextNavMeshDiagnosticLogTime = 0f; nextEnemySummaryDiagnosticTime = 0f; EnemyDiagnosticNextLogTimes.Clear(); floorPostProcessingArenaAttempted = false; Plugin.Log.LogInfo((object)"Applying practice moon settings."); LogArenaDiagnosticState("ApplyPracticeLevelSettings initialized"); Plugin.Log.LogInfo((object)"Practice arena creation requested. Existing terrain/map visuals/colliders will be disabled."); Plugin.Log.LogInfo((object)"Use the default in-game chat (Enter or /) for practice quick commands such as mas3 / sho2 / shot / heal / god."); Plugin.Log.LogInfo((object)"Practice commands are available directly in chat or the ship Terminal while Practice is active."); newLevel.PlanetName = "practice"; ForceWeatherNone(newLevel); DisablePracticeWeatherAndAmbientEffects("ApplyPracticeLevelSettings"); if (newLevel.Enemies != null) { newLevel.Enemies.Clear(); } if (newLevel.OutsideEnemies != null) { newLevel.OutsideEnemies.Clear(); } if (newLevel.DaytimeEnemies != null) { newLevel.DaytimeEnemies.Clear(); } SetIntFieldIfExists(newLevel, "maxEnemyPowerCount", 0); SetIntFieldIfExists(newLevel, "maxOutsideEnemyPowerCount", 0); SetIntFieldIfExists(newLevel, "maxDaytimeEnemyPowerCount", 0); try { newLevel.minScrap = 0; newLevel.maxScrap = 0; } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to set scrap settings: " + ex.Message)); } ForcePracticeTimeNoon(); Plugin.Log.LogInfo((object)"Practice moon settings applied. Planet name: practice. Weather: None. Natural enemies disabled. Natural scrap spawn is blocked by SpawnScrapInLevel prefix."); } } private static void ForceWeatherNone(SelectableLevel level) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = typeof(SelectableLevel).GetField("currentWeather", bindingAttr); if (field != null && field.FieldType.IsEnum) { object value = Enum.Parse(field.FieldType, "None", ignoreCase: true); field.SetValue(level, value); Plugin.Log.LogInfo((object)"Practice weather forced to None by field."); return; } PropertyInfo property = typeof(SelectableLevel).GetProperty("currentWeather", bindingAttr); if (property != null && property.CanWrite && property.PropertyType.IsEnum) { object value2 = Enum.Parse(property.PropertyType, "None", ignoreCase: true); property.SetValue(level, value2); Plugin.Log.LogInfo((object)"Practice weather forced to None by property."); } else { Plugin.Log.LogWarning((object)"Could not find SelectableLevel.currentWeather field/property."); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to force weather to None: " + ex.Message)); } } private static void DisablePracticeWeatherAndAmbientEffects(string context) { if (!PracticeActive) { return; } int num = 0; int num2 = 0; bool flag = false; try { if ((Object)(object)TimeOfDay.Instance != (Object)null) { MethodInfo methodInfo = ((object)TimeOfDay.Instance).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((MethodInfo m) => string.Equals(m.Name, "DisableAllWeather", StringComparison.Ordinal)); if (methodInfo != null) { ParameterInfo[] parameters = methodInfo.GetParameters(); object[] parameters2 = ((parameters.Length != 1 || !(parameters[0].ParameterType == typeof(bool))) ? Array.Empty<object>() : new object[1] { true }); methodInfo.Invoke(TimeOfDay.Instance, parameters2); flag = true; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[AmbientDiag] DisableAllWeather failed. context=" + context + " error=" + ex.GetType().Name + ": " + ex.Message)); } try { ParticleSystem[] array = Object.FindObjectsOfType<ParticleSystem>(true); foreach (ParticleSystem val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val).gameObject)) { try { val.Stop(true, (ParticleSystemStopBehavior)0); num++; } catch { } } } Type type = AccessTools.TypeByName("UnityEngine.VFX.VisualEffect"); if (type != null) { Object[] array2 = Object.FindObjectsOfType(type, true); foreach (Object val2 in array2) { Component val3 = (Component)(object)((val2 is Component) ? val2 : null); if ((Object)(object)val3 == (Object)null || (Object)(object)val3.gameObject == (Object)null || !ShouldDisableWorldObject(val3.gameObject)) { continue; } try { InvokeMethodIfExists(val3, "Stop"); Behaviour val4 = (Behaviour)(object)((val3 is Behaviour) ? val3 : null); if (val4 != null) { val4.enabled = false; } num2++; } catch { } } } } catch (Exception ex2) { Plugin.Log.LogWarning((object)("[AmbientDiag] ambient effect cleanup failed. context=" + context + " error=" + ex2.GetType().Name + ": " + ex2.Message)); } int num5 = DisablePracticeLocalVolumetricFogObjects(); if (!practiceAmbientEffectsDisabled || num > 0 || num2 > 0 || num5 > 0) { Plugin.Log.LogInfo((object)$"[AmbientDiag] context={context} DisableAllWeather={flag} stoppedParticles={num} disabledVisualEffects={num2} disabledLocalVolumetricFog={num5}"); } practiceAmbientEffectsDisabled = true; } private static int DisablePracticeLocalVolumetricFogObjects() { int num = 0; try { GameObject[] array = Object.FindObjectsOfType<GameObject>(true); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || !ShouldDisableWorldObject(val)) { continue; } string text = GetHierarchyPath(val).ToLowerInvariant(); if (text.Contains("fogexclusion")) { continue; } Component[] components = val.GetComponents<Component>(); foreach (Component val2 in components) { if ((Object)(object)val2 == (Object)null || !string.Equals(((object)val2).GetType().Name, "LocalVolumetricFog", StringComparison.Ordinal)) { continue; } try { bool flag = false; Behaviour val3 = (Behaviour)(object)((val2 is Behaviour) ? val2 : null); if (val3 != null && val3.enabled) { val3.enabled = false; flag = true; } if (flag) { num++; Plugin.Log.LogInfo((object)("[AmbientDiag][FOG-OFF] path=" + GetHierarchyPath(val) + " type=" + ((object)val2).GetType().FullName)); } } catch { } } if ((text.Contains("/duststorm") || text.EndsWith("duststorm") || text.Contains("localrollingfog")) && val.activeSelf) { try { val.SetActive(false); } catch { } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[AmbientDiag][FOG-OFF] failed: " + ex.GetType().Name + ": " + ex.Message)); } return num; } private static int DisableDustCloudObjects() { int num = 0; try { Type type = AccessTools.TypeByName("DustClouds"); if (type == null) { return 0; } Object[] array = Object.FindObjectsOfType(type, true); foreach (Object val in array) { Component val2 = (Component)(object)((val is Component) ? val : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.gameObject == (Object)null || !ShouldDisableWorldObject(val2.gameObject)) { continue; } try { Behaviour val3 = (Behaviour)(object)((val2 is Behaviour) ? val2 : null); if (val3 != null) { val3.enabled = false; } val2.gameObject.SetActive(false); num++; } catch { } } } catch { } return num; } private static void LogAmbientSourceInventoryOnce(string context) { if (ambientSourceInventoryLogged) { return; } ambientSourceInventoryLogged = true; try { List<string> list = new List<string>(); GameObject[] array = Object.FindObjectsOfType<GameObject>(true); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || !ShouldDisableWorldObject(val)) { continue; } string text = Normalize(((Object)val).name); if (text.Contains("wind") || text.Contains("dust") || text.Contains("cloud") || text.Contains("fog") || text.Contains("weather")) { string arg = string.Join(",", (from c in val.GetComponents<Component>() where (Object)(object)c != (Object)null select ((object)c).GetType().Name).Distinct().Take(16)); list.Add($"{GetHierarchyPath(val)} [{arg}] active={val.activeInHierarchy}"); if (list.Count >= 80) { break; } } } Plugin.Log.LogInfo((object)("[AmbientSourceDiag] context=" + context + " candidates=" + ((list.Count == 0) ? "<none>" : string.Join(" || ", list)))); } catch (Exception ex) { Plugin.Log.LogWarning((object)("[AmbientSourceDiag] inventory failed: " + ex.GetType().Name + ": " + ex.Message)); } } private static void ForcePracticeTimeNoon() { try { if (!((Object)(object)TimeOfDay.Instance == (Object)null)) { object instance = TimeOfDay.Instance; float floatFieldOrDefault = GetFloatFieldOrDefault(instance, "totalTime", 1080f); float num = floatFieldOrDefault * 0.25f; SetFloatFieldIfExists(instance, "globalTime", num); SetFloatFieldIfExists(instance, "currentDayTime", num); SetFloatFieldIfExists(instance, "normalizedTimeOfDay", 0.25f); SetFloatFieldIfExists(instance, "timeUntilDeadline", floatFieldOrDefault - num); SetFloatFieldIfExists(instance, "globalTimeAtStartOfDay", num); SetBoolFieldIfExists(instance, "currentDayTimeStarted", value: false); ForcePracticeSunNoonVisual(); } } catch { } } private static void ForcePracticeSunNoonVisual() { if (!PracticeActive || (Object)(object)TimeOfDay.Instance == (Object)null) { return; } try { object? fieldOrPropertyValue = GetFieldOrPropertyValue(TimeOfDay.Instance, "sunAnimator"); Animator val = (Animator)((fieldOrPropertyValue is Animator) ? fieldOrPropertyValue : null); if ((Object)(object)val != (Object)null && ((Behaviour)val).isActiveAndEnabled) { val.SetFloat("timeOfDay", 1f / 3f); } } catch { } } private static float GetFloatFieldOrDefault(object target, string fieldName, float fallback) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = target.GetType().GetField(fieldName, bindingAttr); if (field != null && field.FieldType == typeof(float)) { return (float)field.GetValue(target); } } catch { } return fallback; } private static void SetFloatFieldIfExists(object target, string fieldName, float value) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = target.GetType().GetField(fieldName, bindingAttr); if (field != null && field.FieldType == typeof(float)) { field.SetValue(target, value); } } catch { } } private static void SetIntFieldIfExists(object target, string fieldName, int value) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = target.GetType().GetField(fieldName, bindingAttr); if (field != null && field.FieldType == typeof(int)) { field.SetValue(target, value); Plugin.Log.LogInfo((object)$"Set {fieldName} to {value}."); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("Failed to set " + fieldName + ": " + ex.Message)); } } private static void SetBoolFieldIfExists(object target, string fieldName, bool value) { try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = target.GetType().GetField(fieldName, bindingAttr); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(target, value); } } catch { } } private static void SetVector3FieldIfExists(object target, string fieldName, Vector3 value) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) try { BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; FieldInfo field = target.GetType().GetField(fieldName, bindingAttr); if (field != null && field.FieldType == typeof(Vector3)) { field.SetValue(target, value); } } catch { } } private static void DisableExistingMapVisualsAndColliders() { RefreshShipTerminalProtectionCache(); int num = 0; int num2 = 0; int num3 = 0; Terrain[] array = Object.FindObjectsOfType<Terrain>(true); foreach (Terrain val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val).gameObject) && ((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; DisabledTerrains.Add(val); num3++; } } Renderer[] array2 = Object.FindObjectsOfType<Renderer>(true); foreach (Renderer val2 in array2) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)((Component)val2).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val2).gameObject)) { SetRendererForceRenderingOffBestEffort(val2, value: true); if (val2.enabled) { val2.enabled = false; DisabledMapRenderers.Add(val2); num++; } } } Collider[] array3 = Object.FindObjectsOfType<Collider>(true); foreach (Collider val3 in array3) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)((Component)val3).gameObject == (Object)null) && ShouldDisableWorldObject(((Component)val3).gameObject) && val3.enabled) { val3.enabled = false; DisabledMapColliders.Add(val3); num2++; } } int num4 = 0; try { LODGroup[] array4 = Object.FindObjectsOfType<LODGroup>(true); bool flag = default(bool); foreach (LODGroup val4 in array4) { if ((Object)(object)val4 == (Object)null || (Object)(object)((Component)val4).gameObject == (Object)null || !ShouldDisableWorldObject(((Component)val4).gameObject)) { continue; } PropertyInfo property = ((object)val4).GetType().GetProperty("enabled", BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite) { object value = property.GetValue(val4, null); int num5; if (value is bool) { flag = (bool)value; num5 = ((1 == 0) ? 1 : 0); } else { num5 = 1; } if (((uint)num5 | (flag ? 1u : 0u)) != 0) { property.SetValue(val4, false, null); num4++; } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[WorldCleanup] LODGroup disable pass failed: " + ex.GetType().Name + ": " + ex.Message)); } DisableVanillaPracticeVisualRoots(includeGeneratedDungeon: false, "world cleanup"); DisablePracticeWeatherAndAmbientEffects("world cleanup"); nextTerminalInteractionRepairTime = 0f; MaintainShipTerminalInteraction(); int num6 = num + num2 + num3 + num4; if (num6 > 0) { Plugin.Log.LogInfo((object)$"Disabled existing terrain/map visuals/colliders. Terrains: {num3}, Renderers: {num}, Colliders: {num2}, LODGroups: {num4}"); } } private static void SetRendererForceRenderingOffBestEffort(Renderer renderer, bool value) { if ((Object)(object)renderer == (Object)null) { return; } try { PropertyInfo property = typeof(Renderer).GetProperty("forceRenderingOff", BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanWrite) { property.SetValue(renderer, value, null); } } catch { } } private static void DisableVanillaPracticeVisualRoots(bool includeGeneratedDungeon, string context) { //IL_0035: 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) //IL_0046: 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) int num = 0; try { GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>(); foreach (GameObject val in array) { if ((Object)(object)val == (Object)null || IsPracticeObject(val)) { continue; } Scene scene = val.scene; if (!((Scene)(ref scene)).IsValid()) { continue; } scene = val.scene; if (((Scene)(ref scene)).isLoaded) { string text = GetHierarchyPath(val).Replace('\\', '/').ToLowerInvariant(); bool flag = text == "environment/map/modelsintroscene" || text.EndsWith("/environment/map/modelsintroscene"); bool flag2 = includeGeneratedDungeon && (text == "systems/levelgeneration/levelgenerationroot" || text.EndsWith("/systems/levelgeneration/levelgenerationroot")); if ((flag || flag2) && val.activeSelf) { val.SetActive(false); num++; Plugin.Log.LogInfo((object)("[WorldCleanup][ROOT-OFF] context=" + context + " path=" + GetHierarchyPath(val))); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("[WorldCleanup][ROOT-OFF-ERROR] context=" + context + " " + ex.GetType().Name + ": " + ex.Message)); } if (num > 0) { Plugin.Log.LogInfo((object)$"[WorldCleanup][ROOT-OFF] context={context} disabledRoots={num}"); } } private static bool ShouldDisableWorldObject(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } if (IsPracticeObject(obj)) { return false; } if (ShipTerminalProtectedObjectIds.Contains(((Object)obj).GetInstanceID())) { return false; } string text = GetHierarchyPath(obj).ToLowerInvariant(); string text2 = Normalize(((Object)obj).name ?? ""); if (text.Contains("hangarship")) { return false; } if (text.Contains("player")) { return false; } if (text.Contains("terminalscript")) { return false; } if (text.Contains("startofround") || text.Contains("roundmanager") || text.Contains("networkmanager")) { return false; } if (text.Contains("hudmanager") || text.Contains("systems/ui") || text.Contains("mapcamera")) { return false; } if (text.StartsWith("environment/") && !text.Contains("hangarship")) { return true; } if (text.Contains("environment/map")) { return true; } if (text.Contains("systems/levelgeneration/levelgenerationroot")) { return true; } if (text.Contains("levelgenerationroot")) { return true; } if (text2.Contains("terrain") || text2.Contains("ground") || text2.Contains("floor") || text2.Contains("landscape") || text2.Contains("mapterrain") || text2.Contains("moonterrain") || text2.Contains("outsideground") || text2.Contains("outsidefloor")) { return true; } if ((text2.Contains("ladder") || text2.Contains("rock") || text2.Contains("boulder") || text2.Contains("stone") || text2.Contains("hatch") || text2.Contains("entrance") || text2.Contains("fireexit") || text2.Contains("door") || text2.Contains("fence") || text2.Contains("pipe") || text2.Contains("beam") || text2.Contains("cliff")) && (text.Contains("environment") || text.Contains("map") || text.Contains("level") || text.Contains("outside"))) { return true; } return false; } private static string GetHierarchyPath(GameObject obj) { if ((Object)(object)obj == (Object)null) { return ""; } List<string> list = new List<string>(); Transform val = obj.transform; while ((Object)(object)val != (Object)null) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } private static bool IsPracticeObject(GameObject obj) { if ((Object)(object)obj == (Object)null) { return false; } string text = ((Object)obj).name ?? ""; return text.StartsWith("Practice", StringComparison.OrdinalIgnoreCase); } internal static string? HandleShipTerminalPracticeCommand(string rawInput) { if (!PracticeActive) { return null; } string text = rawInput.Trim(); if (string.IsNullOrWhiteSpace(text)) { return null; } string[] array = text.Split(new char[1] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries); string text2 = ((array.Length != 0) ? Normalize(array[0]) : ""); bool flag = text2 == "p" || text2 == "ps" || text2 == "practice"; string commandText = ((!flag) ? text : ((array.Length >= 2) ? array[1].Trim() : "help")); return HandlePracticeCommandBody(commandText, !flag); } private static string? HandlePracticeCommandBody(string commandText, bool returnNullIfUnknown = false) { if (string.IsNullOrWhiteSpace(commandText)) { commandText = "help"; } string[] array = commandText.Split(new char[1] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries); string text = Normalize(array[0]); string text2 = ((array.Length >= 2) ? array[1].Trim() : ""); switch (text) { case "help": case "h": return GetPracticeTerminalHelpText(); case "jp": case "ja": case "japanese": case "en": case "eng": case "english": return "Language switching has been removed. Use help."; case "regen": case "regenerate": case "arena": RegenerateArenaFromCommand(); return "Practice arena regenerated. The Practice NavMesh inside the red enemy area was also rebuilt."; case "flip": case "front": case "direction": FlipArenaDirectionFromCommand(); return "Practice arena direction flipped and regenerated. If the arena is behind the ship, use flip once more."; case "data": case "dat": if (Normalize(text2) == "entity" || Normalize(text2) == "entities" || Normalize(text2) == "enemy" || Normalize(text2) == "enemies") { return GetEntityDataText(); } if (Normalize(text2) == "item" || Normalize(text2) == "items" || Normalize(text2) == "store" || Normalize(text2) == "stores") { return GetStoreItemDataText(); } if (Normalize(text2) == "scrap" || Normalize(text2) == "scraps") { return GetScrapDataText(); } return GetPracticeDataIndexText(); case "datae": case "entitydata": case "enemydata": return GetEntityDataText(); case "datai": case "itemdata": case "storedata": case "storeitems": return GetStoreItemDataText(); case "datas": case "scrapdata": case "scrapsdata": return GetScrapDataText(); case "dumpenemies": case "dumpenemy": return DumpEnemyTypesToLog(); case "dumpitems": case "dumpitem": return DumpItemsToLog(); case "entity": case "enemy": case "ent": return SpawnEnemyCommand(text2); case "delete": case "del": case "clear": if (Normalize(text2) == "item" || Normalize(text2) == "items") { return DeleteDroppedItemsCommand(); } return DeleteEnemyCommand(string.IsNullOrWhiteSpace(text2) ? "all" : text2); case "deli": case "delitem": case "deleteitem": case "clearitem": case "clearitems": return DeleteDroppedItemsCommand(); case "store": case "sto": case "item": case "scrap": return SpawnPracticeItemCommand(text2); case "reset": case "recall": case "back": return ResetAllEnemiesToRespawnPoint(); case "heal": case "recover": return FullHealLocalPlayerCommand(); case "hp": case "health": if (!string.IsNullOrWhiteSpace(text2)) { return SetLocalPlayerHealthCommand(text2); } return FullHealLocalPlayerCommand(); case "sethp": case "sethealth": case "lowhp": return SetLocalPlayerHealthCommand(text2); case "dmg": case "damage": case "hurt": return DamageLocalPlayerCommand(text2); case "stats": case "stat": return TogglePracticeStatsOverlayCommand(); case "hb": case "hit": case "hitbox": case "hitboxes": return TogglePracticeHitboxOverlayCommand(); case "cmdtest": case "commandtest": return CommandSelfTestCommand(); case "aidiag": case "enemyai": case "enemydiag": return GetEnemyAiDiagnosticCommand(); case "god": case "godmode": case "inv": case "invincible": case "immortal": return ToggleLocalPlayerInvincibleCommand(); case "fixhands": case "freehands": return FixHandsCommand(); case "handstate": case "hands": return GetHandStateCommand(); case "invstate": case "godstate": return GetInvStateCommand(); case "cage": return SetEnemyOnlyCageCommand(text2); case "leash": return SetEnemyLeashCommand(text2); case "rescue": case "autorescue": return SetAutoRescueCommand(text2); case "crit": case "critical": case "critinjury": return SetCriticalInjuryCommand(text2); case "critfix": case "clearcrit": case "criticalfix": return ForceCriticalVisualClearCommand(); case "critfx": case "critvisual": case "criticalvisual": return SetCriticalVisualHealthGateCommand(text2); case "manstate": case "manediag": return GetManeaterStateCommand(); case "maninspect": case "manins": case "manmethods": case "manfields": return GetManeaterInspectCommand((text == "manmethods") ? "methods" : ((text == "manfields") ? "fields" : text2)); case "manreset": case "manfix": return ResetManeaterStateCommand(); case "manfresh": return SetManeaterHardRefreshCommand(text2); case "manadult": case "adultman": case "manvisualadult": return SetManeaterForceAdultCommand(text2); case "manadultrespawn": case "manadultrefresh": case "adultrespawn": return SetManeaterAdultRespawnCommand(text2); case "jesfix": case "jesterfix": case "jesaggro": case "jesteraggro": return SetJesterPracticeAggroCommand(text2); case "jesreset": case "jesternoreset": return SetJesterPracticeNoResetCommand(text2); case "tulphys": case "tulipphys": return SetTulipPhysicsDiagnosticCommand(text2); case "tulguard": case "tulipguard": return SetTulipBoundaryGuardCommand(text2); case "hideout": case "stealthout": case "outsidehide": return SetHideOutsidePlayersCommand(text2); case "diag": return GetAllDiagnosticStatus(); case "language": case "lang": case "lan": return "Language switching has been removed. Use help."; default: { string text3 = HandleCompactPracticeCommand(commandText, returnNullIfUnknown: true); if (text3 != null) { return text3; } if (returnNullIfUnknown) { return null; } return "Unknown Practice command: " + commandText + "\n\n" + GetPracticeTerminalHelpText(); } } } internal static string? HandleCompactPracticeCommand(string rawInput, bool returnNullIfUnknown, bool allowDataCommands = true) { if (!PracticeActive) { return returnNullIfUnknown ? null : "Practice mode is not active."; } string text = rawInput.Trim(); if (string.IsNullOrWhiteSpace(text)) { return returnNullIfUnknown ? null : "Empty command."; } string text2 = Normalize(text); string[] array = text.Split(new char[1] { ' ' }, 2, StringSplitOptions.RemoveEmptyEntries); string text3 = ((array.Length != 0) ? Normalize(array[0]) : ""); string text4 = ((array.Length >= 2) ? array[1].Trim() : ""); if (!string.IsNullOrWhiteSpace(text4)) { switch (text3) { case "hp": case "health": case "sethp": case "sethealth": case "lowhp": return SetLocalPlayerHealthCommand(text4); case "dmg": case "damage": case "hurt": return DamageLocalPlayerCommand(text4); case "entity": case "enemy": case "ent": return SpawnEnemyCommand(text4); case "store": case "sto": case "item": case "scrap": return SpawnPracticeItemCommand(text4); case "delete": case "del": case "clear": return DeleteEnemyCommand(text4); case "cage": case "leash": case "rescue": case "autorescue": case "crit": case "critical": case "critinjury": case "critfx": case "critvisual": case "criticalvisual": case "maninspect": case "manins": case "manmethods": case "manfields": case "manfresh": case "manadult": case "adultman": case "manvisualadult": case "manadultrespawn": case "manadultrefresh": case "adultrespawn": case "jesfix": case "jesterfix": case "jesaggro": case "jesteraggro": case "tulphys": case "tulipphys": case "tulguard": case "tulipguard": case "hideout": case "stealthout": case "outsidehide": return HandlePracticeCommandBody(text); } } if (text3 == "aidig" || text3 == "aisig") { return GetEnemyAiDiagnosticCommand(); } if (allowDataCommands) { if (text2 == "help" || text2 == "h") { return GetPracticeTerminalHelpText(); } if (text2 == "data" || text2 == "dat") { return GetPracticeDataIndexText(); } if (text2 == "datae" || text2 == "entitydata" || text2 == "enemydata") { return GetEntityDataText(); } switch (text2) { default: if (!(text2 == "stores")) { break; } goto case "datai"; case "datai": case "itemdata": case "items": case "store": return GetStoreItemDataText(); } switch (text2) { default: if (!(text2 == "scraps")) { break; } goto case "datas"; case "datas": case "scrapdata": case "scrap": return GetScrapDataText(); } if (text2 == "dumpenemies" || text2 == "dumpenemy") { return DumpEnemyTypesToLog(); } if (text2 == "dumpitems" || text2 == "dumpitem") { return DumpItemsToLog(); } } if (text2 == "regen" || text2 == "regenerate" || text2 == "arena") { RegenerateArenaFromCommand(); return "Practice arena regenerated."; } if (text2 == "flip" || text2 == "front" || text2 == "direction") { FlipArenaDirectionFromCommand(); return "Practice arena direction flipped and regenerated."; } switch (text2) { default: if (!(text2 == "delall")) { switch (text2) { default: if (!(text2 == "clearitems")) { if (text2 == "reset" || text2 == "recall" || text2 == "back") { return ResetAllEnemiesToRespawnPoint(); } if (text2 == "heal" || text2 == "recover") { return FullHealLocalPlayerCommand(); } if (text2 == "hp" || text2 == "health") { return FullHealLocalPlayerCommand(); } if (!text2.StartsWith("sethp ", StringComparison.Ordinal) && !text2.StartsWith("sethealth ", StringComparison.Ordinal) && !text2.StartsWith("lowhp ", StringComparison.Ordinal) && !text2.StartsWith("hp ", StringComparison.Ordinal) && !text2.StartsWith("health ", StringComparison.Ordinal)) { if (text2.StartsWith("dmg ", StringComparison.Ordinal) || text2.StartsWith("damage ", StringComparison.Ordinal) || text2.StartsWith("hurt ", StringComparison.Ordinal)) { string argument = (text2.StartsWith("damage ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 7)).Trim() : text.Substring(Math.Min(text.Length, text2.StartsWith("hurt ", StringComparison.Ordinal) ? 5 : 4)).Trim()); return DamageLocalPlayerCommand(argument); } if (text2 == "stats" || text2 == "stat") { return TogglePracticeStatsOverlayCommand(); } switch (text2) { default: if (!(text2 == "hitboxes")) { if (text2 == "cmdtest" || text2 == "commandtest") { return CommandSelfTestCommand(); } if (text2 == "aidiag" || text2 == "enemyai" || text2 == "enemydiag") { return GetEnemyAiDiagnosticCommand(); } switch (text2) { default: if (!(text2 == "immortal")) { if (text2 == "fixhands" || text2 == "freehands") { return FixHandsCommand(); } if (text2 == "handstate" || text2 == "hands") { return GetHandStateCommand(); } if (text2 == "invstate" || text2 == "godstate") { return GetInvStateCommand(); } if (text2 == "manstate" || text2 == "manediag") { return GetManeaterStateCommand(); } switch (text2) { default: if (!(text2 == "manfields")) { if (text2 == "manfresh" || text2.StartsWith("manfresh ", StringComparison.Ordinal)) { string maneaterHardRefreshCommand = ((text2 == "manfresh") ? "" : text.Substring(Math.Min(text.Length, 8)).Trim()); return SetManeaterHardRefreshCommand(maneaterHardRefreshCommand); } if (text2 == "manadult" || text2.StartsWith("manadult ", StringComparison.Ordinal) || text2 == "adultman" || text2.StartsWith("adultman ", StringComparison.Ordinal) || text2 == "manvisualadult" || text2.StartsWith("manvisualadult ", StringComparison.Ordinal)) { int num = (text2.StartsWith("manvisualadult", StringComparison.Ordinal) ? 14 : (text2.StartsWith("adultman", StringComparison.Ordinal) ? 8 : 8)); string maneaterForceAdultCommand = ((text.Length > num) ? text.Substring(num).Trim() : ""); return SetManeaterForceAdultCommand(maneaterForceAdultCommand); } if (text2 == "manadultrespawn" || text2.StartsWith("manadultrespawn ", StringComparison.Ordinal) || text2 == "manadultrefresh" || text2.StartsWith("manadultrefresh ", StringComparison.Ordinal) || text2 == "adultrespawn" || text2.StartsWith("adultrespawn ", StringComparison.Ordinal)) { int num2 = (text2.StartsWith("manadultrefresh", StringComparison.Ordinal) ? 15 : (text2.StartsWith("adultrespawn", StringComparison.Ordinal) ? 12 : 15)); string maneaterAdultRespawnCommand = ((text.Length > num2) ? text.Substring(num2).Trim() : ""); return SetManeaterAdultRespawnCommand(maneaterAdultRespawnCommand); } if (text2 == "crit" || text2.StartsWith("crit ", StringComparison.Ordinal) || text2 == "critical" || text2.StartsWith("critical ", StringComparison.Ordinal) || text2 == "critinjury" || text2.StartsWith("critinjury ", StringComparison.Ordinal)) { int num3 = (text2.StartsWith("critinjury", StringComparison.Ordinal) ? 10 : (text2.StartsWith("critical", StringComparison.Ordinal) ? 8 : 4)); string criticalInjuryCommand = ((text.Length > num3) ? text.Substring(num3).Trim() : ""); return SetCriticalInjuryCommand(criticalInjuryCommand); } if (text2 == "critfix" || text2 == "clearcrit" || text2 == "criticalfix") { return ForceCriticalVisualClearCommand(); } if (text2 == "jesfix" || text2.StartsWith("jesfix ", StringComparison.Ordinal) || text2 == "jesterfix" || text2.StartsWith("jesterfix ", StringComparison.Ordinal) || text2 == "jesaggro" || text2.StartsWith("jesaggro ", StringComparison.Ordinal) || text2 == "jesteraggro" || text2.StartsWith("jesteraggro ", StringComparison.Ordinal)) { int num4 = (text2.StartsWith("jesteraggro", StringComparison.Ordinal) ? 11 : (text2.StartsWith("jesterfix", StringComparison.Ordinal) ? 9 : (text2.StartsWith("jesaggro", StringComparison.Ordinal) ? 8 : 6))); string jesterPracticeAggroCommand = ((text.Length > num4) ? text.Substring(num4).Trim() : ""); return SetJesterPracticeAggroCommand(jesterPracticeAggroCommand); } if (text2 == "jesreset" || text2.StartsWith("jesreset ", StringComparison.Ordinal) || text2 == "jesternoreset" || text2.StartsWith("jesternoreset ", StringComparison.Ordinal)) { int num5 = (text2.StartsWith("jesternoreset", StringComparison.Ordinal) ? 14 : 8); string jesterPracticeNoResetCommand = ((text.Length > num5) ? text.Substring(num5).Trim() : ""); return SetJesterPracticeNoResetCommand(jesterPracticeNoResetCommand); } if (text2 == "critfx" || text2.StartsWith("critfx ", StringComparison.Ordinal) || text2 == "critvisual" || text2.StartsWith("critvisual ", StringComparison.Ordinal) || text2 == "criticalvisual" || text2.StartsWith("criticalvisual ", StringComparison.Ordinal)) { int num6 = (text2.StartsWith("criticalvisual", StringComparison.Ordinal) ? 14 : (text2.StartsWith("critvisual", StringComparison.Ordinal) ? 10 : 6)); string criticalVisualHealthGateCommand = ((text.Length > num6) ? text.Substring(num6).Trim() : ""); return SetCriticalVisualHealthGateCommand(criticalVisualHealthGateCommand); } if (text2.StartsWith("maninspect", StringComparison.Ordinal) || text2.StartsWith("manins", StringComparison.Ordinal)) { string argument2 = (text2.StartsWith("maninspect", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : text.Substring(Math.Min(text.Length, 6)).Trim()); return GetManeaterInspectCommand(argument2); } if (text2 == "diag") { return GetAllDiagnosticStatus(); } if (text2.StartsWith("cage", StringComparison.Ordinal)) { string enemyOnlyCageCommand = ((text.Length > 4) ? text.Substring(4).Trim() : ""); return SetEnemyOnlyCageCommand(enemyOnlyCageCommand); } if (text2.StartsWith("leash", StringComparison.Ordinal)) { string enemyLeashCommand = ((text.Length > 5) ? text.Substring(5).Trim() : ""); return SetEnemyLeashCommand(enemyLeashCommand); } if (text2.StartsWith("rescue", StringComparison.Ordinal) || text2.StartsWith("autorescue", StringComparison.Ordinal)) { string autoRescueCommand = (text2.StartsWith("autorescue", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : text.Substring(Math.Min(text.Length, 6)).Trim()); return SetAutoRescueCommand(autoRescueCommand); } if (text2.StartsWith("tulphys", StringComparison.Ordinal) || text2.StartsWith("tulipphys", StringComparison.Ordinal)) { string tulipPhysicsDiagnosticCommand = (text2.StartsWith("tulipphys", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 8)).Trim() : text.Substring(Math.Min(text.Length, 7)).Trim()); return SetTulipPhysicsDiagnosticCommand(tulipPhysicsDiagnosticCommand); } if (text2.StartsWith("tulguard", StringComparison.Ordinal) || text2.StartsWith("tulipguard", StringComparison.Ordinal)) { string tulipBoundaryGuardCommand = (text2.StartsWith("tulipguard", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : text.Substring(Math.Min(text.Length, 8)).Trim()); return SetTulipBoundaryGuardCommand(tulipBoundaryGuardCommand); } if (text2 == "diaglog" || text2 == "diagpath") { return "Diagnostic log: " + PracticeDiagnosticFile.LogPath; } if (text2.StartsWith("hideout", StringComparison.Ordinal) || text2.StartsWith("stealthout", StringComparison.Ordinal) || text2.StartsWith("outsidehide", StringComparison.Ordinal)) { string hideOutsidePlayersCommand = (text2.StartsWith("outsidehide", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 11)).Trim() : text.Substring(Math.Min(text.Length, text2.StartsWith("stealthout", StringComparison.Ordinal) ? 9 : 7)).Trim()); return SetHideOutsidePlayersCommand(hideOutsidePlayersCommand); } if (array.Length == 1 && (text2 == "jes2" || text2 == "jester2")) { return "jes2 has been removed. Use jes."; } ParsedCommand parsedCommand = ParseCompactNameAndCount(text); if (string.IsNullOrWhiteSpace(parsedCommand.Name)) { return returnNullIfUnknown ? null : ("Unknown command: " + rawInput); } TryResolveEnemyTypes(); EnemyDefinition enemyDefinition = FindEnemyDefinition(parsedCommand.Name); if (enemyDefinition != null) { return SpawnEnemyCommand($"{enemyDefinition.PrimaryAlias} {parsedCommand.Count}"); } string text5 = SpawnPracticeItemCommand($"{parsedCommand.Name} {parsedCommand.Count}"); if (!text5.StartsWith("Unknown item", StringComparison.OrdinalIgnoreCase)) { return text5; } return returnNullIfUnknown ? null : ("Unknown command: " + rawInput); } goto case "maninspect"; case "maninspect": case "manins": case "manmethods": { string argument3 = ((text2 == "manmethods") ? "methods" : ((text2 == "manfields") ? "fields" : "")); return GetManeaterInspectCommand(argument3); } } } goto case "god"; case "god": case "godmode": case "inv": case "invincible": return ToggleLocalPlayerInvincibleCommand(); } } goto case "hb"; case "hb": case "hit": case "hitbox": return TogglePracticeHitboxOverlayCommand(); } } string localPlayerHealthCommand = (text2.StartsWith("sethealth ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 10)).Trim() : (text2.StartsWith("sethp ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 6)).Trim() : (text2.StartsWith("lowhp ", StringComparison.Ordinal) ? text.Substring(Math.Min(text.Length, 6)).Trim() : ((!text2.StartsWith("health ", StringComparison.Ordinal)) ? text.Substring(Math.Min(text.Length, 3)).Trim() : text.Substring(Math.Min(text.Length, 7)).Trim())))); return SetLocalPlayerHealthCommand(localPlayerHealthCommand); } goto case "deli"; case "deli": case "deleteitem": case "deleteitems": case "delitem": case "clearitem": return DeleteDroppedItemsCommand(); } } goto case "delete"; case "delete": case "del": case "clear": case "deleteall": return DeleteAllEnemiesAndCorpses(); } } private static string GetPracticeTerminalHelpText() { return "PRACTICE SANDBOX COMMANDS\n\nDuring Practice, enter commands either in the normal in-game chat (/ to open it) or in the ship Terminal.\nThe same commands work in both places without a p prefix.\n\nENEMIES\nmas = spawn 1 masked\nmas3 = spawn 3 masked\nthu = spawn 1 thumper\ndog = spawn 1 eyeless dog\nold = spawn 1 Old Bird\njes = spawn Jester and progress normal box -> crank -> pop -> chase\ndata = show data categories\ndatae = show entity spawn commands / aliases, including special and internal entities\n\nITEMS\nsho = spawn 1 shovel\nshot = spawn 1 shotgun\ngbar = spawn 1 gold bar\ndatai = show store / purchasable item aliases\ndatas = show scrap + special / system item aliases\n\nPLAYER\nheal = fully heal and clear Critical Injury effects\nsethp 10 / hp 10 = set HP to 10\ndmg 40 / hurt 40 = subtract 40 HP\nstats = toggle HP/ST/HB/INV display (default ON)\nhb / hit = toggle hitbox visualization (default OFF)\ngod = toggle invincible mode\n\nREMOVE / RESET\ndeli = dele