From 187bf415dc37dcbfb4f9c7747d7510018f6a3077 Mon Sep 17 00:00:00 2001 From: AnonymousStrangerOW <169866456+AnonymousStrangerOW@users.noreply.github.com> Date: Sun, 9 Feb 2025 21:08:51 -0500 Subject: [PATCH 1/2] fixes warping to other systems death bug - the player no longer violently gets hurled out of the vessel when warping to custom-made system - possible issues involving violent hurling also happening with the ship when warping into other nh systems may have been fixed as well --- .../Handlers/InvulnerabilityHandler.cs | 24 +++++++++++++++---- NewHorizons/Handlers/PlayerSpawnHandler.cs | 12 ++++++++++ NewHorizons/Handlers/VesselWarpHandler.cs | 23 ++++++++++++++++++ NewHorizons/Main.cs | 2 +- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/NewHorizons/Handlers/InvulnerabilityHandler.cs b/NewHorizons/Handlers/InvulnerabilityHandler.cs index 9aa0e793..6a9e8f1b 100644 --- a/NewHorizons/Handlers/InvulnerabilityHandler.cs +++ b/NewHorizons/Handlers/InvulnerabilityHandler.cs @@ -1,36 +1,50 @@ +using HarmonyLib; using NewHorizons.Utility.OWML; using UnityEngine; +using UnityEngine.SceneManagement; namespace NewHorizons.Handlers { + [HarmonyPatch] internal class InvulnerabilityHandler { private static float _defaultImpactDeathSpeed = -1f; + private static bool _invulnerable; public static void MakeInvulnerable(bool invulnerable) { NHLogger.Log($"Toggling immortality: {invulnerable}"); + _invulnerable = invulnerable; var deathManager = GetDeathManager(); var resources = GetPlayerResouces(); if (invulnerable) { - if (_defaultImpactDeathSpeed == -1f) - _defaultImpactDeathSpeed = deathManager._impactDeathSpeed; - - deathManager._impactDeathSpeed = Mathf.Infinity; deathManager._invincible = true; } else { - deathManager._impactDeathSpeed = _defaultImpactDeathSpeed; resources._currentHealth = 100f; deathManager._invincible = false; } } + [HarmonyPrefix] + [HarmonyPatch(typeof(DeathManager), nameof(DeathManager.KillPlayer))] + [HarmonyPatch(typeof(PlayerResources), nameof(PlayerResources.ApplyInstantDamage))] + [HarmonyPatch(typeof(PlayerImpactAudio), nameof(PlayerImpactAudio.OnImpact))] + public static bool DeathManager_KillPlayer_Prefix() + { + return !_invulnerable; + } + private static DeathManager GetDeathManager() => GameObject.FindObjectOfType(); private static PlayerResources GetPlayerResouces() => GameObject.FindObjectOfType(); + + static InvulnerabilityHandler() + { + SceneManager.sceneUnloaded += (_) => _invulnerable = false; + } } } diff --git a/NewHorizons/Handlers/PlayerSpawnHandler.cs b/NewHorizons/Handlers/PlayerSpawnHandler.cs index 352b4eff..cca2a620 100644 --- a/NewHorizons/Handlers/PlayerSpawnHandler.cs +++ b/NewHorizons/Handlers/PlayerSpawnHandler.cs @@ -70,6 +70,18 @@ namespace NewHorizons.Handlers // Spawn ship Delay.FireInNUpdates(SpawnShip, 30); + Delay.FireInNUpdates(() => + { + var spawnOWRigidBody = GetDefaultSpawn().GetAttachedOWRigidbody(); + if (shouldWarpInFromVessel) spawnOWRigidBody = VesselWarpHandler.VesselSpawnPoint.GetAttachedOWRigidbody(); + if (shouldWarpInFromShip) spawnOWRigidBody = Locator.GetShipBody(); + + var spawnVelocity = spawnOWRigidBody.GetVelocity(); + var spawnAngularVelocity = spawnOWRigidBody.GetPointTangentialVelocity(Locator.GetPlayerBody().GetPosition()); + var velocity = spawnVelocity + spawnAngularVelocity; + + Locator.GetPlayerBody().SetVelocity(velocity); + }, 31); } public static void SpawnShip() diff --git a/NewHorizons/Handlers/VesselWarpHandler.cs b/NewHorizons/Handlers/VesselWarpHandler.cs index bac8fdf7..ba7d4404 100644 --- a/NewHorizons/Handlers/VesselWarpHandler.cs +++ b/NewHorizons/Handlers/VesselWarpHandler.cs @@ -6,6 +6,7 @@ using NewHorizons.Utility; using NewHorizons.Utility.OuterWilds; using NewHorizons.Utility.OWML; using UnityEngine; +using System.Collections; using static NewHorizons.Main; namespace NewHorizons.Handlers @@ -84,6 +85,8 @@ namespace NewHorizons.Handlers { NHLogger.LogVerbose("Relative warping into vessel"); vesselSpawnPoint.WarpPlayer();//Delay.FireOnNextUpdate(vesselSpawnPoint.WarpPlayer); + //Delay.FireInNUpdates(() => InvulnerabilityHandler.MakeInvulnerable(false), 25); + Delay.StartCoroutine(RunEveryNFrames(25, vesselSpawnPoint)); } else { @@ -95,6 +98,26 @@ namespace NewHorizons.Handlers LoadDB(); } + private static IEnumerator RunEveryNFrames(int frameInterval, VesselSpawnPoint vesselSpawn) + { + int frameCount = 0; + InvulnerabilityHandler.MakeInvulnerable(true); + + while (frameCount <= frameInterval) + { + vesselSpawn.WarpPlayer(); + if (frameCount == frameInterval) + { + InvulnerabilityHandler.MakeInvulnerable(false); + var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody(); + var resources = playerBody.GetComponent(); + resources._currentHealth = 100f; + } + frameCount++; + yield return null; // Wait for the next frame + } + } + public static void LoadDB() { if (Instance.CurrentStarSystem == "SolarSystem") diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 41827310..8de703be 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -614,7 +614,7 @@ namespace NewHorizons IsSystemReady = true; // ShipWarpController will handle the invulnerability otherwise - if (!shouldWarpInFromShip) + if (!shouldWarpInFromShip && !shouldWarpInFromVessel) { Delay.FireOnNextUpdate(() => InvulnerabilityHandler.MakeInvulnerable(false)); } From ddb1d50816d9fe19501ce441a402225c33ed55cc Mon Sep 17 00:00:00 2001 From: xen-42 Date: Sun, 9 Feb 2025 23:26:16 -0500 Subject: [PATCH 2/2] Reorganize a bit and add more comments --- .../Handlers/InvulnerabilityHandler.cs | 2 ++ NewHorizons/Handlers/PlayerSpawnHandler.cs | 26 +++++++++++------- NewHorizons/Handlers/VesselWarpHandler.cs | 27 ++++++++++--------- NewHorizons/Main.cs | 2 +- 4 files changed, 34 insertions(+), 23 deletions(-) diff --git a/NewHorizons/Handlers/InvulnerabilityHandler.cs b/NewHorizons/Handlers/InvulnerabilityHandler.cs index 6a9e8f1b..e6f3777a 100644 --- a/NewHorizons/Handlers/InvulnerabilityHandler.cs +++ b/NewHorizons/Handlers/InvulnerabilityHandler.cs @@ -36,6 +36,8 @@ namespace NewHorizons.Handlers [HarmonyPatch(typeof(PlayerImpactAudio), nameof(PlayerImpactAudio.OnImpact))] public static bool DeathManager_KillPlayer_Prefix() { + // Base game _invincible is still overriden by high speed impacts + // We also are avoiding playing impact related effects by just skipping these methods return !_invulnerable; } diff --git a/NewHorizons/Handlers/PlayerSpawnHandler.cs b/NewHorizons/Handlers/PlayerSpawnHandler.cs index cca2a620..24b6d73c 100644 --- a/NewHorizons/Handlers/PlayerSpawnHandler.cs +++ b/NewHorizons/Handlers/PlayerSpawnHandler.cs @@ -70,18 +70,24 @@ namespace NewHorizons.Handlers // Spawn ship Delay.FireInNUpdates(SpawnShip, 30); - Delay.FireInNUpdates(() => - { - var spawnOWRigidBody = GetDefaultSpawn().GetAttachedOWRigidbody(); - if (shouldWarpInFromVessel) spawnOWRigidBody = VesselWarpHandler.VesselSpawnPoint.GetAttachedOWRigidbody(); - if (shouldWarpInFromShip) spawnOWRigidBody = Locator.GetShipBody(); - var spawnVelocity = spawnOWRigidBody.GetVelocity(); - var spawnAngularVelocity = spawnOWRigidBody.GetPointTangentialVelocity(Locator.GetPlayerBody().GetPosition()); - var velocity = spawnVelocity + spawnAngularVelocity; + // Have had bug reports (#1034, #975) where sometimes after spawning via vessel warp or ship warp you die from impact velocity after being flung + // Something weird must be happening with velocity. + // Try to correct it here after the ship is done spawning + Delay.FireInNUpdates(() => FixVelocity(shouldWarpInFromVessel, shouldWarpInFromShip), 31); + } - Locator.GetPlayerBody().SetVelocity(velocity); - }, 31); + private static void FixVelocity(bool shouldWarpInFromVessel, bool shouldWarpInFromShip) + { + var spawnOWRigidBody = GetDefaultSpawn().GetAttachedOWRigidbody(); + if (shouldWarpInFromVessel) spawnOWRigidBody = VesselWarpHandler.VesselSpawnPoint.GetAttachedOWRigidbody(); + if (shouldWarpInFromShip) spawnOWRigidBody = Locator.GetShipBody(); + + var spawnVelocity = spawnOWRigidBody.GetVelocity(); + var spawnAngularVelocity = spawnOWRigidBody.GetPointTangentialVelocity(Locator.GetPlayerBody().GetPosition()); + var velocity = spawnVelocity + spawnAngularVelocity; + + Locator.GetPlayerBody().SetVelocity(velocity); } public static void SpawnShip() diff --git a/NewHorizons/Handlers/VesselWarpHandler.cs b/NewHorizons/Handlers/VesselWarpHandler.cs index ba7d4404..25aac76b 100644 --- a/NewHorizons/Handlers/VesselWarpHandler.cs +++ b/NewHorizons/Handlers/VesselWarpHandler.cs @@ -56,7 +56,9 @@ namespace NewHorizons.Handlers } if (IsVesselPresentAndActive()) + { _vesselSpawnPoint = Instance.CurrentStarSystem == "SolarSystem" ? UpdateVessel() : CreateVessel(); + } else { var vesselDimension = SearchUtilities.Find("DB_VesselDimension_Body/Sector_VesselDimension"); @@ -84,9 +86,12 @@ namespace NewHorizons.Handlers if (_vesselSpawnPoint is VesselSpawnPoint vesselSpawnPoint) { NHLogger.LogVerbose("Relative warping into vessel"); - vesselSpawnPoint.WarpPlayer();//Delay.FireOnNextUpdate(vesselSpawnPoint.WarpPlayer); - //Delay.FireInNUpdates(() => InvulnerabilityHandler.MakeInvulnerable(false), 25); - Delay.StartCoroutine(RunEveryNFrames(25, vesselSpawnPoint)); + vesselSpawnPoint.WarpPlayer(); + + // #1034 Vessel warp sometimes has the player get flung away into space and die + // We do what we do with regular spawns where we keep resetting their position to the right one while invincible until we're relatively certain + // that the spawning sequence is done + Delay.StartCoroutine(FixPlayerSpawning(25, vesselSpawnPoint)); } else { @@ -98,24 +103,22 @@ namespace NewHorizons.Handlers LoadDB(); } - private static IEnumerator RunEveryNFrames(int frameInterval, VesselSpawnPoint vesselSpawn) + private static IEnumerator FixPlayerSpawning(int frameInterval, VesselSpawnPoint vesselSpawn) { - int frameCount = 0; InvulnerabilityHandler.MakeInvulnerable(true); + var frameCount = 0; while (frameCount <= frameInterval) { vesselSpawn.WarpPlayer(); - if (frameCount == frameInterval) - { - InvulnerabilityHandler.MakeInvulnerable(false); - var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody(); - var resources = playerBody.GetComponent(); - resources._currentHealth = 100f; - } frameCount++; yield return null; // Wait for the next frame } + + InvulnerabilityHandler.MakeInvulnerable(false); + var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody(); + var resources = playerBody.GetComponent(); + resources._currentHealth = 100f; } public static void LoadDB() diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 8de703be..995f46c5 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -613,7 +613,7 @@ namespace NewHorizons { IsSystemReady = true; - // ShipWarpController will handle the invulnerability otherwise + // ShipWarpController or VesselWarpHandler will handle the invulnerability otherwise if (!shouldWarpInFromShip && !shouldWarpInFromVessel) { Delay.FireOnNextUpdate(() => InvulnerabilityHandler.MakeInvulnerable(false));