fix bugs for ship and vessel spawns (#1036)

## Bug fixes

- fixes
https://github.com/Outer-Wilds-New-Horizons/new-horizons/issues/1034
- might also fix
https://github.com/Outer-Wilds-New-Horizons/new-horizons/issues/975 but
i couldn't reproduce the issue to be sure.
This commit is contained in:
xen-42 2025-02-09 23:26:53 -05:00 committed by GitHub
commit 0706b901cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 68 additions and 8 deletions

View File

@ -1,36 +1,52 @@
using HarmonyLib;
using NewHorizons.Utility.OWML; using NewHorizons.Utility.OWML;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement;
namespace NewHorizons.Handlers namespace NewHorizons.Handlers
{ {
[HarmonyPatch]
internal class InvulnerabilityHandler internal class InvulnerabilityHandler
{ {
private static float _defaultImpactDeathSpeed = -1f; private static float _defaultImpactDeathSpeed = -1f;
private static bool _invulnerable;
public static void MakeInvulnerable(bool invulnerable) public static void MakeInvulnerable(bool invulnerable)
{ {
NHLogger.Log($"Toggling immortality: {invulnerable}"); NHLogger.Log($"Toggling immortality: {invulnerable}");
_invulnerable = invulnerable;
var deathManager = GetDeathManager(); var deathManager = GetDeathManager();
var resources = GetPlayerResouces(); var resources = GetPlayerResouces();
if (invulnerable) if (invulnerable)
{ {
if (_defaultImpactDeathSpeed == -1f)
_defaultImpactDeathSpeed = deathManager._impactDeathSpeed;
deathManager._impactDeathSpeed = Mathf.Infinity;
deathManager._invincible = true; deathManager._invincible = true;
} }
else else
{ {
deathManager._impactDeathSpeed = _defaultImpactDeathSpeed;
resources._currentHealth = 100f; resources._currentHealth = 100f;
deathManager._invincible = false; 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()
{
// 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;
}
private static DeathManager GetDeathManager() => GameObject.FindObjectOfType<DeathManager>(); private static DeathManager GetDeathManager() => GameObject.FindObjectOfType<DeathManager>();
private static PlayerResources GetPlayerResouces() => GameObject.FindObjectOfType<PlayerResources>(); private static PlayerResources GetPlayerResouces() => GameObject.FindObjectOfType<PlayerResources>();
static InvulnerabilityHandler()
{
SceneManager.sceneUnloaded += (_) => _invulnerable = false;
}
} }
} }

View File

@ -70,6 +70,24 @@ namespace NewHorizons.Handlers
// Spawn ship // Spawn ship
Delay.FireInNUpdates(SpawnShip, 30); Delay.FireInNUpdates(SpawnShip, 30);
// 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);
}
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() public static void SpawnShip()

View File

@ -6,6 +6,7 @@ using NewHorizons.Utility;
using NewHorizons.Utility.OuterWilds; using NewHorizons.Utility.OuterWilds;
using NewHorizons.Utility.OWML; using NewHorizons.Utility.OWML;
using UnityEngine; using UnityEngine;
using System.Collections;
using static NewHorizons.Main; using static NewHorizons.Main;
using static NewHorizons.Utility.Files.AssetBundleUtilities; using static NewHorizons.Utility.Files.AssetBundleUtilities;
@ -56,7 +57,9 @@ namespace NewHorizons.Handlers
} }
if (IsVesselPresentAndActive()) if (IsVesselPresentAndActive())
{
_vesselSpawnPoint = Instance.CurrentStarSystem == "SolarSystem" ? UpdateVessel() : CreateVessel(); _vesselSpawnPoint = Instance.CurrentStarSystem == "SolarSystem" ? UpdateVessel() : CreateVessel();
}
else else
{ {
var vesselDimension = SearchUtilities.Find("DB_VesselDimension_Body/Sector_VesselDimension"); var vesselDimension = SearchUtilities.Find("DB_VesselDimension_Body/Sector_VesselDimension");
@ -84,7 +87,12 @@ namespace NewHorizons.Handlers
if (_vesselSpawnPoint is VesselSpawnPoint vesselSpawnPoint) if (_vesselSpawnPoint is VesselSpawnPoint vesselSpawnPoint)
{ {
NHLogger.LogVerbose("Relative warping into vessel"); NHLogger.LogVerbose("Relative warping into vessel");
vesselSpawnPoint.WarpPlayer();//Delay.FireOnNextUpdate(vesselSpawnPoint.WarpPlayer); 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 else
{ {
@ -96,6 +104,24 @@ namespace NewHorizons.Handlers
LoadDB(); LoadDB();
} }
private static IEnumerator FixPlayerSpawning(int frameInterval, VesselSpawnPoint vesselSpawn)
{
InvulnerabilityHandler.MakeInvulnerable(true);
var frameCount = 0;
while (frameCount <= frameInterval)
{
vesselSpawn.WarpPlayer();
frameCount++;
yield return null; // Wait for the next frame
}
InvulnerabilityHandler.MakeInvulnerable(false);
var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody();
var resources = playerBody.GetComponent<PlayerResources>();
resources._currentHealth = 100f;
}
public static void LoadDB() public static void LoadDB()
{ {
if (Instance.CurrentStarSystem == "SolarSystem") if (Instance.CurrentStarSystem == "SolarSystem")

View File

@ -601,8 +601,8 @@ namespace NewHorizons
{ {
IsSystemReady = true; IsSystemReady = true;
// ShipWarpController will handle the invulnerability otherwise // ShipWarpController or VesselWarpHandler will handle the invulnerability otherwise
if (!shouldWarpInFromShip) if (!shouldWarpInFromShip && !shouldWarpInFromVessel)
{ {
Delay.FireOnNextUpdate(() => InvulnerabilityHandler.MakeInvulnerable(false)); Delay.FireOnNextUpdate(() => InvulnerabilityHandler.MakeInvulnerable(false));
} }