## 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:
Nick 2023-07-03 12:38:13 -04:00 committed by GitHub
commit 45e52be73b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 373 additions and 106 deletions

View File

@ -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;

View File

@ -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)

View File

@ -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}]");

View File

@ -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;
}

View File

@ -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

View File

@ -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);
}

View 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;
}
}
}
}

View File

@ -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)
{

View File

@ -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));
}

View File

@ -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()

View File

@ -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;
}
}

View File

@ -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>

View File

@ -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;
}

View File

@ -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;

View 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);
}
}

View File

@ -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();

View File

@ -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
}
}

View File

@ -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));
}
}

View File

@ -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;
}
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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"

View File

@ -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"
}

View File

@ -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" ],