using NewHorizons.Utility; using NewHorizons.Utility.OWML; using System; using System.Collections; using UnityEngine; namespace NewHorizons.Handlers { public static class PlayerSpawnHandler { private static bool _wasInvincible; private static bool _wasDeathManagerInvincible; private static float _impactDeathSpeed; public static void SetUpPlayerSpawn() { var spawnPoint = Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint; if (spawnPoint != null) { SearchUtilities.Find("Player_Body").GetComponent().SetBodyToMatch(spawnPoint.GetAttachedOWRigidbody()); GetPlayerSpawner().SetInitialSpawnPoint(spawnPoint); } else { NHLogger.Log($"No NH spawn point for {Main.Instance.CurrentStarSystem}"); } } public static void OnSystemReady(bool shouldWarpInFromShip, bool shouldWarpInFromVessel) { NHLogger.Log($"OnSystemReady {shouldWarpInFromVessel}, {shouldWarpInFromShip}, {UsingCustomSpawn()}"); if (shouldWarpInFromShip) { Main.Instance.ShipWarpController.WarpIn(Main.Instance.WearingSuit); } else if (shouldWarpInFromVessel) { VesselWarpHandler.TeleportToVessel(); } else if (UsingCustomSpawn()) { InvulnerabilityHandler.MakeInvulnerable(true); var player = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody(); var spawn = GetDefaultSpawn(); // Idk why but these just don't work? var matchInitialMotion = player.GetComponent(); if (matchInitialMotion != null) UnityEngine.Object.Destroy(matchInitialMotion); Main.Instance.StartCoroutine(SpawnCoroutine(player, spawn, 5)); } } private static IEnumerator SpawnCoroutine(OWRigidbody playerBody, SpawnPoint spawn, int length) { for(int i = 0; i < length; i++) { playerBody.WarpToPositionRotation(spawn.transform.position, spawn.transform.rotation); FixVelocity(); yield return new WaitForEndOfFrame(); } InvulnerabilityHandler.MakeInvulnerable(false); } private static void FixVelocity() { var player = SearchUtilities.Find("Player_Body"); var playerBody = player.GetAttachedOWRigidbody(); var spawn = GetDefaultSpawn(); playerBody.WarpToPositionRotation(spawn.transform.position, spawn.transform.rotation); // Player dies during the teleport sometimes so we prevent that var resources = player.GetComponent(); var deathManager = Locator.GetDeathManager(); var spawnVelocity = spawn._attachedBody.GetVelocity(); var spawnAngularVelocity = spawn._attachedBody.GetPointTangentialVelocity(playerBody.transform.position); var velocity = spawnVelocity + spawnAngularVelocity; playerBody.SetVelocity(velocity); NHLogger.LogVerbose($"Player spawn velocity {velocity} Player velocity {playerBody.GetVelocity()} spawn body {spawnVelocity} spawn angular vel {spawnAngularVelocity}"); resources._currentHealth = 100f; resources._invincible = _wasInvincible; deathManager._invincible = _wasDeathManagerInvincible; deathManager._impactDeathSpeed = _impactDeathSpeed; } private static Vector3 CalculateMatchVelocity(OWRigidbody owRigidbody, OWRigidbody bodyToMatch, bool ignoreAngularVelocity) { var vector = Vector3.zero; owRigidbody.UpdateCenterOfMass(); vector += bodyToMatch.GetVelocity(); if (!ignoreAngularVelocity) { var worldCenterOfMass = owRigidbody.GetWorldCenterOfMass(); var worldCenterOfMass2 = bodyToMatch.GetWorldCenterOfMass(); var initAngularVelocity = bodyToMatch.GetAngularVelocity(); vector += OWPhysics.PointTangentialVelocity(worldCenterOfMass, worldCenterOfMass2, initAngularVelocity); } var aoPrimary = bodyToMatch.GetComponent()?._primaryBody?.GetAttachedOWRigidbody(); // Stock sun has its primary as itself for some reason if (aoPrimary != null && aoPrimary != bodyToMatch) { vector += CalculateMatchVelocity(bodyToMatch, aoPrimary, true); } return vector; } public static bool UsingCustomSpawn() => Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint != null; public static PlayerSpawner GetPlayerSpawner() => GameObject.FindObjectOfType(); public static SpawnPoint GetDefaultSpawn() => Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint ?? GetPlayerSpawner().GetSpawnPoint(SpawnLocation.TimberHearth); } }