mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
1.12.1 (#620)
## Minor features - Starting popups can be shown multiple times using `repeatPopup` in the addon-manifest file #621 ## Improvements - Can now use `pathToAnimController` on a character dialogue to link it to a Hearthian recorder so that it's visual effects will be triggered during the dialogue (resolves #520) - Can now change the spawn point within the base game Hearthian system (resolves #567) - Added a 5 second delay to warp transmitters after you come back through the return pad. Means 360 degree alignment target actually works when returning through it instead of sending you straight back. (resolves #563) - Only signal frequencies in use by the current system will be shown. (resolves #572) ## Bug fixes - Fixed spawning on tidally locked planets (resolves #505) - Fixed vanilla objects being given labels (OPC, QM, SS) #623 - Fixed solar flare tint not matching star colour #616
This commit is contained in:
commit
45e52be73b
@ -58,7 +58,7 @@ namespace NewHorizons.Builder.Body
|
||||
if (_flareMaterial == null)
|
||||
{
|
||||
_flareMaterial = new Material(_starSolarFlareEmitter.GetComponentInChildren<SolarFlareController>().GetComponent<MeshRenderer>().sharedMaterial).DontDestroyOnLoad();
|
||||
_flareMaterial.color = Color.white;
|
||||
_flareMaterial.SetColor(Shader.PropertyToID("_Color"), Color.white);
|
||||
}
|
||||
}
|
||||
|
||||
@ -353,9 +353,13 @@ namespace NewHorizons.Builder.Body
|
||||
var flareTint = starModule.tint.ToColor();
|
||||
var emitter = solarFlareEmitter.GetComponent<SolarFlareEmitter>();
|
||||
emitter.tint = flareTint;
|
||||
|
||||
var material = new Material(_flareMaterial);
|
||||
foreach (var controller in solarFlareEmitter.GetComponentsInChildren<SolarFlareController>())
|
||||
// Since the star isn't awake yet the controllers haven't been made
|
||||
foreach (var prefab in new GameObject[] { emitter.domePrefab, emitter.loopPrefab, emitter.streamerPrefab })
|
||||
{
|
||||
var controller = prefab.GetComponent<SolarFlareController>();
|
||||
// controller._meshRenderer doesn't exist yet since Awake hasn't been called
|
||||
controller.GetComponent<MeshRenderer>().sharedMaterial = material;
|
||||
controller._color = Color.white;
|
||||
controller._tint = flareTint;
|
||||
|
||||
@ -7,9 +7,10 @@ namespace NewHorizons.Builder.General
|
||||
{
|
||||
public static class AstroObjectBuilder
|
||||
{
|
||||
public static NHAstroObject Make(GameObject body, AstroObject primaryBody, PlanetConfig config)
|
||||
public static NHAstroObject Make(GameObject body, AstroObject primaryBody, PlanetConfig config, bool isVanilla)
|
||||
{
|
||||
NHAstroObject astroObject = body.AddComponent<NHAstroObject>();
|
||||
astroObject.isVanilla = isVanilla;
|
||||
astroObject.HideDisplayName = !config.Base.hasMapMarker;
|
||||
astroObject.invulnerableToSun = config.Base.invulnerableToSun;
|
||||
|
||||
@ -48,8 +49,9 @@ namespace NewHorizons.Builder.General
|
||||
alignment._localAlignmentAxis = alignmentAxis;
|
||||
|
||||
// Static bodies won't update rotation with physics for some reason
|
||||
// Have to set it next tick else it flings the player into deep space on spawn (#171)
|
||||
if (!config.Orbit.isStatic) Delay.FireOnNextUpdate(() => alignment._usePhysicsToRotate = true);
|
||||
// Have to set it in 2 ticks else it flings the player into deep space on spawn (#171)
|
||||
// Pushed to 3 frames after system is ready, bc spawning takes 2 frames, this is hurting my brain too much to try to improve the numbers idc
|
||||
if (!config.Orbit.isStatic) Delay.RunWhen(() => Main.IsSystemReady, () => Delay.FireInNUpdates(() => alignment._usePhysicsToRotate = true, 3));
|
||||
}
|
||||
|
||||
if (config.Base.centerOfSolarSystem)
|
||||
|
||||
@ -6,6 +6,7 @@ using NewHorizons.Utility.OuterWilds;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Steamworks;
|
||||
|
||||
namespace NewHorizons.Builder.General
|
||||
{
|
||||
@ -16,25 +17,39 @@ namespace NewHorizons.Builder.General
|
||||
{
|
||||
SpawnPoint playerSpawn = null;
|
||||
|
||||
if (!Main.Instance.IsWarpingFromVessel && !Main.Instance.IsWarpingFromShip && module.playerSpawn != null)
|
||||
// Make the spawn point even if it won't be used this loop
|
||||
if (module.playerSpawn != null)
|
||||
{
|
||||
GameObject spawnGO = GeneralPropBuilder.MakeNew("PlayerSpawnPoint", planetGO, null, module.playerSpawn);
|
||||
spawnGO.SetActive(false);
|
||||
spawnGO.layer = Layer.PlayerSafetyCollider;
|
||||
|
||||
playerSpawn = spawnGO.AddComponent<SpawnPoint>();
|
||||
playerSpawn._attachedBody = owRigidBody;
|
||||
playerSpawn._spawnLocation = SpawnLocation.None;
|
||||
// #601 we need to actually set the right trigger volumes here
|
||||
playerSpawn._triggerVolumes = new OWTriggerVolume[0];
|
||||
|
||||
spawnGO.transform.position += spawnGO.transform.up * 4f;
|
||||
// This was a stupid hack to stop players getting stuck in the ground and now we have to keep it forever
|
||||
spawnGO.transform.position += 4f * spawnGO.transform.up;
|
||||
spawnGO.SetActive(true);
|
||||
}
|
||||
|
||||
if (module.shipSpawn != null)
|
||||
{
|
||||
GameObject spawnGO = GeneralPropBuilder.MakeNew("ShipSpawnPoint", planetGO, null, module.shipSpawn);
|
||||
spawnGO.SetActive(false);
|
||||
spawnGO.layer = Layer.PlayerSafetyCollider;
|
||||
|
||||
var spawnPoint = spawnGO.AddComponent<SpawnPoint>();
|
||||
spawnPoint._isShipSpawn = true;
|
||||
spawnPoint._triggerVolumes = new OWTriggerVolume[0];
|
||||
var shipSpawn = spawnGO.AddComponent<SpawnPoint>();
|
||||
shipSpawn._isShipSpawn = true;
|
||||
shipSpawn._attachedBody = owRigidBody;
|
||||
shipSpawn._spawnLocation = SpawnLocation.None;
|
||||
|
||||
// #601 we need to actually set the right trigger volumes here
|
||||
shipSpawn._triggerVolumes = new OWTriggerVolume[0];
|
||||
|
||||
// TODO: this should happen elsewhere
|
||||
var ship = SearchUtilities.Find("Ship_Body");
|
||||
if (ship != null)
|
||||
{
|
||||
@ -48,27 +63,14 @@ namespace NewHorizons.Builder.General
|
||||
}
|
||||
|
||||
ship.GetRequiredComponent<MatchInitialMotion>().SetBodyToMatch(owRigidBody);
|
||||
|
||||
if (Main.Instance.IsWarpingFromShip)
|
||||
{
|
||||
NHLogger.LogVerbose("Overriding player spawn to be inside ship");
|
||||
GameObject playerSpawnGO = new GameObject("PlayerSpawnPoint");
|
||||
playerSpawnGO.transform.parent = ship.transform;
|
||||
playerSpawnGO.layer = Layer.PlayerSafetyCollider;
|
||||
|
||||
playerSpawnGO.transform.localPosition = new Vector3(0, 0, 0);
|
||||
|
||||
playerSpawn = playerSpawnGO.AddComponent<SpawnPoint>();
|
||||
playerSpawn._triggerVolumes = new OWTriggerVolume[0];
|
||||
playerSpawnGO.transform.localRotation = Quaternion.Euler(0, 0, 0);
|
||||
}
|
||||
}
|
||||
spawnGO.SetActive(true);
|
||||
}
|
||||
|
||||
if ((Main.Instance.IsWarpingFromVessel || (!Main.Instance.IsWarpingFromShip && (module.playerSpawn?.startWithSuit ?? false))) && !suitUpQueued)
|
||||
{
|
||||
suitUpQueued = true;
|
||||
Delay.RunWhen(() => Main.IsSystemReady, () => SuitUp());
|
||||
Delay.RunWhen(() => Main.IsSystemReady, SuitUp);
|
||||
}
|
||||
|
||||
NHLogger.Log($"Made spawnpoint on [{planetGO.name}]");
|
||||
|
||||
@ -1,14 +1,13 @@
|
||||
using NewHorizons.External.Modules;
|
||||
using HarmonyLib;
|
||||
using NewHorizons.External.Modules.Props.Audio;
|
||||
using NewHorizons.Utility;
|
||||
using NewHorizons.Utility.Files;
|
||||
using NewHorizons.Utility.OWML;
|
||||
using NewHorizons.Utility.OuterWilds;
|
||||
using OWML.Common;
|
||||
using OWML.Utils;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using NewHorizons.External.Modules.Props.Audio;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace NewHorizons.Builder.Props.Audio
|
||||
{
|
||||
@ -20,8 +19,8 @@ namespace NewHorizons.Builder.Props.Audio
|
||||
|
||||
public static int NumberOfFrequencies;
|
||||
|
||||
private static List<AudioSignal> _qmSignals;
|
||||
private static List<AudioSignal> _cloakedSignals;
|
||||
private static HashSet<AudioSignal> _qmSignals;
|
||||
private static HashSet<AudioSignal> _cloakedSignals;
|
||||
|
||||
public static bool Initialized;
|
||||
|
||||
@ -36,22 +35,46 @@ namespace NewHorizons.Builder.Props.Audio
|
||||
};
|
||||
NumberOfFrequencies = EnumUtils.GetValues<SignalFrequency>().Length;
|
||||
|
||||
_qmSignals = new List<AudioSignal>() { SearchUtilities.Find("QuantumMoon_Body/Signal_Quantum").GetComponent<AudioSignal>() };
|
||||
_cloakedSignals = new List<AudioSignal>();
|
||||
_qmSignals = new (){ SearchUtilities.Find("QuantumMoon_Body/Signal_Quantum").GetComponent<AudioSignal>() };
|
||||
_cloakedSignals = new();
|
||||
|
||||
Initialized = true;
|
||||
|
||||
SceneManager.sceneUnloaded += OnSceneUnloaded;
|
||||
Main.Instance.OnStarSystemLoaded.AddListener(OnStarSystemLoaded);
|
||||
}
|
||||
|
||||
public static bool IsCloaked(this AudioSignal signal)
|
||||
private static HashSet<SignalFrequency> _frequenciesInUse = new();
|
||||
|
||||
private static void OnSceneUnloaded(Scene _)
|
||||
{
|
||||
return _cloakedSignals.Contains(signal);
|
||||
_frequenciesInUse.Clear();
|
||||
}
|
||||
|
||||
public static bool IsOnQuantumMoon(this AudioSignal signal)
|
||||
private static void OnStarSystemLoaded(string starSystem)
|
||||
{
|
||||
return _qmSignals.Contains(signal);
|
||||
// If its the base game solar system or eye we get all the main frequencies
|
||||
if (starSystem == "SolarSystem" || starSystem == "EyeOfTheUniverse")
|
||||
{
|
||||
_frequenciesInUse.Add(SignalFrequency.Quantum);
|
||||
_frequenciesInUse.Add(SignalFrequency.EscapePod);
|
||||
_frequenciesInUse.Add(SignalFrequency.Radio);
|
||||
_frequenciesInUse.Add(SignalFrequency.HideAndSeek);
|
||||
}
|
||||
|
||||
// Always show the traveler frequency. The signalscope defaults to this on spawn, and is the only frequency known by default
|
||||
// We don't want a scenario where the player knows no frequencies
|
||||
_frequenciesInUse.Add(SignalFrequency.Traveler);
|
||||
|
||||
NHLogger.LogVerbose($"Frequencies in use in {starSystem}: {_frequenciesInUse.Join(x => x.ToString())}");
|
||||
}
|
||||
|
||||
public static bool IsFrequencyInUse(SignalFrequency freq) => _frequenciesInUse.Contains(freq);
|
||||
|
||||
public static bool IsCloaked(this AudioSignal signal) => _cloakedSignals.Contains(signal);
|
||||
|
||||
public static bool IsOnQuantumMoon(this AudioSignal signal) => _qmSignals.Contains(signal);
|
||||
|
||||
public static SignalFrequency AddFrequency(string str)
|
||||
{
|
||||
if (_customFrequencyNames == null) Init();
|
||||
@ -153,6 +176,8 @@ namespace NewHorizons.Builder.Props.Audio
|
||||
if (planetGO.GetComponent<AstroObject>()?.GetAstroObjectName() == AstroObject.Name.QuantumMoon) _qmSignals.Add(audioSignal);
|
||||
if (info.insideCloak) _cloakedSignals.Add(audioSignal);
|
||||
|
||||
_frequenciesInUse.Add(frequency);
|
||||
|
||||
return signalGO;
|
||||
}
|
||||
|
||||
|
||||
@ -147,6 +147,7 @@ namespace NewHorizons.Builder.Props
|
||||
var controller = character.GetComponent<CharacterAnimController>();
|
||||
var traveler = character.GetComponent<TravelerController>();
|
||||
var travelerEye = character.GetComponent<TravelerEyeController>();
|
||||
var hearthianRecorder = character.GetComponent<HearthianRecorderEffects>();
|
||||
|
||||
var lookOnlyWhenTalking = info.lookAtRadius <= 0;
|
||||
|
||||
@ -196,6 +197,34 @@ namespace NewHorizons.Builder.Props
|
||||
dialogue.OnEndConversation += nomaiController.StopWatchingPlayer;
|
||||
}
|
||||
}
|
||||
else if (hearthianRecorder != null)
|
||||
{
|
||||
Delay.FireOnNextUpdate(() =>
|
||||
{
|
||||
// #520
|
||||
if (hearthianRecorder._characterDialogueTree != null)
|
||||
{
|
||||
hearthianRecorder._characterDialogueTree.OnStartConversation -= hearthianRecorder.OnPlayRecorder;
|
||||
hearthianRecorder._characterDialogueTree.OnEndConversation -= hearthianRecorder.OnStopRecorder;
|
||||
}
|
||||
|
||||
// Recorder props have their own dialogue on them already
|
||||
// Make sure to delete it when we're trying to connect new dialogue to it
|
||||
var existingDialogue = hearthianRecorder.GetComponent<CharacterDialogueTree>();
|
||||
if (existingDialogue != dialogue && existingDialogue != null)
|
||||
{
|
||||
// Can't delete the existing dialogue because its a required component but we can make it unable to select at least
|
||||
GameObject.Destroy(hearthianRecorder.GetComponent<OWCollider>());
|
||||
GameObject.Destroy(hearthianRecorder.GetComponent<SphereCollider>());
|
||||
GameObject.Destroy(existingDialogue._interactVolume);
|
||||
existingDialogue.enabled = false;
|
||||
}
|
||||
|
||||
hearthianRecorder._characterDialogueTree = dialogue;
|
||||
hearthianRecorder._characterDialogueTree.OnStartConversation += hearthianRecorder.OnPlayRecorder;
|
||||
hearthianRecorder._characterDialogueTree.OnEndConversation += hearthianRecorder.OnStopRecorder;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// If they have nothing else just put the face player when talking thing on them
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
using NewHorizons.Builder.Props.TranslatorText;
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.External.Modules.Props;
|
||||
using NewHorizons.External.Modules.WarpPad;
|
||||
using NewHorizons.Utility;
|
||||
@ -137,6 +138,9 @@ namespace NewHorizons.Builder.Props
|
||||
|
||||
transmitter.GetComponent<BoxShape>().enabled = true;
|
||||
|
||||
// Prevents the transmitter from sending you straight back if you use the return function of the receiver #563
|
||||
transmitterObject.AddComponent<NomaiWarpTransmitterCooldown>();
|
||||
|
||||
transmitterObject.SetActive(true);
|
||||
}
|
||||
|
||||
|
||||
45
NewHorizons/Components/NomaiWarpTransmitterCooldown.cs
Normal file
45
NewHorizons/Components/NomaiWarpTransmitterCooldown.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Components
|
||||
{
|
||||
public class NomaiWarpTransmitterCooldown : MonoBehaviour
|
||||
{
|
||||
private NomaiWarpTransmitter _transmitter;
|
||||
private NomaiWarpReceiver _receiver;
|
||||
|
||||
private float _reenabledTime = 0f;
|
||||
private bool _cooldownActive;
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_transmitter = GetComponent<NomaiWarpTransmitter>();
|
||||
_transmitter.OnReceiveWarpedBody += _transmitter_OnReceiveWarpedBody;
|
||||
}
|
||||
|
||||
public void OnDestroy()
|
||||
{
|
||||
if (_transmitter != null)
|
||||
{
|
||||
_transmitter.OnReceiveWarpedBody -= _transmitter_OnReceiveWarpedBody;
|
||||
}
|
||||
}
|
||||
|
||||
private void _transmitter_OnReceiveWarpedBody(OWRigidbody warpedBody, NomaiWarpPlatform startPlatform, NomaiWarpPlatform targetPlatform)
|
||||
{
|
||||
_cooldownActive = true;
|
||||
|
||||
_reenabledTime = Time.time + 5f;
|
||||
_receiver = _transmitter._targetReceiver;
|
||||
_transmitter._targetReceiver = null;
|
||||
}
|
||||
|
||||
public void FixedUpdate()
|
||||
{
|
||||
if (_cooldownActive && Time.time > _reenabledTime)
|
||||
{
|
||||
_cooldownActive = false;
|
||||
_transmitter._targetReceiver = _receiver;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -12,6 +12,7 @@ namespace NewHorizons.Components.Orbital
|
||||
public bool HideDisplayName { get; set; }
|
||||
public bool IsDimension { get; set; }
|
||||
public bool invulnerableToSun;
|
||||
public bool isVanilla;
|
||||
|
||||
public void SetOrbitalParametersFromConfig(OrbitModule orbit)
|
||||
{
|
||||
|
||||
@ -134,7 +134,7 @@ namespace NewHorizons.Components.Ship
|
||||
{
|
||||
if (_isWarpingIn && LateInitializerManager.isDoneInitializing)
|
||||
{
|
||||
Delay.FireInNUpdates(() => StartWarpInEffect(), 1);
|
||||
Delay.FireOnNextUpdate(StartWarpInEffect);
|
||||
_isWarpingIn = false;
|
||||
}
|
||||
|
||||
@ -167,7 +167,7 @@ namespace NewHorizons.Components.Ship
|
||||
NHLogger.LogVerbose("Starting warp-in effect");
|
||||
_oneShotSource.PlayOneShot(AudioType.VesselSingularityCollapse, 1f);
|
||||
Locator.GetDeathManager()._invincible = true;
|
||||
if (Main.Instance.CurrentStarSystem.Equals("SolarSystem")) TeleportToShip();
|
||||
TeleportToShip();
|
||||
_whitehole.Create();
|
||||
_waitingToBeSeated = true;
|
||||
if (_wearingSuit && !Locator.GetPlayerController()._isWearingSuit)
|
||||
@ -179,6 +179,7 @@ namespace NewHorizons.Components.Ship
|
||||
private void TeleportToShip()
|
||||
{
|
||||
var playerSpawner = FindObjectOfType<PlayerSpawner>();
|
||||
NHLogger.LogVerbose("Debug warping into ship");
|
||||
playerSpawner.DebugWarp(playerSpawner.GetSpawnPoint(SpawnLocation.Ship));
|
||||
}
|
||||
|
||||
|
||||
@ -252,7 +252,10 @@ namespace NewHorizons.Components.SizeControllers
|
||||
_surface._materials[0].SetFloat(ColorTime, 0);
|
||||
}
|
||||
|
||||
if (_flareEmitter != null) _flareEmitter._tint = _currentColour;
|
||||
if (_flareEmitter != null)
|
||||
{
|
||||
_flareEmitter.tint = _currentColour;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCollapse()
|
||||
|
||||
5
NewHorizons/External/Configs/AddonConfig.cs
vendored
5
NewHorizons/External/Configs/AddonConfig.cs
vendored
@ -26,5 +26,10 @@ namespace NewHorizons.External.Configs
|
||||
/// A pop-up message for the first time a user runs the add-on
|
||||
/// </summary>
|
||||
public string popupMessage;
|
||||
|
||||
/// <summary>
|
||||
/// If popupMessage is set, should it repeat every time the game starts or only once
|
||||
/// </summary>
|
||||
public bool repeatPopup;
|
||||
}
|
||||
}
|
||||
|
||||
@ -22,7 +22,10 @@ namespace NewHorizons.External.Modules.Props.Dialogue
|
||||
|
||||
/// <summary>
|
||||
/// If this dialogue is meant for a character, this is the relative path from the planet to that character's
|
||||
/// CharacterAnimController, TravelerController, TravelerEyeController (eye of the universe), FacePlayerWhenTalking, or SolanumAnimController.
|
||||
/// CharacterAnimController, TravelerController, TravelerEyeController (eye of the universe), FacePlayerWhenTalking,
|
||||
/// HearthianRecorderEffects or SolanumAnimController.
|
||||
///
|
||||
/// If it's a Recorder this will also delete the existing dialogue already attached to that prop.
|
||||
///
|
||||
/// If none of those components are present it will add a FacePlayerWhenTalking component.
|
||||
/// </summary>
|
||||
|
||||
@ -6,7 +6,7 @@ namespace NewHorizons.External.Modules.VariableSize
|
||||
public class VariableSizeModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Scale this object over time
|
||||
/// Scale this object over time. Time value is in minutes.
|
||||
/// </summary>
|
||||
public TimeValuePair[] curve;
|
||||
}
|
||||
|
||||
@ -343,7 +343,7 @@ namespace NewHorizons.Handlers
|
||||
body.Config.Base.hasMapMarker = false;
|
||||
|
||||
var owRigidBody = RigidBodyBuilder.Make(go, body.Config);
|
||||
var ao = AstroObjectBuilder.Make(go, null, body.Config);
|
||||
var ao = AstroObjectBuilder.Make(go, null, body.Config, false);
|
||||
|
||||
var sector = SectorBuilder.Make(go, owRigidBody, 2000f);
|
||||
ao._rootSector = sector;
|
||||
@ -409,7 +409,7 @@ namespace NewHorizons.Handlers
|
||||
}
|
||||
|
||||
var owRigidBody = RigidBodyBuilder.Make(go, body.Config);
|
||||
var ao = AstroObjectBuilder.Make(go, primaryBody, body.Config);
|
||||
var ao = AstroObjectBuilder.Make(go, primaryBody, body.Config, false);
|
||||
|
||||
var sphereOfInfluence = GetSphereOfInfluence(body);
|
||||
|
||||
@ -456,9 +456,12 @@ namespace NewHorizons.Handlers
|
||||
// Spawning on other planets is a bit hacky so we do it last
|
||||
if (body.Config.Spawn != null)
|
||||
{
|
||||
NHLogger.LogVerbose("Making spawn point");
|
||||
NHLogger.LogVerbose($"Making spawn point on {body.Config.name}");
|
||||
var spawnPoint = SpawnPointBuilder.Make(go, body.Config.Spawn, owRigidBody);
|
||||
if (Main.SystemDict[body.Config.starSystem].SpawnPoint == null || (body.Config.Spawn.playerSpawn?.isDefault ?? false))
|
||||
var isVanillaSystem = body.Config.starSystem == "SolarSystem" || body.Config.starSystem == "EyeOfTheUniverse";
|
||||
var needsSpawnPoint = Main.SystemDict[body.Config.starSystem].SpawnPoint == null || isVanillaSystem;
|
||||
var isDefaultSpawn = body.Config.Spawn.playerSpawn?.isDefault ?? true; // Backwards compat
|
||||
if (needsSpawnPoint || isDefaultSpawn)
|
||||
{
|
||||
Main.SystemDict[body.Config.starSystem].SpawnPoint = spawnPoint;
|
||||
}
|
||||
@ -702,7 +705,7 @@ namespace NewHorizons.Handlers
|
||||
}
|
||||
|
||||
// Just destroy the existing AO after copying everything over
|
||||
var newAO = AstroObjectBuilder.Make(go, primary, body.Config);
|
||||
var newAO = AstroObjectBuilder.Make(go, primary, body.Config, true);
|
||||
newAO._gravityVolume = ao._gravityVolume;
|
||||
newAO._moon = ao._moon;
|
||||
newAO._name = ao._name;
|
||||
|
||||
128
NewHorizons/Handlers/PlayerSpawnHandler.cs
Normal file
128
NewHorizons/Handlers/PlayerSpawnHandler.cs
Normal file
@ -0,0 +1,128 @@
|
||||
using NewHorizons.Utility;
|
||||
using NewHorizons.Utility.OWML;
|
||||
using System;
|
||||
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<MatchInitialMotion>().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)
|
||||
{
|
||||
if (shouldWarpInFromShip)
|
||||
{
|
||||
Main.Instance.ShipWarpController.WarpIn(Main.Instance.WearingSuit);
|
||||
}
|
||||
else if (shouldWarpInFromVessel)
|
||||
{
|
||||
VesselWarpHandler.TeleportToVessel();
|
||||
}
|
||||
else if (UsingCustomSpawn())
|
||||
{
|
||||
var player = SearchUtilities.Find("Player_Body");
|
||||
var playerBody = player.GetAttachedOWRigidbody();
|
||||
var spawn = GetDefaultSpawn();
|
||||
|
||||
// Player dies during the teleport sometimes so we prevent that
|
||||
var resources = player.GetComponent<PlayerResources>();
|
||||
var deathManager = Locator.GetDeathManager();
|
||||
|
||||
_wasInvincible = resources._invincible;
|
||||
_wasDeathManagerInvincible = deathManager._invincible;
|
||||
_impactDeathSpeed = deathManager._impactDeathSpeed;
|
||||
|
||||
resources._invincible = true;
|
||||
deathManager._invincible = true;
|
||||
deathManager._impactDeathSpeed = float.MaxValue;
|
||||
|
||||
Delay.FireOnNextUpdate(() =>
|
||||
{
|
||||
var matchInitialMotion = playerBody.GetComponent<MatchInitialMotion>();
|
||||
|
||||
playerBody.WarpToPositionRotation(spawn.transform.position, spawn.transform.rotation);
|
||||
|
||||
if (matchInitialMotion != null)
|
||||
{
|
||||
// Idk why but these just don't work?
|
||||
UnityEngine.Object.Destroy(matchInitialMotion);
|
||||
Delay.FireOnNextUpdate(FixVelocity);
|
||||
}
|
||||
else
|
||||
{
|
||||
FixVelocity();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
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<PlayerResources>();
|
||||
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<AstroObject>()?._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<PlayerSpawner>();
|
||||
public static SpawnPoint GetDefaultSpawn() => Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint ?? GetPlayerSpawner().GetSpawnPoint(SpawnLocation.TimberHearth);
|
||||
}
|
||||
}
|
||||
@ -62,6 +62,7 @@ namespace NewHorizons.Handlers
|
||||
public static void TeleportToVessel()
|
||||
{
|
||||
var playerSpawner = Object.FindObjectOfType<PlayerSpawner>();
|
||||
NHLogger.LogVerbose("Debug warping into vessel");
|
||||
playerSpawner.DebugWarp(_vesselSpawnPoint);
|
||||
Builder.General.SpawnPointBuilder.SuitUp();
|
||||
|
||||
|
||||
@ -75,7 +75,7 @@ namespace NewHorizons
|
||||
private string _defaultStarSystem = "SolarSystem";
|
||||
internal string _currentStarSystem = "SolarSystem";
|
||||
private bool _firstLoad = true;
|
||||
private ShipWarpController _shipWarpController;
|
||||
public ShipWarpController ShipWarpController { get; private set; }
|
||||
|
||||
// API events
|
||||
public class StarSystemEvent : UnityEvent<string> { }
|
||||
@ -418,18 +418,21 @@ namespace NewHorizons
|
||||
|
||||
StarChartHandler.Init(SystemDict.Values.ToArray());
|
||||
|
||||
// Fix spawn point
|
||||
PlayerSpawnHandler.SetUpPlayerSpawn();
|
||||
|
||||
if (isSolarSystem)
|
||||
{
|
||||
// Warp drive
|
||||
HasWarpDrive = StarChartHandler.CanWarp();
|
||||
if (_shipWarpController == null)
|
||||
if (ShipWarpController == null)
|
||||
{
|
||||
_shipWarpController = SearchUtilities.Find("Ship_Body").AddComponent<ShipWarpController>();
|
||||
_shipWarpController.Init();
|
||||
ShipWarpController = SearchUtilities.Find("Ship_Body").AddComponent<ShipWarpController>();
|
||||
ShipWarpController.Init();
|
||||
}
|
||||
if (HasWarpDrive == true) EnableWarpDrive();
|
||||
|
||||
var shouldWarpInFromShip = IsWarpingFromShip && _shipWarpController != null;
|
||||
var shouldWarpInFromShip = IsWarpingFromShip && ShipWarpController != null;
|
||||
var shouldWarpInFromVessel = IsWarpingFromVessel && VesselWarpHandler.VesselSpawnPoint != null;
|
||||
Delay.RunWhen(() => IsSystemReady, () => OnSystemReady(shouldWarpInFromShip, shouldWarpInFromVessel));
|
||||
|
||||
@ -443,7 +446,6 @@ namespace NewHorizons
|
||||
// Fix the map satellite
|
||||
SearchUtilities.Find("HearthianMapSatellite_Body", false).AddComponent<MapSatelliteOrbitFix>();
|
||||
|
||||
|
||||
// Sector changes (so that projection pools actually turn off proxies and cull groups on these moons)
|
||||
|
||||
//Fix attlerock vanilla sector components (they were set to timber hearth's sector)
|
||||
@ -564,11 +566,8 @@ namespace NewHorizons
|
||||
Locator.GetPlayerBody().gameObject.AddComponent<DebugRaycaster>();
|
||||
Locator.GetPlayerBody().gameObject.AddComponent<DebugPropPlacer>();
|
||||
Locator.GetPlayerBody().gameObject.AddComponent<DebugMenu>();
|
||||
// DebugArrow.CreateArrow(Locator.GetPlayerBody().gameObject); // This is for NH devs mostly. It shouldn't be active in debug mode for now. Someone should make a dev tools submenu for it though.
|
||||
|
||||
if (shouldWarpInFromShip) _shipWarpController.WarpIn(WearingSuit);
|
||||
else if (shouldWarpInFromVessel) VesselWarpHandler.TeleportToVessel();
|
||||
else FindObjectOfType<PlayerSpawner>().DebugWarp(SystemDict[_currentStarSystem].SpawnPoint);
|
||||
PlayerSpawnHandler.OnSystemReady(shouldWarpInFromShip, shouldWarpInFromVessel);
|
||||
|
||||
VesselCoordinatePromptHandler.RegisterPrompts(SystemDict.Where(system => system.Value.Config.Vessel?.coords != null).Select(x => x.Value).ToList());
|
||||
}
|
||||
@ -701,7 +700,7 @@ namespace NewHorizons
|
||||
}
|
||||
if (!string.IsNullOrEmpty(addonConfig.popupMessage))
|
||||
{
|
||||
MenuHandler.RegisterOneTimePopup(mod, TranslationHandler.GetTranslation(addonConfig.popupMessage, TranslationHandler.TextType.UI));
|
||||
MenuHandler.RegisterOneTimePopup(mod, TranslationHandler.GetTranslation(addonConfig.popupMessage, TranslationHandler.TextType.UI), addonConfig.repeatPopup);
|
||||
}
|
||||
}
|
||||
|
||||
@ -820,7 +819,7 @@ namespace NewHorizons
|
||||
OnChangeStarSystem?.Invoke(newStarSystem);
|
||||
|
||||
NHLogger.Log($"Warping to {newStarSystem}");
|
||||
if (warp && _shipWarpController) _shipWarpController.WarpOut();
|
||||
if (warp && ShipWarpController) ShipWarpController.WarpOut();
|
||||
IsChangingStarSystem = true;
|
||||
WearingSuit = PlayerState.IsWearingSuit();
|
||||
|
||||
@ -868,5 +867,7 @@ namespace NewHorizons
|
||||
}
|
||||
}
|
||||
#endregion Change star system
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ namespace NewHorizons.OtherMods.MenuFramework
|
||||
{
|
||||
private static IMenuAPI _menuApi;
|
||||
|
||||
private static List<(IModBehaviour mod, string message)> _registeredPopups = new();
|
||||
private static List<(IModBehaviour mod, string message, bool repeat)> _registeredPopups = new();
|
||||
private static List<string> _failedFiles = new();
|
||||
|
||||
public static void Init()
|
||||
@ -38,9 +38,9 @@ namespace NewHorizons.OtherMods.MenuFramework
|
||||
_menuApi.RegisterStartupPopup(warning);
|
||||
}
|
||||
|
||||
foreach(var (mod, message) in _registeredPopups)
|
||||
foreach(var (mod, message, repeat) in _registeredPopups)
|
||||
{
|
||||
if (!NewHorizonsData.HasReadOneTimePopup(mod.ModHelper.Manifest.UniqueName))
|
||||
if (repeat || !NewHorizonsData.HasReadOneTimePopup(mod.ModHelper.Manifest.UniqueName))
|
||||
{
|
||||
_menuApi.RegisterStartupPopup(TranslationHandler.GetTranslation(message, TranslationHandler.TextType.UI));
|
||||
NewHorizonsData.ReadOneTimePopup(mod.ModHelper.Manifest.UniqueName);
|
||||
@ -64,6 +64,6 @@ namespace NewHorizons.OtherMods.MenuFramework
|
||||
|
||||
public static void RegisterFailedConfig(string filename) => _failedFiles.Add(filename);
|
||||
|
||||
public static void RegisterOneTimePopup(IModBehaviour mod, string message) => _registeredPopups.Add((mod, message));
|
||||
public static void RegisterOneTimePopup(IModBehaviour mod, string message, bool repeat) => _registeredPopups.Add((mod, message, repeat));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
using HarmonyLib;
|
||||
|
||||
namespace NewHorizons.Patches.DialoguePatches
|
||||
{
|
||||
[HarmonyPatch(typeof(HearthianRecorderEffects))]
|
||||
public static class HearthianRecorderEffectsPatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(nameof(HearthianRecorderEffects.Awake))]
|
||||
public static bool HearthianRecorderEffects_Awake(HearthianRecorderEffects __instance)
|
||||
{
|
||||
// If we're adding custom dialogue to a recorder the CharacterDialogueTree isn't going to be on the object
|
||||
if (__instance.GetComponent<CharacterDialogueTree>() == null)
|
||||
{
|
||||
__instance.enabled = false;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7,32 +7,19 @@ namespace NewHorizons.Patches.MapPatches
|
||||
[HarmonyPatch(typeof(ReferenceFrame))]
|
||||
public static class ReferenceFramePatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPostfix]
|
||||
[HarmonyPatch(nameof(ReferenceFrame.GetHUDDisplayName))]
|
||||
public static bool ReferenceFrame_GetHUDDisplayName(ReferenceFrame __instance, ref string __result)
|
||||
public static void ReferenceFrame_GetHUDDisplayName(ReferenceFrame __instance, ref string __result)
|
||||
{
|
||||
var ao = __instance.GetAstroObject();
|
||||
|
||||
if (ao == null) return true;
|
||||
|
||||
if (ao._name != AstroObject.Name.CustomString)
|
||||
if (__instance.GetAstroObject() is NHAstroObject nhao && !nhao.isVanilla && !nhao.HideDisplayName)
|
||||
{
|
||||
__result = AstroObject.AstroObjectNameToString(ao._name);
|
||||
return false;
|
||||
var customName = nhao.GetCustomName();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(customName))
|
||||
{
|
||||
__result = TranslationHandler.GetTranslation(customName, TranslationHandler.TextType.UI, false);
|
||||
}
|
||||
}
|
||||
|
||||
__result = string.Empty;
|
||||
|
||||
if (ao is NHAstroObject nhao && nhao.HideDisplayName) return false;
|
||||
|
||||
var customName = ao.GetCustomName();
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(customName))
|
||||
{
|
||||
__result = TranslationHandler.GetTranslation(customName, TranslationHandler.TextType.UI, false);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -11,19 +11,12 @@ namespace NewHorizons.Patches.PlayerPatches
|
||||
[HarmonyPatch(nameof(PlayerSpawner.SpawnPlayer))]
|
||||
public static bool PlayerSpawner_SpawnPlayer(PlayerSpawner __instance)
|
||||
{
|
||||
if (Main.Instance.IsWarpingFromVessel || Main.Instance.DidWarpFromVessel)
|
||||
if (Main.Instance.IsWarpingFromVessel || Main.Instance.DidWarpFromVessel || Main.Instance.IsWarpingFromShip)
|
||||
{
|
||||
NHLogger.LogWarning("Abort player spawn. Vessel will handle it.");
|
||||
NHLogger.LogWarning("Abort player spawn. Vessel/Ship will handle it.");
|
||||
return false;
|
||||
}
|
||||
else if (Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint != null)
|
||||
{
|
||||
NHLogger.LogVerbose($"Player spawning at {Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint.transform.GetPath()}");
|
||||
__instance.SetInitialSpawnPoint(Main.SystemDict[Main.Instance.CurrentStarSystem].SpawnPoint);
|
||||
} else if (Main.Instance.CurrentStarSystem != "SolarSystem" && Main.Instance.CurrentStarSystem != "EyeOfTheUniverse")
|
||||
{
|
||||
NHLogger.LogWarning("No player spawn point set.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,9 +21,11 @@ namespace NewHorizons.Patches.SignalPatches
|
||||
__instance._frequencyFilterIndex += increment;
|
||||
__instance._frequencyFilterIndex = __instance._frequencyFilterIndex >= count ? 0 : __instance._frequencyFilterIndex;
|
||||
__instance._frequencyFilterIndex = __instance._frequencyFilterIndex < 0 ? count - 1 : __instance._frequencyFilterIndex;
|
||||
SignalFrequency signalFrequency = AudioSignal.IndexToFrequency(__instance._frequencyFilterIndex);
|
||||
var signalFrequency = AudioSignal.IndexToFrequency(__instance._frequencyFilterIndex);
|
||||
|
||||
if (!PlayerData.KnowsFrequency(signalFrequency) && (!__instance._isUnknownFreqNearby || __instance._unknownFrequency != signalFrequency))
|
||||
// Skip over this frequency
|
||||
var isUnknown = !PlayerData.KnowsFrequency(signalFrequency) && !(__instance._isUnknownFreqNearby && __instance._unknownFrequency == signalFrequency);
|
||||
if (isUnknown || !SignalBuilder.IsFrequencyInUse(signalFrequency))
|
||||
{
|
||||
__instance.SwitchFrequencyFilter(increment);
|
||||
}
|
||||
|
||||
@ -23,6 +23,10 @@
|
||||
"type": "string",
|
||||
"description": "A pop-up message for the first time a user runs the add-on"
|
||||
},
|
||||
"repeatPopup": {
|
||||
"type": "boolean",
|
||||
"description": "If popupMessage is set, should it repeat every time the game starts or only once"
|
||||
},
|
||||
"$schema": {
|
||||
"type": "string",
|
||||
"description": "The schema to validate with"
|
||||
|
||||
@ -774,7 +774,7 @@
|
||||
"properties": {
|
||||
"curve": {
|
||||
"type": "array",
|
||||
"description": "Scale this object over time",
|
||||
"description": "Scale this object over time. Time value is in minutes.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeValuePair"
|
||||
}
|
||||
@ -963,7 +963,7 @@
|
||||
"properties": {
|
||||
"curve": {
|
||||
"type": "array",
|
||||
"description": "Scale this object over time",
|
||||
"description": "Scale this object over time. Time value is in minutes.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeValuePair"
|
||||
}
|
||||
@ -1323,7 +1323,7 @@
|
||||
},
|
||||
"pathToAnimController": {
|
||||
"type": "string",
|
||||
"description": "If this dialogue is meant for a character, this is the relative path from the planet to that character's\nCharacterAnimController, TravelerController, TravelerEyeController (eye of the universe), FacePlayerWhenTalking, or SolanumAnimController.\n\nIf none of those components are present it will add a FacePlayerWhenTalking component."
|
||||
"description": "If this dialogue is meant for a character, this is the relative path from the planet to that character's\nCharacterAnimController, TravelerController, TravelerEyeController (eye of the universe), FacePlayerWhenTalking, \nHearthianRecorderEffects or SolanumAnimController.\n\nIf it's a Recorder this will also delete the existing dialogue already attached to that prop.\n\nIf none of those components are present it will add a FacePlayerWhenTalking component."
|
||||
},
|
||||
"radius": {
|
||||
"type": "number",
|
||||
@ -2854,7 +2854,7 @@
|
||||
"properties": {
|
||||
"curve": {
|
||||
"type": "array",
|
||||
"description": "Scale this object over time",
|
||||
"description": "Scale this object over time. Time value is in minutes.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeValuePair"
|
||||
}
|
||||
@ -3088,7 +3088,7 @@
|
||||
"properties": {
|
||||
"curve": {
|
||||
"type": "array",
|
||||
"description": "Scale this object over time",
|
||||
"description": "Scale this object over time. Time value is in minutes.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeValuePair"
|
||||
}
|
||||
@ -3222,7 +3222,7 @@
|
||||
"properties": {
|
||||
"curve": {
|
||||
"type": "array",
|
||||
"description": "Scale this object over time",
|
||||
"description": "Scale this object over time. Time value is in minutes.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeValuePair"
|
||||
}
|
||||
@ -4430,7 +4430,7 @@
|
||||
"properties": {
|
||||
"curve": {
|
||||
"type": "array",
|
||||
"description": "Scale this object over time",
|
||||
"description": "Scale this object over time. Time value is in minutes.",
|
||||
"items": {
|
||||
"$ref": "#/definitions/TimeValuePair"
|
||||
}
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
"author": "xen, Bwc9876, clay, MegaPiggy, John, Trifid, Hawkbar, Book",
|
||||
"name": "New Horizons",
|
||||
"uniqueName": "xen.NewHorizons",
|
||||
"version": "1.12.0",
|
||||
"version": "1.12.1",
|
||||
"owmlVersion": "2.9.0",
|
||||
"dependencies": [ "JohnCorby.VanillaFix", "_nebula.MenuFramework", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
||||
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "PacificEngine.OW_CommonResources" ],
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user