Decompiled source of WanderingPlanetIII v1.1.10
DSPWanderingPlanets.dll
Decompiled a day ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using CommonAPI; using CommonAPI.Systems; using CommonAPI.Systems.ModLocalization; using HarmonyLib; using UnityEngine; using crecheng.DSPModSave; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("DSPWanderingPlanets")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.10.0")] [assembly: AssemblyInformationalVersion("1.1.10")] [assembly: AssemblyProduct("DSPWanderingPlanets")] [assembly: AssemblyTitle("DSPWanderingPlanets")] [assembly: AssemblyVersion("1.1.10.0")] namespace DSPWanderingPlanets; internal sealed class DeterministicRandom { private uint state; internal uint State { get { return state; } set { state = ((value == 0) ? 1831565813u : value); } } internal DeterministicRandom(uint seed) { state = ((seed == 0) ? 1831565813u : seed); } private DeterministicRandom(uint state, bool clone) { this.state = state; } internal DeterministicRandom Clone() { return new DeterministicRandom(state, clone: true); } internal uint NextUInt() { uint num = state; num ^= num << 13; num ^= num >> 17; return state = num ^ (num << 5); } internal double NextDouble() { return (double)NextUInt() / 4294967296.0; } internal int NextInt(int exclusiveMaximum) { if (exclusiveMaximum <= 0) { throw new ArgumentOutOfRangeException("exclusiveMaximum"); } return (int)(NextUInt() % (uint)exclusiveMaximum); } internal int NextInt(int minimum, int exclusiveMaximum) { if (exclusiveMaximum <= minimum) { throw new ArgumentOutOfRangeException("exclusiveMaximum"); } return minimum + NextInt(exclusiveMaximum - minimum); } } internal static class GenerationMarker { private const int MarkerBase = 20590000; private const int MaximumEncodedSystems = 99; private const int MaximumStarCount = 128; internal static bool TryGetSystemCount(GameDesc gameDesc, out int count) { count = ((gameDesc != null) ? (gameDesc.galaxyAlgo - 20590000) : 0); if (count > 0) { return count <= 99; } return false; } internal static int MarkNewGame(GameDesc gameDesc) { if (gameDesc == null) { return 0; } if (TryGetSystemCount(gameDesc, out var count)) { return count; } int systemCount = ModConfig.GetSystemCount(gameDesc.galaxySeed); int val = Math.Max(0, 128 - gameDesc.starCount); int num = Math.Min(systemCount, val); if (num <= 0) { return 0; } gameDesc.starCount += num; gameDesc.galaxyAlgo = 20590000 + num; return num; } } [HarmonyPatch] internal static class GalaxyGenerationPatches { internal static void ValidateTargets() { MethodInfo methodInfo = AccessTools.Method(typeof(GameData), "NewGame", new Type[1] { typeof(GameDesc) }, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(UniverseGen), "CreateGalaxy", new Type[1] { typeof(GameDesc) }, (Type[])null); if (methodInfo == null || methodInfo.ReturnType != typeof(bool)) { throw new MissingMethodException("GameData.NewGame(GameDesc) has changed."); } if (methodInfo2 == null || methodInfo2.ReturnType != typeof(GalaxyData)) { throw new MissingMethodException("UniverseGen.CreateGalaxy(GameDesc) has changed."); } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyPatch(typeof(GameData), "NewGame")] private static void GameData_NewGame_Prefix(GameDesc _gameDesc) { int num = GenerationMarker.MarkNewGame(_gameDesc); if (num > 0) { Plugin.Log.LogInfo((object)("Reserved " + num + " wandering-system star IDs for the new universe.")); } } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyAfter(new string[] { "Zincon.DSPAddPlanetMoon2Patch", "Zincon.CustomCreateBirthStarLite" })] [HarmonyPatch(typeof(UniverseGen), "CreateGalaxy")] private static void UniverseGen_CreateGalaxy_Postfix(GameDesc gameDesc, GalaxyData __result) { if (__result != null && GenerationMarker.TryGetSystemCount(gameDesc, out var count)) { int num = Math.Min(count, Math.Max(0, __result.starCount - 1)); if (num > 0) { WanderingSystemFactory.TransformGalaxy(__result, gameDesc, num); } } } } internal static class ModConfig { private const int MaximumSupportedSystems = 32; internal static ConfigEntry<double> SpeedMetersPerSecond { get; private set; } internal static ConfigEntry<int> MinimumSystemCount { get; private set; } internal static ConfigEntry<int> MaximumSystemCount { get; private set; } internal static ConfigEntry<bool> StartInWanderingSystem { get; private set; } internal static ConfigEntry<float> UnipolarMagnetChance { get; private set; } internal static ConfigEntry<double> MinimumWormholeHours { get; private set; } internal static ConfigEntry<double> MaximumWormholeHours { get; private set; } internal static double LegacyReplaySpeedMetersPerSecond { get; private set; } internal static void Initialize(ConfigFile config) { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Expected O, but got Unknown //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Expected O, but got Unknown //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Expected O, but got Unknown //IL_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Expected O, but got Unknown //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01fd: Expected O, but got Unknown SpeedMetersPerSecond = config.Bind<double>("Movement", "SpeedMetersPerSecond", 600.0, new ConfigDescription("Wandering-system travel speed in DSP universe metres per second.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(1.0, 1000000.0), Array.Empty<object>())); double value = SpeedMetersPerSecond.Value; LegacyReplaySpeedMetersPerSecond = config.Bind<double>("Migration", "LegacyReplaySpeedMetersPerSecond", value, new ConfigDescription("Recorded 1.0.x speed used only to preserve old-save positions during migration.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(1.0, 1000000.0), Array.Empty<object>())).Value; if (Math.Abs(SpeedMetersPerSecond.Value - 1200.0) < 0.001) { SpeedMetersPerSecond.Value = 600.0; config.Save(); } MinimumWormholeHours = config.Bind<double>("Movement", "MinimumWormholeHours", 2.0, new ConfigDescription("Minimum in-game hours between random wormholes for each wandering system.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.05, 1000.0), Array.Empty<object>())); MaximumWormholeHours = config.Bind<double>("Movement", "MaximumWormholeHours", 6.0, new ConfigDescription("Maximum in-game hours between random wormholes for each wandering system.", (AcceptableValueBase)(object)new AcceptableValueRange<double>(0.05, 1000.0), Array.Empty<object>())); MinimumSystemCount = config.Bind<int>("Generation", "MinimumSystemCount", 3, new ConfigDescription("Minimum wandering systems in a new save. This is stored in the save's galaxy marker.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 32), Array.Empty<object>())); MaximumSystemCount = config.Bind<int>("Generation", "MaximumSystemCount", 8, new ConfigDescription("Maximum wandering systems in a new save. This is stored in the save's galaxy marker.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(0, 32), Array.Empty<object>())); StartInWanderingSystem = config.Bind<bool>("Generation", "StartInWanderingSystem", true, "Start new saves on the main planet of a wandering system. Disable to preserve the vanilla birth system."); UnipolarMagnetChance = config.Bind<float>("Resources", "UnipolarMagnetChance", 0.25f, new ConfigDescription("Chance for each solid body in a wandering system to receive one unipolar-magnet cluster.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>())); } internal static int GetSystemCount(int galaxySeed) { int num = MinimumSystemCount.Value; int num2 = MaximumSystemCount.Value; if (num > num2) { int num3 = num; num = num2; num2 = num3; } if (num == num2) { return num; } DeterministicRandom deterministicRandom = new DeterministicRandom((uint)(galaxySeed ^ 0x57414E44)); return num + deterministicRandom.NextInt(num2 - num + 1); } internal static void GetWormholeIntervalSeconds(out double minimum, out double maximum) { minimum = MinimumWormholeHours.Value * 3600.0; maximum = MaximumWormholeHours.Value * 3600.0; if (minimum > maximum) { double num = minimum; minimum = maximum; maximum = num; } } } internal static class MotionController { private sealed class RuntimeGalaxy { internal GalaxyData Galaxy { get; } internal int[] SystemIndexes { get; } internal bool[] IsSystemIndex { get; } internal Point3d[] Targets { get; } internal MotionTrack[] Tracks { get; } internal Point3d[] NextFrameOffsets { get; } internal Dictionary<int, int> TrackByStarIndex { get; } internal double Speed { get; set; } internal RuntimeGalaxy(GalaxyData galaxy, int[] systemIndexes, bool[] isSystemIndex, Point3d[] targets, MotionTrack[] tracks, double speed) { Galaxy = galaxy; SystemIndexes = systemIndexes; IsSystemIndex = isSystemIndex; Targets = targets; Tracks = tracks; NextFrameOffsets = new Point3d[tracks.Length]; Speed = speed; TrackByStarIndex = new Dictionary<int, int>(); for (int i = 0; i < systemIndexes.Length; i++) { TrackByStarIndex[systemIndexes[i]] = i; } } } private const int SaveVersion = 1; private const double SystemWarpLightYearsPerSecond = 0.25; private const double WarpSteeringRadiansPerSecond = Math.PI / 4.0; private static readonly object SyncRoot = new object(); private static readonly Dictionary<GalaxyData, RuntimeGalaxy> Galaxies = new Dictionary<GalaxyData, RuntimeGalaxy>(); private static readonly Dictionary<int, MotionTrackState> PendingStates = new Dictionary<int, MotionTrackState>(); private static StarData activePlayerWarpStar; private static MotionTrack activePlayerWarpTrack; internal static void Register(GalaxyData galaxy, int[] systemIndexes) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) if (galaxy == null || systemIndexes == null || systemIndexes.Length == 0) { return; } bool[] array = new bool[galaxy.starCount]; foreach (int num in systemIndexes) { if (num <= 0 || num >= galaxy.starCount) { throw new ArgumentOutOfRangeException("systemIndexes"); } array[num] = true; } Point3d[] array2 = new Point3d[galaxy.starCount - systemIndexes.Length]; int num2 = 0; for (int j = 0; j < galaxy.starCount; j++) { if (!array[j]) { array2[num2++] = ToPoint(galaxy.stars[j].uPosition); } } MotionTrack[] array3 = new MotionTrack[systemIndexes.Length]; double configuredSpeed = GetConfiguredSpeed(); double metersPerSecond = Math.Max(1.0, ModConfig.LegacyReplaySpeedMetersPerSecond); for (int k = 0; k < array3.Length; k++) { StarData val = galaxy.stars[systemIndexes[k]]; array3[k] = new MotionTrack(ToPoint(val.uPosition), (uint)(val.seed ^ galaxy.seed ^ 0x54524156)); array3[k].ResetLegacy(array2, metersPerSecond, 2400000.0); } RuntimeGalaxy runtimeGalaxy = new RuntimeGalaxy(galaxy, (int[])systemIndexes.Clone(), array, array2, array3, configuredSpeed); lock (SyncRoot) { Galaxies.Clear(); Galaxies.Add(galaxy, runtimeGalaxy); activePlayerWarpStar = null; activePlayerWarpTrack = null; ApplyPendingStates(runtimeGalaxy); } } internal static void BeforePoseUpdate(GalaxyData galaxy, double time) { //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) RuntimeGalaxy value; lock (SyncRoot) { if (!Galaxies.TryGetValue(galaxy, out value)) { return; } } double configuredSpeed = GetConfiguredSpeed(); if (Math.Abs(configuredSpeed - value.Speed) > 0.001) { value.Speed = configuredSpeed; for (int i = 0; i < value.Tracks.Length; i++) { value.Tracks[i].SetCruiseSpeed(configuredSpeed); } } ModConfig.GetWormholeIntervalSeconds(out var minimum, out var maximum); int num = ((GameMain.localStar == null) ? (-1) : GameMain.localStar.index); for (int j = 0; j < value.Tracks.Length; j++) { MotionTrack motionTrack = value.Tracks[j]; motionTrack.SetWormholeIntervalRange(minimum, maximum); if (motionTrack.IsWarping) { motionTrack.SetWarpSpeed(GetSystemWarpSpeed()); } bool holdWormhole = num == value.SystemIndexes[j]; motionTrack.AdvanceTo(Math.Max(0.0, time), value.Targets, holdWormhole); Point3d position = motionTrack.Position; Point3d point3d = motionTrack.Direction * (motionTrack.ActiveSpeed / 60.0); value.NextFrameOffsets[j] = point3d; StarData val = galaxy.stars[value.SystemIndexes[j]]; val.uPosition = ToVector(position); val.position = ToVector(position / 2400000.0); ref AstroData reference = ref galaxy.astrosData[val.astroId]; reference.id = val.astroId; reference.type = (EAstroType)1; reference.uPos = val.uPosition; reference.uPosNext = ToVector(position + point3d); if (galaxy.graphNodes != null && val.index >= 0 && val.index < galaxy.graphNodes.Length && galaxy.graphNodes[val.index] != null) { galaxy.graphNodes[val.index].pos = val.position; } } } internal static void AfterPoseUpdate(GalaxyData galaxy) { //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) RuntimeGalaxy value; lock (SyncRoot) { if (!Galaxies.TryGetValue(galaxy, out value)) { return; } } for (int i = 0; i < value.Tracks.Length; i++) { Point3d point3d = value.NextFrameOffsets[i]; StarData val = galaxy.stars[value.SystemIndexes[i]]; for (int j = 0; j < val.planetCount; j++) { PlanetData val2 = val.planets[j]; if (val2 != null) { val2.uPositionNext.x += point3d.X; val2.uPositionNext.y += point3d.Y; val2.uPositionNext.z += point3d.Z; galaxy.astrosData[val2.id].uPosNext = val2.uPositionNext; } } } } internal static bool TryToggleLocalSystemWarp(Player player) { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) if (player == null) { return false; } StarData localPlayerStar = GetLocalPlayerStar(player); if (localPlayerStar?.galaxy == null) { return false; } MotionTrack motionTrack; lock (SyncRoot) { if (!Galaxies.TryGetValue(localPlayerStar.galaxy, out var value) || !value.TrackByStarIndex.TryGetValue(localPlayerStar.index, out var value2)) { return false; } motionTrack = value.Tracks[value2]; } if (motionTrack.IsWarping) { motionTrack.StopWarp(); activePlayerWarpStar = null; activePlayerWarpTrack = null; Plugin.Log.LogInfo((object)"Planetary warp disengaged."); return true; } if (player.planetData?.star != localPlayerStar || (int)player.movementState != 0) { return false; } if (GameMain.history == null || !PrototypeRegistry.IsPlanetaryWarpTechUnlocked(GameMain.history) || player.mecha == null || !PrototypeRegistry.TryConsumePlanetaryWarper(player)) { return false; } double systemWarpSpeed = GetSystemWarpSpeed(); if (!motionTrack.StartWarp(systemWarpSpeed)) { return false; } activePlayerWarpStar = localPlayerStar; activePlayerWarpTrack = motionTrack; Plugin.Log.LogInfo((object)("Planetary warp engaged at 0.25 ly/s (" + systemWarpSpeed + " m/s).")); return true; } internal static bool TrySteerLocalSystemWarp(Player player, Point3d screenRight, Point3d screenUp, double horizontal, double vertical, double deltaTime) { if (player == null || deltaTime <= 0.0 || (Math.Abs(horizontal) < 0.001 && Math.Abs(vertical) < 0.001)) { return false; } StarData localPlayerStar = GetLocalPlayerStar(player); if (localPlayerStar?.galaxy == null) { return false; } lock (SyncRoot) { if (!Galaxies.TryGetValue(localPlayerStar.galaxy, out var value) || !value.TrackByStarIndex.TryGetValue(localPlayerStar.index, out var value2)) { return false; } return TrySteerTrack(value.Tracks[value2], screenRight, screenUp, horizontal, vertical, deltaTime); } } internal static bool TrySteerActivePlayerWarp(Point3d screenRight, Point3d screenUp, double horizontal, double vertical, double deltaTime) { if (deltaTime <= 0.0 || (Math.Abs(horizontal) < 0.001 && Math.Abs(vertical) < 0.001)) { return false; } lock (SyncRoot) { if (activePlayerWarpTrack == null || !activePlayerWarpTrack.IsWarping) { return false; } return TrySteerTrack(activePlayerWarpTrack, screenRight, screenUp, horizontal, vertical, deltaTime); } } internal static bool IsPlayerSystemWarping() { lock (SyncRoot) { return activePlayerWarpTrack != null && activePlayerWarpTrack.IsWarping; } } internal static bool TryGetActivePlayerWarpDirection(out Point3d direction) { direction = new Point3d(1.0, 0.0, 0.0); lock (SyncRoot) { if (activePlayerWarpTrack == null || !activePlayerWarpTrack.IsWarping) { return false; } direction = activePlayerWarpTrack.Direction; return direction.Magnitude > 1E-06; } } internal static void RefreshActivePlayerWarp(Player player) { if (player == null) { return; } lock (SyncRoot) { if (activePlayerWarpTrack == null || !activePlayerWarpTrack.IsWarping) { activePlayerWarpStar = null; activePlayerWarpTrack = null; StarData val = player.planetData?.star; if (val == null && player == GameMain.mainPlayer) { val = GameMain.localStar; } if (val?.galaxy != null && Galaxies.TryGetValue(val.galaxy, out var value) && value.TrackByStarIndex.TryGetValue(val.index, out var value2) && value.Tracks[value2].IsWarping) { activePlayerWarpStar = val; activePlayerWarpTrack = value.Tracks[value2]; } } } } internal static bool TryGetLocalWarp(Player player, out Point3d direction, out double speed) { direction = new Point3d(1.0, 0.0, 0.0); speed = 0.0; StarData localPlayerStar = GetLocalPlayerStar(player); if (localPlayerStar?.galaxy == null) { return false; } lock (SyncRoot) { if (!Galaxies.TryGetValue(localPlayerStar.galaxy, out var value) || !value.TrackByStarIndex.TryGetValue(localPlayerStar.index, out var value2)) { return false; } MotionTrack motionTrack = value.Tracks[value2]; if (!motionTrack.IsWarping) { return false; } direction = motionTrack.Direction; speed = motionTrack.ActiveSpeed; return true; } } internal static bool IsLocalSystemWarping(Player player) { StarData localPlayerStar = GetLocalPlayerStar(player); if (localPlayerStar?.galaxy == null) { return false; } lock (SyncRoot) { RuntimeGalaxy value; int value2; return Galaxies.TryGetValue(localPlayerStar.galaxy, out value) && value.TrackByStarIndex.TryGetValue(localPlayerStar.index, out value2) && value.Tracks[value2].IsWarping; } } internal static bool IsAnySystemWarping() { lock (SyncRoot) { foreach (RuntimeGalaxy value in Galaxies.Values) { for (int i = 0; i < value.Tracks.Length; i++) { if (value.Tracks[i].IsWarping) { return true; } } } return false; } } internal static bool IsWanderingPlanet(PlanetData planet) { return IsWanderingStar(planet?.star); } internal static bool IsWanderingStar(StarData star) { if (star?.galaxy == null) { return false; } lock (SyncRoot) { RuntimeGalaxy value; return Galaxies.TryGetValue(star.galaxy, out value) && star.index >= 0 && star.index < value.IsSystemIndex.Length && value.IsSystemIndex[star.index]; } } private static double GetSystemWarpSpeed() { return 600000.0; } private static bool TrySteerTrack(MotionTrack track, Point3d screenRight, Point3d screenUp, double horizontal, double vertical, double deltaTime) { double num = Math.Min(1.0, Math.Sqrt(horizontal * horizontal + vertical * vertical)); Point3d steeringDirection = screenRight * horizontal + screenUp * vertical; double radians = Math.PI / 4.0 * Math.Min(deltaTime, 0.1) * num; return track.SteerWarp(steeringDirection, radians); } private static StarData GetLocalPlayerStar(Player player) { if (player == GameMain.mainPlayer && activePlayerWarpStar != null) { if (activePlayerWarpTrack != null && activePlayerWarpTrack.IsWarping) { return activePlayerWarpStar; } activePlayerWarpStar = null; activePlayerWarpTrack = null; } StarData val = ((player == null) ? null : player.planetData?.star); if (val == null && player == GameMain.mainPlayer) { val = GameMain.localStar; } return val; } internal static void Export(BinaryWriter writer) { writer.Write(1); lock (SyncRoot) { RuntimeGalaxy currentRuntime = GetCurrentRuntime(); if (currentRuntime == null) { writer.Write(0); return; } writer.Write(currentRuntime.Tracks.Length); for (int i = 0; i < currentRuntime.Tracks.Length; i++) { writer.Write(currentRuntime.SystemIndexes[i]); WriteState(writer, currentRuntime.Tracks[i].CaptureState()); } } } internal static void Import(BinaryReader reader) { int num = reader.ReadInt32(); if (num != 1) { throw new InvalidDataException("Unsupported wandering-planet motion save version " + num + "."); } int num2 = reader.ReadInt32(); if (num2 < 0 || num2 > 99) { throw new InvalidDataException("Invalid wandering-system motion count."); } lock (SyncRoot) { PendingStates.Clear(); for (int i = 0; i < num2; i++) { int key = reader.ReadInt32(); PendingStates[key] = ReadState(reader); } RuntimeGalaxy currentRuntime = GetCurrentRuntime(); if (currentRuntime != null) { ApplyPendingStates(currentRuntime); } } } internal static void IntoOtherSave() { lock (SyncRoot) { PendingStates.Clear(); activePlayerWarpStar = null; activePlayerWarpTrack = null; RuntimeGalaxy currentRuntime = GetCurrentRuntime(); if (currentRuntime == null) { return; } double configuredSpeed = GetConfiguredSpeed(); double num = Math.Max(0.0, GameMain.gameTime); ModConfig.GetWormholeIntervalSeconds(out var minimum, out var maximum); for (int i = 0; i < currentRuntime.Tracks.Length; i++) { MotionTrack motionTrack = currentRuntime.Tracks[i]; if (num <= 0.001) { motionTrack.Reset(currentRuntime.Targets, configuredSpeed, 2400000.0, minimum, maximum); continue; } motionTrack.ResetLegacy(currentRuntime.Targets, Math.Max(1.0, ModConfig.LegacyReplaySpeedMetersPerSecond), 2400000.0); motionTrack.AdvanceTo(num, currentRuntime.Targets, holdWormhole: false); motionTrack.EnableWormholes(configuredSpeed, minimum, maximum); } currentRuntime.Speed = configuredSpeed; } } internal static void Clear() { lock (SyncRoot) { Galaxies.Clear(); PendingStates.Clear(); activePlayerWarpStar = null; activePlayerWarpTrack = null; } } private static RuntimeGalaxy GetCurrentRuntime() { GalaxyData galaxy = GameMain.galaxy; if (galaxy != null && Galaxies.TryGetValue(galaxy, out var value)) { return value; } using (Dictionary<GalaxyData, RuntimeGalaxy>.ValueCollection.Enumerator enumerator = Galaxies.Values.GetEnumerator()) { if (enumerator.MoveNext()) { return enumerator.Current; } } return null; } private static void ApplyPendingStates(RuntimeGalaxy runtime) { if (PendingStates.Count == 0) { return; } ModConfig.GetWormholeIntervalSeconds(out var minimum, out var maximum); double configuredSpeed = GetConfiguredSpeed(); for (int i = 0; i < runtime.Tracks.Length; i++) { if (PendingStates.TryGetValue(runtime.SystemIndexes[i], out var value)) { runtime.Tracks[i].RestoreState(value, runtime.Targets, 2400000.0, minimum, maximum); runtime.Tracks[i].SetCruiseSpeed(configuredSpeed); PendingStates.Remove(runtime.SystemIndexes[i]); } } runtime.Speed = configuredSpeed; } private static void WriteState(BinaryWriter writer, MotionTrackState state) { WritePoint(writer, state.Position); WritePoint(writer, state.Direction); writer.Write(state.TargetIndex); writer.Write(state.NextRandomRetargetTime); writer.Write(state.NextWormholeTime); writer.Write(state.CurrentTime); writer.Write(state.CruiseSpeed); writer.Write(state.IsWarping); writer.Write(state.WarpSpeed); writer.Write(state.RandomState); } private static MotionTrackState ReadState(BinaryReader reader) { return new MotionTrackState { Position = ReadPoint(reader), Direction = ReadPoint(reader), TargetIndex = reader.ReadInt32(), NextRandomRetargetTime = reader.ReadDouble(), NextWormholeTime = reader.ReadDouble(), CurrentTime = reader.ReadDouble(), CruiseSpeed = reader.ReadDouble(), IsWarping = reader.ReadBoolean(), WarpSpeed = reader.ReadDouble(), RandomState = reader.ReadUInt32() }; } private static void WritePoint(BinaryWriter writer, Point3d point) { writer.Write(point.X); writer.Write(point.Y); writer.Write(point.Z); } private static Point3d ReadPoint(BinaryReader reader) { return new Point3d(reader.ReadDouble(), reader.ReadDouble(), reader.ReadDouble()); } private static double GetConfiguredSpeed() { return Math.Max(1.0, ModConfig.SpeedMetersPerSecond.Value); } private static Point3d ToPoint(VectorLF3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) return new Point3d(value.x, value.y, value.z); } private static VectorLF3 ToVector(Point3d value) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) return new VectorLF3(value.X, value.Y, value.Z); } } [HarmonyPatch(typeof(GalaxyData), "UpdatePoses")] internal static class MotionPatches { internal static void ValidateTargets() { MethodInfo methodInfo = AccessTools.Method(typeof(GalaxyData), "UpdatePoses", new Type[1] { typeof(double) }, (Type[])null); if (methodInfo == null || methodInfo.ReturnType != typeof(void)) { throw new MissingMethodException("GalaxyData.UpdatePoses(double) has changed."); } } [HarmonyPrefix] [HarmonyPriority(800)] [HarmonyBefore(new string[] { "Zincon.DSPAddPlanetMoon2Patch" })] private static void Prefix(GalaxyData __instance, double time) { MotionController.BeforePoseUpdate(__instance, time); } [HarmonyPostfix] [HarmonyPriority(0)] private static void Postfix(GalaxyData __instance) { MotionController.AfterPoseUpdate(__instance); } } internal struct Point3d { internal double X; internal double Y; internal double Z; internal double SqrMagnitude => X * X + Y * Y + Z * Z; internal double Magnitude => Math.Sqrt(SqrMagnitude); internal Point3d Normalized { get { double magnitude = Magnitude; if (!(magnitude <= 1E-12)) { return this / magnitude; } return default(Point3d); } } internal Point3d(double x, double y, double z) { X = x; Y = y; Z = z; } internal static double Dot(Point3d left, Point3d right) { return left.X * right.X + left.Y * right.Y + left.Z * right.Z; } public static Point3d operator +(Point3d left, Point3d right) { return new Point3d(left.X + right.X, left.Y + right.Y, left.Z + right.Z); } public static Point3d operator -(Point3d left, Point3d right) { return new Point3d(left.X - right.X, left.Y - right.Y, left.Z - right.Z); } public static Point3d operator *(Point3d value, double scale) { return new Point3d(value.X * scale, value.Y * scale, value.Z * scale); } public static Point3d operator /(Point3d value, double scale) { return new Point3d(value.X / scale, value.Y / scale, value.Z / scale); } } internal sealed class MotionTrackState { internal Point3d Position; internal Point3d Direction; internal int TargetIndex; internal double NextRandomRetargetTime; internal double NextWormholeTime; internal double CurrentTime; internal double CruiseSpeed; internal bool IsWarping; internal double WarpSpeed; internal uint RandomState; } internal sealed class MotionTrack { internal const double MinimumRandomRetargetSeconds = 1800.0; private const double ForwardConeCosine = 0.5; private const double Epsilon = 1E-07; private const int WormholeDirectionSamples = 12; private readonly Point3d initialPosition; private readonly uint seed; private DeterministicRandom random; private double cruiseSpeed; private double warpSpeed; private double lightYear; private double currentTime; private double minimumWormholeSeconds; private double maximumWormholeSeconds; internal Point3d Position { get; private set; } internal Point3d Direction { get; private set; } internal int TargetIndex { get; private set; } internal double NextRandomRetargetTime { get; private set; } internal double NextWormholeTime { get; private set; } internal double CurrentTime => currentTime; internal bool IsWarping { get; private set; } internal double ActiveSpeed { get { if (!IsWarping) { return cruiseSpeed; } return warpSpeed; } } internal MotionTrack(Point3d initialPosition, uint seed) { this.initialPosition = initialPosition; this.seed = seed; Position = initialPosition; Direction = new Point3d(1.0, 0.0, 0.0); TargetIndex = -1; } internal void Reset(IReadOnlyList<Point3d> targets, double metersPerSecond, double lightYearInMeters) { Reset(targets, metersPerSecond, lightYearInMeters, 7200.0, 21600.0); } internal void Reset(IReadOnlyList<Point3d> targets, double metersPerSecond, double lightYearInMeters, double minimumWormholeIntervalSeconds, double maximumWormholeIntervalSeconds) { ResetLegacy(targets, metersPerSecond, lightYearInMeters); SetWormholeIntervalRange(minimumWormholeIntervalSeconds, maximumWormholeIntervalSeconds); ScheduleWormhole(); } internal void ResetLegacy(IReadOnlyList<Point3d> targets, double metersPerSecond, double lightYearInMeters) { ValidateParameters(targets, metersPerSecond, lightYearInMeters); cruiseSpeed = metersPerSecond; warpSpeed = 0.0; lightYear = lightYearInMeters; currentTime = 0.0; Position = initialPosition; Direction = new Point3d(1.0, 0.0, 0.0); TargetIndex = -1; IsWarping = false; random = new DeterministicRandom(seed); SelectTarget(targets, respectHeading: false, -1); ScheduleRandomRetarget(); NextWormholeTime = double.PositiveInfinity; } internal void EnableWormholes(double metersPerSecond, double minimumWormholeIntervalSeconds, double maximumWormholeIntervalSeconds) { SetCruiseSpeed(metersPerSecond); SetWormholeIntervalRange(minimumWormholeIntervalSeconds, maximumWormholeIntervalSeconds); ScheduleWormhole(); } internal void SetCruiseSpeed(double metersPerSecond) { if (metersPerSecond <= 0.0) { throw new ArgumentOutOfRangeException("metersPerSecond"); } cruiseSpeed = metersPerSecond; } internal void SetWormholeIntervalRange(double minimum, double maximum) { if (minimum <= 0.0 || maximum <= 0.0) { throw new ArgumentOutOfRangeException("minimum"); } minimumWormholeSeconds = Math.Min(minimum, maximum); maximumWormholeSeconds = Math.Max(minimum, maximum); } internal bool StartWarp(double metersPerSecond) { if (IsWarping || metersPerSecond <= 0.0) { return false; } warpSpeed = metersPerSecond; IsWarping = true; return true; } internal bool StopWarp() { if (!IsWarping) { return false; } IsWarping = false; warpSpeed = 0.0; return true; } internal bool SetWarpSpeed(double metersPerSecond) { if (!IsWarping || metersPerSecond <= 0.0) { return false; } warpSpeed = metersPerSecond; return true; } internal bool SteerWarp(Point3d steeringDirection, double radians) { if (!IsWarping || radians <= 1E-07) { return false; } Point3d point3d = steeringDirection - Direction * Point3d.Dot(steeringDirection, Direction); if (point3d.SqrMagnitude <= 1E-07) { return false; } double num = Math.Min(Math.PI / 2.0, radians); Direction = (Direction * Math.Cos(num) + point3d.Normalized * Math.Sin(num)).Normalized; return true; } internal void AdvanceTo(double time, IReadOnlyList<Point3d> targets) { AdvanceTo(time, targets, holdWormhole: false); } internal void AdvanceTo(double time, IReadOnlyList<Point3d> targets, bool holdWormhole) { if (time < currentTime - 1E-07) { double num = time - currentTime; NextRandomRetargetTime += num; if (!double.IsInfinity(NextWormholeTime)) { NextWormholeTime += num; } currentTime = Math.Max(0.0, time); return; } int num2 = 0; while (currentTime + 1E-07 < time) { if (++num2 > 100000) { throw new InvalidOperationException("Wandering motion exceeded its event safety limit."); } double num3 = time - currentTime; Point3d targetOffset = targets[TargetIndex] - Position; double activeSpeed = ActiveSpeed; double arrivalSeconds = GetArrivalSeconds(targetOffset, activeSpeed); if (IsWarping) { double seconds = Math.Min(arrivalSeconds, num3); Move(seconds, activeSpeed); FreezeTimers(seconds, freezeRandomRetarget: true, freezeWormhole: true); if (arrivalSeconds <= num3 + 1E-07) { IsWarping = false; warpSpeed = 0.0; SelectTarget(targets, respectHeading: true, -1); ScheduleRandomRetarget(); ScheduleWormhole(); } continue; } double val = Math.Max(0.0, NextRandomRetargetTime - currentTime); double num4 = (holdWormhole ? double.PositiveInfinity : Math.Max(0.0, NextWormholeTime - currentTime)); double num5 = Math.Min(arrivalSeconds, Math.Min(val, num4)); if (num5 > num3 || double.IsInfinity(num5)) { Move(num3, cruiseSpeed); if (holdWormhole) { FreezeTimers(num3, freezeRandomRetarget: false, freezeWormhole: true); } break; } Move(num5, cruiseSpeed); if (holdWormhole) { FreezeTimers(num5, freezeRandomRetarget: false, freezeWormhole: true); } if (num4 <= num5 + 1E-07) { ExecuteWormhole(targets); ScheduleRandomRetarget(); ScheduleWormhole(); } else { SelectTarget(targets, respectHeading: true, -1); ScheduleRandomRetarget(); } } } internal double GetMinimumIntervalSeconds() { return Math.Min(1800.0, 20.0 * lightYear / cruiseSpeed); } internal double GetMaximumIntervalSeconds() { return Math.Max(1800.0, 20.0 * lightYear / cruiseSpeed); } internal MotionTrackState CaptureState() { return new MotionTrackState { Position = Position, Direction = Direction, TargetIndex = TargetIndex, NextRandomRetargetTime = NextRandomRetargetTime, NextWormholeTime = NextWormholeTime, CurrentTime = currentTime, CruiseSpeed = cruiseSpeed, IsWarping = IsWarping, WarpSpeed = warpSpeed, RandomState = random.State }; } internal void RestoreState(MotionTrackState state, IReadOnlyList<Point3d> targets, double lightYearInMeters, double minimumWormholeIntervalSeconds, double maximumWormholeIntervalSeconds) { if (state == null || state.TargetIndex < 0 || state.TargetIndex >= targets.Count) { throw new ArgumentException("Invalid wandering motion state.", "state"); } ValidateParameters(targets, Math.Max(1.0, state.CruiseSpeed), lightYearInMeters); Position = state.Position; Direction = state.Direction.Normalized; if (Direction.SqrMagnitude <= 1E-07) { Direction = (targets[state.TargetIndex] - Position).Normalized; } TargetIndex = state.TargetIndex; NextRandomRetargetTime = state.NextRandomRetargetTime; NextWormholeTime = state.NextWormholeTime; currentTime = Math.Max(0.0, state.CurrentTime); cruiseSpeed = Math.Max(1.0, state.CruiseSpeed); IsWarping = state.IsWarping && state.WarpSpeed > 0.0; warpSpeed = (IsWarping ? state.WarpSpeed : 0.0); lightYear = lightYearInMeters; SetWormholeIntervalRange(minimumWormholeIntervalSeconds, maximumWormholeIntervalSeconds); random = new DeterministicRandom(state.RandomState); } private void Move(double seconds, double metersPerSecond) { if (!(seconds <= 1E-07)) { Position += Direction * (metersPerSecond * seconds); currentTime += seconds; } } private double GetArrivalSeconds(Point3d targetOffset, double metersPerSecond) { double sqrMagnitude = targetOffset.SqrMagnitude; double num = lightYear * lightYear; if (sqrMagnitude <= num) { return 0.0; } double num2 = Point3d.Dot(targetOffset, Direction); if (num2 <= 0.0) { return double.PositiveInfinity; } double num3 = Math.Max(0.0, sqrMagnitude - num2 * num2); if (num3 > num) { return double.PositiveInfinity; } double val = num2 - Math.Sqrt(Math.Max(0.0, num - num3)); return Math.Max(0.0, val) / metersPerSecond; } private void FreezeTimers(double seconds, bool freezeRandomRetarget, bool freezeWormhole) { if (!(seconds <= 1E-07)) { if (freezeRandomRetarget) { NextRandomRetargetTime += seconds; } if (freezeWormhole && !double.IsInfinity(NextWormholeTime)) { NextWormholeTime += seconds; } } } private void ExecuteWormhole(IReadOnlyList<Point3d> targets) { int num = random.NextInt(targets.Count); Point3d point3d = targets[num]; Point3d position = point3d + RandomUnitVector() * lightYear; double num2 = GetNearestOtherTargetDistanceSquared(position, targets, num); for (int i = 1; i < 12; i++) { Point3d point3d2 = point3d + RandomUnitVector() * lightYear; double nearestOtherTargetDistanceSquared = GetNearestOtherTargetDistanceSquared(point3d2, targets, num); if (nearestOtherTargetDistanceSquared > num2) { num2 = nearestOtherTargetDistanceSquared; position = point3d2; } } Position = position; SelectTarget(targets, respectHeading: false, num); } private Point3d RandomUnitVector() { double num = random.NextDouble() * 2.0 - 1.0; double num2 = random.NextDouble() * Math.PI * 2.0; double num3 = Math.Sqrt(Math.Max(0.0, 1.0 - num * num)); return new Point3d(num3 * Math.Cos(num2), num, num3 * Math.Sin(num2)); } private static double GetNearestOtherTargetDistanceSquared(Point3d position, IReadOnlyList<Point3d> targets, int excludedIndex) { double num = double.PositiveInfinity; for (int i = 0; i < targets.Count; i++) { if (i != excludedIndex) { num = Math.Min(num, (targets[i] - position).SqrMagnitude); } } return num; } private void SelectTarget(IReadOnlyList<Point3d> targets, bool respectHeading, int additionallyExcludedIndex) { List<int> list = new List<int>(); int num = -1; double num2 = double.NegativeInfinity; int targetIndex = TargetIndex; for (int i = 0; i < targets.Count; i++) { if (i == additionallyExcludedIndex || (respectHeading && i == targetIndex)) { continue; } Point3d point3d = targets[i] - Position; double magnitude = point3d.Magnitude; if (!(magnitude <= lightYear + 1E-07)) { Point3d right = point3d / magnitude; double num3 = (respectHeading ? Point3d.Dot(Direction, right) : 1.0); if (!respectHeading || num3 > 0.5) { list.Add(i); } if (num3 > num2) { num2 = num3; num = i; } } } if (list.Count > 0) { TargetIndex = list[random.NextInt(list.Count)]; } else if (num >= 0) { TargetIndex = num; } else { int excludedIndex = ((additionallyExcludedIndex >= 0) ? additionallyExcludedIndex : (respectHeading ? targetIndex : (-1))); TargetIndex = FindFarthestTarget(targets, excludedIndex); } Direction = (targets[TargetIndex] - Position).Normalized; if (Direction.SqrMagnitude <= 1E-07) { Direction = new Point3d(1.0, 0.0, 0.0); } } private int FindFarthestTarget(IReadOnlyList<Point3d> targets, int excludedIndex) { int num = -1; double num2 = double.NegativeInfinity; for (int i = 0; i < targets.Count; i++) { if (i != excludedIndex || targets.Count <= 1) { double sqrMagnitude = (targets[i] - Position).SqrMagnitude; if (sqrMagnitude > num2) { num2 = sqrMagnitude; num = i; } } } if (num < 0) { return 0; } return num; } private void ScheduleRandomRetarget() { double minimumIntervalSeconds = GetMinimumIntervalSeconds(); double maximumIntervalSeconds = GetMaximumIntervalSeconds(); NextRandomRetargetTime = currentTime + minimumIntervalSeconds + random.NextDouble() * (maximumIntervalSeconds - minimumIntervalSeconds); } private void ScheduleWormhole() { NextWormholeTime = currentTime + minimumWormholeSeconds + random.NextDouble() * (maximumWormholeSeconds - minimumWormholeSeconds); } private static void ValidateParameters(IReadOnlyList<Point3d> targets, double metersPerSecond, double lightYearInMeters) { if (targets == null || targets.Count == 0) { throw new ArgumentException("At least one target star is required.", "targets"); } if (metersPerSecond <= 0.0 || lightYearInMeters <= 0.0) { throw new ArgumentOutOfRangeException("metersPerSecond"); } } } [BepInPlugin("Zincon.DSPWanderingPlanets", "wandering planet III", "1.1.10")] [BepInProcess("DSPGAME.exe")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInIncompatibility("dsp.galactic-scale.2")] [CommonAPISubmoduleDependency(new string[] { "ProtoRegistry" })] public sealed class Plugin : BaseUnityPlugin, IModCanSave { public const string PluginGuid = "Zincon.DSPWanderingPlanets"; public const string PluginName = "wandering planet III"; public const string PluginVersion = "1.1.10"; public const string NestedMoonsGuid = "Zincon.DSPNestedMoons"; public const string DspAddPlanetGuid = "Zincon.DSPAddPlanetMoon2Patch"; public const string GalacticScaleGuid = "dsp.galactic-scale.2"; public const string CommonApiGuid = "dsp.common-api.CommonAPI"; private Harmony harmony; internal static ManualLogSource Log { get; private set; } private void Awake() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown Log = ((BaseUnityPlugin)this).Logger; try { ModConfig.Initialize(((BaseUnityPlugin)this).Config); PrototypeRegistry.Register(); GalaxyGenerationPatches.ValidateTargets(); MotionPatches.ValidateTargets(); VisualPatches.ValidateTargets(); WarpPatches.ValidateTargets(); harmony = new Harmony("Zincon.DSPWanderingPlanets"); harmony.PatchAll(typeof(Plugin).Assembly); ((BaseUnityPlugin)this).Logger.LogInfo((object)"wandering planet III 1.1.10 loaded. New universes will include deterministic wandering systems."); } catch (Exception ex) { Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } harmony = null; ((Behaviour)this).enabled = false; ((BaseUnityPlugin)this).Logger.LogError((object)("Failed to initialize wandering planet III:\n" + ex)); } } private void OnDestroy() { VisualPatches.RestoreRuntimeVisuals(); WarpPatches.ClearRuntimeState(); MotionController.Clear(); PrototypeRegistry.UnregisterRuntimeHandlers(); Harmony obj = harmony; if (obj != null) { obj.UnpatchSelf(); } harmony = null; } private void LateUpdate() { if (harmony != null) { VisualPatches.RefreshRuntimeVisuals(); } } private void Update() { if (harmony != null) { Player mainPlayer = GameMain.mainPlayer; PrototypeRegistry.MigrateLegacyTechnology(GameMain.history); if (VFInput._warpKey && MotionController.TryToggleLocalSystemWarp(mainPlayer)) { WarpPatches.NotifySystemWarpToggleHandled(); } MotionController.RefreshActivePlayerWarp(mainPlayer); WarpPatches.UpdateSteeringInput(); } } public void Export(BinaryWriter writer) { MotionController.Export(writer); } public void Import(BinaryReader reader) { MotionController.Import(reader); } public void IntoOtherSave() { PrototypeRegistry.ResetSaveMigration(); MotionController.IntoOtherSave(); } } internal static class PrototypeRegistry { internal const int PlanetaryWarperItemId = 11991; internal const int PlanetaryWarperRecipeId = 490; internal const int PlanetaryWarpTechId = 1991; private const int LegacyPlanetaryWarpTechId = 11991; private const int VanillaWarperItemId = 1210; private const int GravityLensItemId = 1209; private const int QuantumChipItemId = 1305; private const int StrangeAnnihilationFuelRodItemId = 1804; private const int DarkFogMatterRecombinatorItemId = 5203; private const int DarkFogNegentropySingularityItemId = 5204; private const int GravityMatrixTechId = 1705; private const float TechnologyColumnSpacing = 4f; private const float TechnologyRowSpacing = 4f; private const float TechnologyNodeClearance = 3.5f; private const int GreenMatrixItemId = 6006; private const string VanillaWarperIconPath = "Icons/ItemRecipe/space-warper"; private const string ItemNameKey = "WanderingPlanetaryWarperName"; private const string ItemDescriptionKey = "WanderingPlanetaryWarperDescription"; private const string RecipeDescriptionKey = "WanderingPlanetaryWarperRecipeDescription"; private const string TechNameKey = "WanderingPlanetaryWarpTechNameV2"; private const string TechDescriptionKey = "WanderingPlanetaryWarpTechDescription"; private const string TechConclusionKey = "WanderingPlanetaryWarpTechConclusion"; internal const string WanderingSystemTypeNameKey = "WanderingSystemTypeName"; private static readonly FieldInfo ItemIconField = AccessTools.Field(typeof(ItemProto), "_iconSprite"); private static readonly FieldInfo RecipeIconField = AccessTools.Field(typeof(RecipeProto), "_iconSprite"); private static readonly FieldInfo TechIconField = AccessTools.Field(typeof(TechProto), "_iconSprite"); private static ItemProto itemProto; private static RecipeProto recipeProto; private static TechProto techProto; private static Texture2D iconTexture; private static Sprite iconSprite; private static GameHistoryData migratedHistory; internal static void Register() { //IL_012e: Unknown result type (might be due to invalid IL or missing references) if (ItemIconField == null || RecipeIconField == null || TechIconField == null) { throw new MissingFieldException("DSP prototype icon fields have changed."); } RegisterTranslations(); using (ProtoRegistry.StartModLoad("Zincon.DSPWanderingPlanets")) { itemProto = ProtoRegistry.RegisterItem(11991, "WanderingPlanetaryWarperName", "WanderingPlanetaryWarperDescription", "Icons/ItemRecipe/space-warper", 1707, 10, (EItemType)3); itemProto.Productive = true; recipeProto = ProtoRegistry.RegisterRecipe(490, (ERecipeType)4, 3600, new int[6] { 1210, 1804, 1209, 1305, 5203, 5204 }, new int[6] { 50, 20, 20, 20, 10, 10 }, new int[1] { 11991 }, new int[1] { 1 }, "WanderingPlanetaryWarperRecipeDescription", 1991, 1707, "WanderingPlanetaryWarperName", "Icons/ItemRecipe/space-warper"); techProto = ProtoRegistry.RegisterTech(1991, "WanderingPlanetaryWarpTechNameV2", "WanderingPlanetaryWarpTechDescription", "WanderingPlanetaryWarpTechConclusion", "Icons/ItemRecipe/space-warper", new int[1] { 1705 }, new int[1] { 6006 }, new int[1] { 1 }, 21600000L, new int[1] { 490 }, FindTechnologyPosition()); if (((Proto)techProto).ID != 1991) { Plugin.Log.LogWarning((object)("LDBTool remapped the planetary-warp technology from " + 1991 + " to " + ((Proto)techProto).ID + "; restoring the main-tree ID.")); ((Proto)techProto).ID = 1991; } } ProtoRegistry.onLoadingFinished += ApplyCustomIcon; } internal static void UnregisterRuntimeHandlers() { migratedHistory = null; ProtoRegistry.onLoadingFinished -= ApplyCustomIcon; if ((Object)(object)iconSprite != (Object)null) { Object.Destroy((Object)(object)iconSprite); iconSprite = null; } if ((Object)(object)iconTexture != (Object)null) { Object.Destroy((Object)(object)iconTexture); iconTexture = null; } } internal static bool TryConsumePlanetaryWarper(Player player) { StorageComponent val = ((player == null) ? null : player.mecha?.warpStorage); if (val?.grids == null || val.grids.Length == 0 || val.grids[0].itemId != 11991 || val.grids[0].count <= 0) { return false; } int num = 11991; int num2 = 1; int num3 = default(int); val.TakeTailItems(ref num, ref num2, ref num3, false); if (num != 11991 || num2 != 1) { return false; } player.mecha.AddConsumptionStat(num, num2, player.nearestFactory); return true; } internal static bool IsPlanetaryWarpTechUnlocked(GameHistoryData history) { if (history != null) { if (!history.TechUnlocked(1991)) { return history.TechUnlocked(11991); } return true; } return false; } internal static void MigrateLegacyTechnology(GameHistoryData history) { if (history != null && history != migratedHistory) { if (history.TechUnlocked(11991) && !history.TechUnlocked(1991)) { history.UnlockTechUnlimited(1991, true); Plugin.Log.LogInfo((object)"Migrated the legacy planetary-warp technology to the visible tech tree."); } migratedHistory = history; } } internal static void ResetSaveMigration() { migratedHistory = null; } internal static bool IsSupportedWarper(int itemId) { if (itemId != 1210) { return itemId == 11991; } return true; } internal static int GetWarpSlotStackSize(int itemId) { if (itemId != 11991) { return 20; } return 10; } private static Vector2 FindTechnologyPosition() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(1705); if (val == null) { return new Vector2(53f, -35f); } float num = val.Position.x + 4f; Vector2 val2 = default(Vector2); for (int i = 0; i < 64; i++) { int num2 = ((i != 0) ? ((i + 1) / 2 * ((i % 2 != 1) ? 1 : (-1))) : 0); ((Vector2)(ref val2))..ctor(num, val.Position.y + (float)num2 * 4f); if (IsTechnologyPositionFree(val2)) { return val2; } } return new Vector2(num, val.Position.y - 256f); } private static bool IsTechnologyPositionFree(Vector2 candidate) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) TechProto[] dataArray = ((ProtoSet<TechProto>)(object)LDB.techs).dataArray; if (dataArray == null) { return true; } foreach (TechProto val in dataArray) { if (val != null && ((Proto)val).ID < 2000 && Math.Abs(val.Position.x - candidate.x) < 3.5f && Math.Abs(val.Position.y - candidate.y) < 3.5f) { return false; } } return true; } private static void RegisterTranslations() { LocalizationModule.RegisterTranslation("WanderingPlanetaryWarperName", "Planetary Space Warper", "行星空间翘曲器", "Planetary Space Warper"); LocalizationModule.RegisterTranslation("WanderingPlanetaryWarperDescription", "A Dark-Fog-derived curvature core that encloses nearby space and drives an entire wandering system through a jump.", "源自黑雾空间技术的曲率核心,可包裹附近空间并驱动整个流浪星系跳跃。", "A Dark-Fog-derived curvature core that encloses nearby space and drives an entire wandering system through a jump."); LocalizationModule.RegisterTranslation("WanderingPlanetaryWarperRecipeDescription", "Combine warpers, strange annihilation fuel, gravitational components, and Dark Fog matter-control materials into a stellar-scale jump core.", "将翘曲器、奇异湮灭燃料、引力组件与黑雾物质控制材料封装为星系尺度的跳跃核心。", "Combine warpers, strange annihilation fuel, gravitational components, and Dark Fog matter-control materials into a stellar-scale jump core."); LocalizationModule.RegisterTranslation("WanderingPlanetaryWarpTechNameV2", "Planetary Spacetime Folding", "行星级空间折叠", "Planetary Spacetime Folding"); LocalizationModule.RegisterTranslation("WanderingPlanetaryWarpTechDescription", "Reverse-engineer the Dark Fog's matter-recombination and negentropy-confinement technologies to construct a closed curvature field around an entire star system. Powered by core-element-antimatter annihilation, the field reconstructs local spacetime topology, removes the wandering system from its conventional geodesic, and reinserts it at the target coordinates.", "通过逆向解析黑雾的物质重组与负熵约束技术,构建覆盖整个恒星系统的闭合曲率场。核心素-反物质奇异湮灭反应为局部时空拓扑重构提供能量,使流浪星系整体脱离常规测地线,并在目标坐标重新嵌入现实空间。", "Reverse-engineer the Dark Fog's matter-recombination and negentropy-confinement technologies to construct a closed curvature field around an entire star system. Powered by core-element-antimatter annihilation, the field reconstructs local spacetime topology, removes the wandering system from its conventional geodesic, and reinserts it at the target coordinates."); LocalizationModule.RegisterTranslation("WanderingPlanetaryWarpTechConclusion", "System-scale curvature navigation protocol established. Controlled spatial jumps are now available to wandering systems.", "系统级曲率航行协议已完成。流浪星系现可执行受控空间跃迁。", "System-scale curvature navigation protocol established. Controlled spatial jumps are now available to wandering systems."); LocalizationModule.RegisterTranslation("WanderingSystemTypeName", "Wandering System", "流浪星系", "Wandering System"); } private static void ApplyCustomIcon() { //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Expected O, but got Unknown //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) TechProto val = ((ProtoSet<TechProto>)(object)LDB.techs).Select(1991); RecipeProto val2 = ((ProtoSet<RecipeProto>)(object)LDB.recipes).Select(490); if (val != techProto || val2 != recipeProto || val.PreTechs == null || Array.IndexOf(val.PreTechs, 1705) < 0) { Plugin.Log.LogError((object)("Planetary-warp prototype self-check failed: tech=" + ((val == null) ? "missing" : ((Proto)val).ID.ToString()) + ", recipe=" + ((val2 == null) ? "missing" : ((Proto)val2).ID.ToString()) + ".")); } else { Plugin.Log.LogInfo((object)("Planetary-warp prototypes loaded at main-tree tech ID " + ((Proto)val).ID + " after gravity-matrix tech " + 1705 + " at (" + val.Position.x + ", " + val.Position.y + ") with " + val2.Items.Length + " recipe ingredients.")); } try { using (Stream stream = typeof(PrototypeRegistry).Assembly.GetManifestResourceStream("DSPWanderingPlanets.assets.planetary-space-warper.png")) { if (stream == null) { throw new FileNotFoundException("Embedded planetary-warper icon was not found.", "DSPWanderingPlanets.assets.planetary-space-warper.png"); } byte[] array = new byte[stream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = stream.Read(array, i, array.Length - i); if (num <= 0) { throw new EndOfStreamException("Could not read the embedded icon."); } } iconTexture = new Texture2D(2, 2, (TextureFormat)5, false); ((Object)iconTexture).name = "planetary-space-warper"; if (!ImageConversion.LoadImage(iconTexture, array, false)) { throw new InvalidDataException("The embedded icon is not a valid PNG."); } iconSprite = Sprite.Create(iconTexture, new Rect(0f, 0f, (float)((Texture)iconTexture).width, (float)((Texture)iconTexture).height), new Vector2(0.5f, 0.5f), 100f); ((Object)iconSprite).name = "planetary-space-warper"; } ItemIconField.SetValue(itemProto, iconSprite); RecipeIconField.SetValue(recipeProto, iconSprite); TechIconField.SetValue(techProto, iconSprite); } catch (Exception ex) { Plugin.Log.LogError((object)("Failed to apply the planetary-warper icon: " + ex)); } } } [HarmonyPatch] internal static class VeinGenerationPatches { private const int UnipolarTypeIndex = 14; [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(PlanetAlgorithm), "GenerateVeins")] private static void PlanetAlgorithm_Postfix(PlanetData ___planet) { TryInjectUnipolarCluster(___planet); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(PlanetAlgorithm0), "GenerateVeins")] private static void PlanetAlgorithm0_Postfix(PlanetData ___planet) { TryInjectUnipolarCluster(___planet); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(PlanetAlgorithm7), "GenerateVeins")] private static void PlanetAlgorithm7_Postfix(PlanetData ___planet) { TryInjectUnipolarCluster(___planet); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(PlanetAlgorithm11), "GenerateVeins")] private static void PlanetAlgorithm11_Postfix(PlanetData ___planet) { TryInjectUnipolarCluster(___planet); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(PlanetAlgorithm12), "GenerateVeins")] private static void PlanetAlgorithm12_Postfix(PlanetData ___planet) { TryInjectUnipolarCluster(___planet); } [HarmonyPostfix] [HarmonyPriority(0)] [HarmonyPatch(typeof(PlanetAlgorithm13), "GenerateVeins")] private static void PlanetAlgorithm13_Postfix(PlanetData ___planet) { TryInjectUnipolarCluster(___planet); } private static void TryInjectUnipolarCluster(PlanetData planet) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Invalid comparison between Unknown and I4 //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!MotionController.IsWanderingPlanet(planet) || (int)planet.type == 5 || (int)planet.type == 0 || planet.data == null) { return; } DeterministicRandom deterministicRandom = new DeterministicRandom((uint)(planet.seed ^ 0x4D41474E)); if (deterministicRandom.NextDouble() >= (double)ModConfig.UnipolarMagnetChance.Value) { return; } lock (planet) { if (!ContainsUnipolarVein(planet.data)) { AddUnipolarCluster(planet, deterministicRandom); } } } private static bool ContainsUnipolarVein(PlanetRawData data) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Invalid comparison between Unknown and I4 if (data.veinPool == null) { return false; } for (int i = 1; i < data.veinCursor && i < data.veinPool.Length; i++) { if (data.veinPool[i].id == i && (int)data.veinPool[i].type == 14) { return true; } } return false; } private static void AddUnipolarCluster(PlanetData planet, DeterministicRandom random) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01db: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_021d: Unknown result type (might be due to invalid IL or missing references) //IL_0225: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) int[] veinModelIndexs = PlanetModelingManager.veinModelIndexs; int[] veinModelCounts = PlanetModelingManager.veinModelCounts; int[] veinProducts = PlanetModelingManager.veinProducts; if (veinModelIndexs == null || veinModelCounts == null || veinProducts == null || veinModelIndexs.Length <= 14 || veinModelCounts.Length <= 14 || veinProducts.Length <= 14 || veinModelCounts[14] <= 0) { return; } PlanetRawData data = planet.data; if (!TryChooseClusterCenter(planet, data, random, out var center)) { return; } int num = FindNextGroupIndex(data); Quaternion val = Quaternion.FromToRotation(Vector3.up, center); Vector3 val2 = val * Vector3.right; Vector3 val3 = val * Vector3.forward; float num2 = 2.1f / planet.radius; int num3 = random.NextInt(12, 19); int amountBase = Mathf.Max(20, Mathf.RoundToInt(30000f * Math.Max(0.1f, planet.star.resourceCoef))); List<Vector3> list = new List<Vector3>(num3); int num4 = 0; for (int i = 0; i < num3 * 20; i++) { if (num4 >= num3) { break; } double num5 = random.NextDouble() * Math.PI * 2.0; float num6 = ((num4 == 0) ? 0f : ((float)Math.Sqrt(random.NextDouble()) * 4.2f)); Vector3 val4 = (val2 * (float)Math.Cos(num5) + val3 * (float)Math.Sin(num5)) * (num6 * num2); Vector3 val5 = center + val4; Vector3 normalized = ((Vector3)(ref val5)).normalized; float num7 = data.QueryHeight(normalized); if (!(num7 < planet.radius) && !IsTooCloseToClusterNode(list, normalized, num2)) { VeinData val6 = new VeinData { type = (EVeinType)14, groupIndex = (short)num, modelIndex = (short)(veinModelIndexs[14] + random.NextInt(veinModelCounts[14])), amount = CalculateAmount(amountBase, random), productId = veinProducts[14], pos = normalized * num7, minerCount = 0 }; if (DSPGame.GameDesc.isInfiniteResource) { val6.amount = 1000000000; } else { val6.amount = Mathf.Max(1, Mathf.RoundToInt((float)val6.amount * DSPGame.GameDesc.resourceMultiplier)); } data.EraseVegetableAtPoint(normalized); data.AddVeinData(val6); list.Add(normalized); num4++; } } } private static bool IsTooCloseToClusterNode(List<Vector3> placedDirections, Vector3 direction, float spacing) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //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) float num = spacing * spacing * 0.65f; for (int i = 0; i < placedDirections.Count; i++) { Vector3 val = placedDirections[i] - direction; if (((Vector3)(ref val)).sqrMagnitude < num) { return true; } } return false; } private static bool TryChooseClusterCenter(PlanetData planet, PlanetRawData data, DeterministicRandom random, out Vector3 center) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < 512; i++) { center = new Vector3((float)(random.NextDouble() * 2.0 - 1.0), (float)(random.NextDouble() * 2.0 - 1.0), (float)(random.NextDouble() * 2.0 - 1.0)); if (!(((Vector3)(ref center)).sqrMagnitude < 0.01f)) { ((Vector3)(ref center)).Normalize(); if (!(data.QueryHeight(center) < planet.radius) && !IsNearExistingVein(data, center)) { return true; } } } center = Vector3.zero; return false; } private static bool IsNearExistingVein(PlanetRawData data, Vector3 center) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if (data.veinPool == null) { return false; } for (int i = 1; i < data.veinCursor && i < data.veinPool.Length; i++) { VeinData val = data.veinPool[i]; if (val.id == i && ((Vector3)(ref val.pos)).sqrMagnitude > 0.01f && Vector3.Dot(((Vector3)(ref val.pos)).normalized, center) > 0.985f) { return true; } } return false; } private static int FindNextGroupIndex(PlanetRawData data) { int num = 0; if (data.veinPool != null) { for (int i = 1; i < data.veinCursor && i < data.veinPool.Length; i++) { if (data.veinPool[i].id == i) { num = Math.Max(num, data.veinPool[i].groupIndex); } } } return Math.Min(32767, num + 1); } private static int CalculateAmount(int amountBase, DeterministicRandom random) { return Mathf.RoundToInt((float)amountBase * (float)(0.5 + random.NextDouble())); } } internal static class VisualPatches { private sealed class HiddenOrbitState { internal PlanetData Planet; internal GameObject RelatedObject; internal Renderer PlanetRenderer; internal Renderer[] Renderers; internal bool[] EnabledStates; internal void Hide() { for (int i = 0; i < Renderers.Length; i++) { Renderer val = Renderers[i]; if ((Object)(object)val != (Object)null && val != PlanetRenderer) { val.enabled = false; } } } internal void Restore() { for (int i = 0; i < Renderers.Length; i++) { Renderer val = Renderers[i]; if ((Object)(object)val != (Object)null) { val.enabled = EnabledStates[i]; } } } } [HarmonyPatch(typeof(UIStarmapPlanet), "_OnLateUpdate")] private static class StarmapPlanetLightingPatch { [HarmonyPostfix] private static void Postfix(UIStarmapPlanet __instance) { RemoveStarmapDaylight(__instance); } } [HarmonyPatch(typeof(UIStarmap), "_OnLateUpdate")] private static class StarmapPlayerTrackDirectionPatch { [HarmonyPostfix] private static void Postfix(UIStarmap __instance) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance?.playerTrack == (Object)null) && MotionController.TryGetActivePlayerWarpDirection(out var direction)) { Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor((float)direction.X, (float)direction.Y, (float)direction.Z); if (((Vector3)(ref val)).sqrMagnitude > 1E-06f) { __instance.playerTrack.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized); } } } } [HarmonyPatch(typeof(UIStarmapPlanet), "_OnFree")] private static class StarmapPlanetFreePatch { [HarmonyPrefix] private static void Prefix(UIStarmapPlanet __instance) { RestoreOrbitVisibility(__instance); } } [HarmonyPatch(/*Could not decode attribute arguments.*/)] private static class WanderingSystemTypeNamePatch { [HarmonyPostfix] private static void Postfix(StarData __instance, ref string __result) { if (MotionController.IsWanderingStar(__instance)) { __result = Localization.Translate("WanderingSystemTypeName"); } } } [HarmonyPatch(typeof(UIStarDetail), "OnStarDataSet")] private static class WanderingSystemSpectrumPatch { [HarmonyPostfix] private static void Postfix(UIStarDetail __instance) { if (MotionController.IsWanderingStar((__instance != null) ? __instance.star : null)) { if ((Object)(object)__instance.typeText != (Object)null) { __instance.typeText.text = Localization.Translate("WanderingSystemTypeName"); } if ((Object)(object)__instance.spectrValueText != (Object)null) { __instance.spectrValueText.text = "-"; } } } } private static readonly Color StarmapGray = new Color(0.56f, 0.59f, 0.61f, 1f); private static readonly Dictionary<UIStarmapPlanet, HiddenOrbitState> HiddenOrbits = new Dictionary<UIStarmapPlanet, HiddenOrbitState>(); private static FieldInfo spotMaterialField; private static FieldInfo massMaterialField; private static FieldInfo planetMaterialField; internal static void ValidateTargets() { spotMaterialField = AccessTools.Field(typeof(UIStarmapStarObject), "spotMat"); massMaterialField = AccessTools.Field(typeof(UIStarmapStarObject), "massMat"); planetMaterialField = AccessTools.Field(typeof(UIStarmapPlanet), "planetMat"); if (spotMaterialField == null || massMaterialField == null || planetMaterialField == null || AccessTools.Method(typeof(UIStarmap), "_OnLateUpdate", (Type[])null, (Type[])null) == null || AccessTools.Method(typeof(UIStarmapPlanet), "_OnLateUpdate", (Type[])null, (Type[])null) == null || AccessTools.Method(typeof(UIStarmapPlanet), "_OnFree", (Type[])null, (Type[])null) == null || AccessTools.PropertyGetter(typeof(StarData), "typeString") == null || AccessTools.Method(typeof(UIStarDetail), "OnStarDataSet", (Type[])null, (Type[])null) == null) { throw new MissingFieldException("DSP starmap visual fields have changed."); } } internal static void RefreshRuntimeVisuals() { HidePhysicalStars(((Object)(object)GameMain.instance == (Object)null) ? null : GameMain.universeSimulator); UpdateStarmap(UIRoot.instance?.uiGame?.starmap); } internal static void RestoreRuntimeVisuals() { foreach (HiddenOrbitState value in HiddenOrbits.Values) { value.Restore(); } HiddenOrbits.Clear(); } private static void HidePhysicalStars(UniverseSimulator universe) { if (universe?.starSimulators == null) { return; } for (int i = 0; i < universe.starSimulators.Length; i++) { StarSimulator val = universe.starSimulators[i]; if ((Object)(object)val != (Object)null && MotionController.IsWanderingStar(val.starData) && ((Component)val).gameObject.activeSelf) { ((Component)val).gameObject.SetActive(false); } } } private static void UpdateStarmap(UIStarmap starmap) { if ((Object)(object)starmap == (Object)null) { RestoreRuntimeVisuals(); return; } if (starmap.planetUIs != null) { for (int i = 0; i < starmap.planetUIs.Length; i++) { UIStarmapPlanet val = starmap.planetUIs[i]; if (!((Object)(object)val == (Object)null)) { bool hiddenMainOrbit = MotionController.IsWanderingPlanet(val.planet) && val.planet?.orbitAroundPlanet == null && (Object)(object)val.relatedObject != (Object)null; UpdateOrbitVisibility(val, hiddenMainOrbit); RemoveStarmapDaylight(val); } } } if (starmap.starUIs == null) { return; } for (int j = 0; j < starmap.starUIs.Length; j++) { UIStarmapStarObject val2 = starmap.starUIs[j]?.starObject; if (!((Object)(object)val2 == (Object)null) && MotionController.IsWanderingStar(val2.star)) { object? value = spotMaterialField.GetValue(val2); ApplyGray((Material)((value is Material) ? value : null), val2.spotBlender); object? value2 = massMaterialField.GetValue(val2); ApplyGray((Material)((value2 is Material) ? value2 : null), val2.massBlender); } } } private static void UpdateOrbitVisibility(UIStarmapPlanet planetUi, bool hiddenMainOrbit) { if (HiddenOrbits.TryGetValue(planetUi, out var value) && (!hiddenMainOrbit || value.Planet != planetUi.planet || value.RelatedObject != planetUi.relatedObject)) { value.Restore(); HiddenOrbits.Remove(planetUi); value = null; } if (!hiddenMainOrbit) { return; } if (value == null) { Renderer[] componentsInChildren = planetUi.relatedObject.GetComponentsInChildren<Renderer>(true); bool[] array = new bool[componentsInChildren.Length]; for (int i = 0; i < componentsInChildren.Length; i++) { array[i] = (Object)(object)componentsInChildren[i] != (Object)null && componentsInChildren[i].enabled; } value = new HiddenOrbitState { Planet = planetUi.planet, RelatedObject = planetUi.relatedObject, PlanetRenderer = planetUi.planetRenderer, Renderers = componentsInChildren, EnabledStates = array }; HiddenOrbits.Add(planetUi, value); } value.Hide(); } private static void RemoveStarmapDaylight(UIStarmapPlanet planetUi) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (MotionController.IsWanderingPlanet(planetUi.planet)) { object? value = planetMaterialField.GetValue(planetUi); Material val = (Material)((value is Material) ? value : null); if ((Object)(object)val != (Object)null && val.HasProperty("_SunDir")) { val.SetVector("_SunDir", Vector4.zero); } } } private static void RestoreOrbitVisibility(UIStarmapPlanet planetUi) { if ((Object)(object)planetUi != (Object)null && HiddenOrbits.TryGetValue(planetUi, out var value)) { value.Restore(); HiddenOrbits.Remove(planetUi); } } private static void ApplyGray(Material material, StarMaterialBlender blender) { if ((Object)(object)material == (Object)null) { return; } if (blender?.colorPropNames != null) { for (int i = 0; i < blender.colorPropNames.Length; i++) { SetGrayIfPresent(material, blender.colorPropNames[i]); } } SetGrayIfPresent(material, "_Color"); SetGrayIfPresent(material, "_TintColor"); SetGrayIfPresent(material, "_SunCenterColor"); SetGrayIfPresent(material, "_SunGlowColor"); } private static void SetGrayIfPresent(Material material, string propertyName) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(propertyName) && material.HasProperty(propertyName)) { Color color = material.GetColor(propertyName); material.SetColor(propertyName, new Color(StarmapGray.r, StarmapGray.g, StarmapGray.b, color.a)); } } } internal static class WanderingSystemFactory { private const double SatelliteGravity = 1.0830842106853677E-08; private const double FourPiSquared = 39.47841760435743; private const float MainPlanetOffsetAu = 1f; private const int MediterraneanThemeId = 1; internal static void TransformGalaxy(GalaxyData galaxy, GameDesc gameDesc, int systemCount) { int[] array = SelectSystemIndexes(galaxy, systemCount); if (array.Length == 0) { Plugin.Log.LogWarning((object)"No non-birth main-sequence stars were available for wandering systems."); return; } for (int i = 0; i < array.Length; i++) { BuildSystem(galaxy, galaxy.stars[array[i]], gameDesc, i + 1); } if (ModConfig.StartInWanderingSystem.Value && ConfigureBirthSystem(galaxy, array)) { Plugin.Log.LogInfo((object)"Configured the first wandering system as the new-save birth system."); } IsolateMovingGraphNodes(galaxy, array); RecalculateHabitableCount(galaxy); MotionController.Register(galaxy, array); MotionController.BeforePoseUpdate(galaxy, 0.0); for (int j = 0; j < array.Length; j++) { StarData val = galaxy.stars[array[j]]; for (int k = 0; k < val.planetCount; k++) { val.planets[k].UpdateRuntimePose(0.0); } } MotionController.AfterPoseUpdate(galaxy); Plugin.Log.LogInfo((object)("Generated " + array.Length + " wandering systems with the built-in route planner enabled.")); if (array.Length < systemCount) { Plugin.Log.LogWarning((object)("Requested " + systemCount + " wandering systems, but only " + array.Length + " non-birth main-sequence stars were available. Compact and giant stars were preserved.")); } } private static int[] SelectSystemIndexes(GalaxyData galaxy, int requestedCount) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) List<int> list = new List<int>(requestedCount); int num = galaxy.starCount - 1; while (num >= 1 && list.Count < requestedCount) { StarData val = galaxy.stars[num]; if (val != null && (int)val.type == 0) { list.Add(num); } num--; } list.Sort(); return list.ToArray(); } private static bool ConfigureBirthSystem(GalaxyData galaxy, int[] systemIndexes) { if (galaxy == null || systemIndexes == null) { return false; } foreach (int num in systemIndexes) { if (num < 0 || num >= galaxy.starCount) { continue; } StarData val = galaxy.stars[num]; if (val?.planets != null) { PlanetData val2 = SelectBirthPlanet(val, galaxy.seed); if (val2 != null && ApplyMediterraneanBirthTheme(val2)) { galaxy.birthStarId = val.id; galaxy.birthPlanetId = val2.id; return true; } } } return false; } private static PlanetData SelectBirthPlanet(StarData star, int galaxySeed) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Invalid comparison between Unknown and I4 List<PlanetData> list = new List<PlanetData>(); for (int i = 0; i < star.planetCount; i++) { PlanetData val = star.planets[i]; if (val != null && (int)val.type != 5 && (val.orbitAroundPlanet == null || val.orbitAroundPlanet.orbitAroundPlanet == null)) { list.Add(val); } } if (list.Count == 0) { return null; } DeterministicRandom deterministicRandom = new DeterministicRandom((uint)(galaxySeed ^ star.seed ^ 0x42495254)); return list[deterministicRandom.NextInt(list.Count)]; } private static bool ApplyMediterraneanBirthTheme(PlanetData planet) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Invalid comparison between Unknown and I4 if (planet.theme == 1 && (int)planet.type == 2) { return true; } ThemeProto val = ((ProtoSet<ThemeProto>)(object)LDB.themes)?.Select(1); if (val == null || (int)val.Distribute != 1 || (int)val.PlanetType != 2) { Plugin.Log.LogError((object)"Vanilla Mediterranean birth theme 1 is unavailable; wandering-system birth was not enabled."); return false; } DotNet35Random val2 = new DotNet35Random(planet.infoSeed ^ 0x4D454449); double num = val2.NextDouble(); double num2 = val2.NextDouble(); double num3 = val2.NextDouble(); double num4 = val2.NextDouble(); int num5 = val2.Next(); int index = planet.star.index; try { planet.type = (EPlanetType)2; planet.star.index = 0; PlanetGen.SetPlanetTheme(planet, new int[1] { 1 }, num, num2, num3, num4, num5); } finally { planet.star.index = index; } if (planet.theme == 1) { return (int)planet.type == 2; } return false; } private static void BuildSystem(GalaxyData galaxy, StarData star, GameDesc gameDesc, int ordinal) { ClearOldPlanetAstros(galaxy, star); PrepareGenerationAnchor(star, ordinal); BodyLayout[] array = WanderingSystemLayout.Generate((star.seed * 397) ^ (galaxy.seed * 7919) ^ ordinal); star.planets = (PlanetData[])(object)new PlanetData[array.Length]; star.planetCount = array.Length; for (int i = 0; i < array.Length; i++) { int num = star.seed * 486187739 + i * 16777619 + 31; int num2 = (num * 397) ^ 0x57414E44; PlanetData val = PlanetGen.CreatePlanet(galaxy, star, gameDesc.savedThemeIds, i, 0, Math.Min(16, Math.Max(1, array[i].OrbitIndex)), i + 1, array[i].IsGas, num, num2); star.planets[i] = val; } ConfigureHierarchy(galaxy, star, array); SuppressAnchorStar(galaxy, star); } private static void PrepareGenerationAnchor(StarData star, int ordinal) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) star.name = "Wandering Planet " + ordinal; star.overrideName = string.Empty; star.type = (EStarType)0; star.mass = 1f; star.radius = 1f; star.luminosity = 1f; star.temperature = 5778f; star.habitableRadius = 1f; star.lightBalanceRadius = 1f; star.orbitScaler = 1f; star.asterBelt1OrbitIndex = 0f; star.asterBelt2OrbitIndex = 0f; star.asterBelt1Radius = 0f; star.asterBelt2Radius = 0f; } private static void ConfigureHierarchy(GalaxyData galaxy, StarData star, BodyLayout[] layout) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Invalid comparison between Unknown and I4 //IL_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < layout.Length; i++) { BodyLayout bodyLayout = layout[i]; PlanetData val = star.planets[i]; val.singularity = (EPlanetSingularity)(val.singularity & -33); if (bodyLayout.ParentIndex < 0) { val.orbitAroundPlanet = null; val.orbitAround = 0; val.orbitIndex = 1; val.number = 1; val.orbitRadius = 1f; val.sunDistance = 1f; val.orbitalPeriod = 1E+30; val.orbitPhase = 0f; } else { PlanetData val2 = (val.orbitAroundPlanet = star.planets[bodyLayout.ParentIndex]); val.orbitAround = val2.number; val.orbitIndex = bodyLayout.OrbitIndex; val.number = bodyLayout.SiblingNumber; val.orbitRadius = CalculateSatelliteOrbitRadius(star, val2, val); val.sunDistance = 1f; val.orbitalPeriod = Math.Sqrt(39.47841760435743 * (double)val.orbitRadius * (double)val.orbitRadius * (double)val.orbitRadius / 1.0830842106853677E-08); } float radiusForDepth = WanderingSystemLayout.GetRadiusForDepth(bodyLayout.Depth, val.radius); if (Math.Abs(radiusForDepth - val.radius) > 0.01f) { val.radius = radiusForDepth; if ((int)val.type != 5) { val.scale = 1f; val.precision = 200; val.segment = 5; } } UpdateRuntimeRotations(val); val.luminosity = CalculateSolarEfficiency(val.infoSeed); galaxy.astrosData[val.id].uRadius = val.realRadius; } float sunDistance = CalculateSystemRadius(star); for (int j = 0; j < star.planetCount; j++) { star.planets[j].sunDistance = sunDistance; } for (int k = 0; k < layout.Length; k++) { if (layout[k].Children.Count > 0) { PlanetData obj = star.planets[k]; obj.singularity = (EPlanetSingularity)(obj.singularity | 0x20); } } } private static float CalculateSystemRadius(StarData star) { float num = 1f; for (int i = 0; i < star.planetCount; i++) { PlanetData obj = star.planets[i]; float num2 = obj.realRadius / 40000f; for (PlanetData val = obj; val != null; val = val.orbitAroundPlanet) { num2 += val.orbitRadius; } num = Math.Max(num, num2); } return num; } private static float CalculateSatelliteOrbitRadius(StarData star, PlanetData parent, PlanetData satellite) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) DotNet35Random val = new DotNet35Random(satellite.infoSeed); double num = val.NextDouble(); double num2 = val.NextDouble(); float num3 = Mathf.Pow(1.2f, (float)(num * (num2 - 0.5) * 0.5)); return ((1600f * (float)satellite.orbitIndex + 200f) * Mathf.Pow(star.orbitScaler, 0.3f) * Mathf.Lerp(num3, 1f, 0.5f) + parent.realRadius) / 40000f; } private static void UpdateRuntimeRotations(PlanetData body) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_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) Quaternion val = Quaternion.AngleAxis(body.orbitLongitude, Vector3.up) * Quaternion.AngleAxis(body.orbitInclination, Vector3.forward); body.runtimeOrbitRotation = ((body.orbitAroundPlanet == null) ? val : (body.orbitAroundPlanet.runtimeOrbitRotation * val)); body.runtimeSystemRotation = body.runtimeOrbitRotation * Quaternion.AngleAxis(body.obliquity, Vector3.forward); } private static float CalculateSolarEfficiency(int seed) { DeterministicRandom deterministicRandom = new DeterministicRandom((uint)(seed ^ 0x534F4C52)); return (float)(0.001 + deterministicRandom.NextDouble() * 0.009); } private static void SuppressAnchorStar(GalaxyData galaxy, StarData star) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) star.mass = 0.01f; star.radius = 1f; star.luminosity = 0f; star.temperature = 1f; star.classFactor = -2f; star.color = 0.3f; star.habitableRadius = 0f; star.lightBalanceRadius = 0f; star.dysonRadius = 0.2f; star.acdiskRadius = 0f; star.asterBelt1OrbitIndex = 0f; star.asterBelt2OrbitIndex = 0f; star.asterBelt1Radius = 0f; star.asterBelt2Radius = 0f; star.initialHiveCount = 0; star.maxHiveCount = 0; star.hivePatternLevel = 0; AstroData val = galaxy.astrosData[star.astroId]; val.id = star.astroId; val.type = (EAstroType)1; val.parentId = 0; val.uRadius = 0f; galaxy.astrosData[star.astroId] = val; } private static void ClearOldPlanetAstros(GalaxyData galaxy, StarData star) { for (int i = 1; i < 100; i++) { ((AstroData)(ref galaxy.astrosData[star.astroId + i])).SetEmpty(); galaxy.astrosFactory[star.astroId + i] = null; } } private static void IsolateMovingGraphNodes(GalaxyData galaxy, int[] systemIndexes) { if (galaxy.graphNodes == null) { return; } foreach (int num in systemIndexes) { StarGraphNode val = galaxy.graphNodes[num]; if (val == null) { continue; } for (int j = 0; j < galaxy.graphNodes.Length; j++) { StarGraphNode val2 = galaxy.graphNodes[j]; if (val2 != null && val2 != val) { val2.conns?.Remove(val); val2.lines?.Remove(val); } } val.conns?.Clear(); val.lines?.Clear(); } } private static void RecalculateHabitableCount(GalaxyData galaxy) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Invalid comparison between Unknown and I4 int num = 0; for (int i = 0; i < galaxy.starCount; i++) { PlanetData[] planets = galaxy.stars[i].planets; for (int j = 0; j < planets.Length; j++) { if (planets[j] != null && (int)planets[j].type == 2) { num++; } } } galaxy.habitableCount = num; } } internal sealed class BodyLayout { internal int Index { get; } internal int ParentIndex { get; } internal int Depth { get; } internal bool IsGas { get; } internal int OrbitIndex { get; set; } internal int SiblingNumber { get; set; } internal List<int> Children { get; } internal BodyLayout(int index, int parentIndex, int depth, bool isGas) { Index = index; ParentIndex = parentIndex; Depth = depth; IsGas = isGas; Children = new List<int>(); } } internal static class WanderingSystemLayout { internal const int MinimumPrimaryMoons = 2; internal const int MaximumPrimaryMoons = 5; internal const int MaximumBodies = 6; internal const int MaximumDepth = 5; internal const double BaseMoonChance = 0.6; internal static BodyLayout[] Generate(int seed) { DeterministicRandom deterministicRandom = new DeterministicRandom((uint)(seed ^ 0x4D4F4F4E)); List<BodyLayout> list = new List<BodyLayout>(6); BodyLayout bodyLayout = AddBody(list, -1, 0, isGas: false); int num = 2 + deterministicRandom.NextInt(4); for (int i = 0; i < num; i++) { if (list.Count >= 6) { break; } AddBody(list, bodyLayout.Index, 1, RollGas(deterministicRandom)); } for (int j = 0; j < bodyLayout.Children.Count; j++) { if (list.Count >= 6) { break; } AddNestedMoons(list, list[bodyLayout.Children[j]], deterministicRandom); } AssignSatelliteOrbits(bodyLayout, list); return list.ToArray(); } internal static double GetHostChance(int hostDepth) { if (hostDepth < 0) { throw new ArgumentOutOfRangeException("hostDepth"); } return Math.Pow(0.6, hostDepth + 1); } internal static float GetRadiusForDepth(int depth, float originalRadius) { if (depth == 3) { return 160f; } if (depth >= 4) { return 80f; } return originalRadius; } private static BodyLayout AddBody(List<BodyLayout> bodies, int parentIndex, int depth, bool isGas) { BodyLayout bodyLayout = new BodyLayout(bodies.Count, parentIndex, depth, isGas); bodies.Add(bodyLayout); if (parentIndex >= 0) { bodies[parentIndex].Children.Add(bodyLayout.Index); } return bodyLayout; } private static void AddNestedMoons(List<BodyLayout> bodies, BodyLayout parent, DeterministicRandom random) { if (parent.Depth < 5) { double hostChance = GetHostChance(parent.Depth); while (bodies.Count < 6 && random.NextDouble() < hostChance) { BodyLayout parent2 = AddBody(bodies, parent.Index, parent.Depth + 1, RollGas(random)); AddNestedMoons(bodies, parent2, random); } } } private static bool RollGas(DeterministicRandom random) { return random.NextDouble() < 0.2; } private static void AssignSatelliteOrbits(BodyLayout host, IReadOnlyList<BodyLayout> bodies) { int num = 0; for (int i = 0; i < host.Children.Count; i++) { BodyLayout bodyLayout = bodies[host.Children[i]]; int num2 = (bodyLayout.IsGas ? 3 : ((bodyLayout.Children.Count > 0) ? 1 : 0)); bodyLayout.SiblingNumber = i + 1; bodyLayout.OrbitIndex = i + 1 + num + num2; num += num2 * 2; AssignSatelliteOrbits(bodyLayout, bodies); } } } internal static class WarpPatches { [HarmonyPatch] private static class WarperStorageAddPatches { internal static IEnumerable<MethodBase> GetTargetMethods() { Type byRefInt = typeof(int).MakeByRefType(); yield return AccessTools.Method(typeof(StorageComponent), "AddItem", new Type[5] { typeof(int), typeof(int), typeof(int), byRefInt, typeof(bool) }, (Type[])null); yield return AccessTools.Method(typeof(StorageComponent), "AddItemStacked", new Type[4] { typeof(int), typeof(int), typeof(int), byRefInt }, (Type[])null); yield return AccessTools.Method(typeof(StorageComponent), "AddItemFiltered", new Type[5] { typeof(int), typeof(int), typeof(int), byRefInt, typeof(bool) }, (Type[])null); yield return AccessTools.Method(typeof(StorageComponent), "AddItemFilteredBanOnly", new Type[4] { typeof(int), typeof(int), typeof(int), byRefInt }, (Type[])null); yield return AccessTools.Method(typeof(StorageComponent), "AddItem", new Type[6] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), byRefInt }, (Type[])null); yield return AccessTools.Method(typeof(StorageComponent), "AddItemBanGridFirst", new Type[4] { typeof(int), typeof(int), typeof(int), byRefInt }, (Type[])null); } private static IEnumerable<MethodBase> TargetMethods() { return GetTargetMethods(); } [HarmonyPrefix] private static void Prefix(StorageComponent __instance, [HarmonyArgument(0)] int itemId) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Player mainPlayer = GameMain.mainPlayer; StorageComponent val = ((mainPlayer == null) ? null : mainPlayer.mecha?.warpStorage); if (__instance == val && PrototypeRegistry.IsSupportedWarper(itemId) && __instance.grids != null && __instance.grids.Length != 0) { GRID val2 = __instance.grids[0]; if (val2.count <= 0 || val2.itemId == itemId) { __instance.SetFilterDirect(0, itemId, PrototypeRegistry.GetWarpSlotStackSize(itemId)); } } } } [HarmonyPatch] private static class PreventVanillaWarperUseDuringSystemWarpPatch { private static IEnumerable<MethodBase> TargetMethods() { yield return AccessTools.Method(typeof(Mecha), "UseWarper", Type.EmptyTypes, (Type[])null); yield return AccessTools.Method(typeof(Mecha), "AutoReplenishWarper", Type.EmptyTypes, (Type[])null); } [HarmonyPrefix] private static bool Prefix(Mecha __instance, ref bool __result) { Player mainPlayer = GameMain.mainPlayer; if (__instance != ((mainPlayer != null) ? mainPlayer.mecha : null) || (!IsPlanetaryWarperSlot(__instance.warpStorage) && !MotionController.IsAnySystemWarping() && Time.frameCount > suppressVanillaWarperThroughFrame)) { return true; } __result = false; return false; } } [HarmonyPatch(typeof(PlayerController), "GetInput")] private static class CaptureMovementInputForWarpSteeringPatch { [HarmonyPostfix] private static void Postfix(PlayerController __instance) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && ShouldCaptureSteeringInput()) { Vector4 input = __instance.input0; input.x = 0f; input.y = 0f; __instance.input0 = input; if (__instance.actionWalk != null) { __instance.actionWalk.moveVelocity = Vector3.zero; } if (__instance.actionDrift != null) { __instance.actionDrift.moveVelocity = Vector3.zero; } if (__instance.actionFly != null) { __instance.actionFly.moveVelocity = Vector3.zero; } } } } [HarmonyPatch(typeof(VFWarpEffect), "Update")] private static class WarpVisualPatch { private struct VisualState { internal bool Applied; internal VFWarpEffect Effect; internal Player OriginalPlayer; } [HarmonyPrefix] private static void Prefix(VFWarpEffect __instance, ref VisualState __state) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result