Merge branch 'main' into hawkbar-docs-updates

This commit is contained in:
Joshua Thome 2024-04-13 15:20:14 -05:00 committed by GitHub
commit 3d630b26fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
43 changed files with 432 additions and 206 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 128 KiB

View File

@ -10,7 +10,7 @@
"Trifid#Tester\n#Programmer",
"Nageld#Programmer",
"Ernesto#Fish",
"With help from#Raicuparta\n#dgarroDC\n#jtsalomo\n#and the modding community",
"With help from#Raicuparta\n#dgarroDC\n#jtsalomo\n#coderCleric\n#TRSasasusu\n#and the modding community",
" ",
"Based off Marshmallow made by#_nebula",
"With help from#AmazingAlek\n#Raicuparta\n#and the Outer Wilds discord server",

View File

@ -1,10 +1,10 @@
using NewHorizons.External.Modules;
using NewHorizons.External.Modules.Props;
using NewHorizons.Utility;
using NewHorizons.Utility.Files;
using OWML.Common;
using System;
using UnityEngine;
namespace NewHorizons.Builder.Atmosphere
{
public static class FogBuilder
@ -26,7 +26,9 @@ namespace NewHorizons.Builder.Atmosphere
internal static void InitPrefabs()
{
if (_ramp == null) _ramp = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/FogColorRamp.png");
// Checking null here it was getting destroyed and wouldnt reload and never worked outside of the first loop
// GetTexture caches itself anyway so it doesn't matter that this gets called multiple times
_ramp = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/FogColorRamp.png");
if (_isInit) return;
@ -73,6 +75,7 @@ namespace NewHorizons.Builder.Atmosphere
atmo.fogRampPath != null ? ImageUtilities.GetTexture(mod, atmo.fogRampPath) :
atmo.fogTint != null ? ImageUtilities.TintImage(_ramp, atmo.fogTint.ToColor()) :
_ramp;
PFC.fogColorRampTexture = colorRampTexture;
PFC.fogColorRampIntensity = 1f;
if (atmo.fogTint != null)

View File

@ -1,6 +1,7 @@
using NewHorizons.External.Modules;
using NewHorizons.External.Modules.VariableSize;
using UnityEngine;
namespace NewHorizons.Builder.Atmosphere
{
public static class SunOverrideBuilder

View File

@ -1,6 +1,6 @@
using NewHorizons.Components;
using NewHorizons.Components.Orbital;
using NewHorizons.External.Configs;
using NewHorizons.External;
using NewHorizons.Utility.OWML;
using UnityEngine;
@ -8,9 +8,13 @@ namespace NewHorizons.Builder.General
{
public static class AstroObjectBuilder
{
public static NHAstroObject Make(GameObject body, AstroObject primaryBody, PlanetConfig config, bool isVanilla)
public static NHAstroObject Make(GameObject body, AstroObject primaryBody, NewHorizonsBody nhBody, bool isVanilla)
{
NHAstroObject astroObject = body.AddComponent<NHAstroObject>();
astroObject.modUniqueName = nhBody.Mod.ModHelper.Manifest.UniqueName;
var config = nhBody.Config;
astroObject.isVanilla = isVanilla;
astroObject.HideDisplayName = !config.Base.hasMapMarker;
astroObject.invulnerableToSun = config.Base.invulnerableToSun;

View File

@ -12,6 +12,8 @@ namespace NewHorizons.Builder.General
{
// We can't not build a reference frame volume, Cloak requires one to be there
module.maxTargetDistance = 0f;
module.targetWhenClose = true;
module.targetColliderRadius = 0f;
module.hideInMap = true;
owrb.SetIsTargetable(false);
}

View File

@ -1,9 +1,11 @@
using HarmonyLib;
using NewHorizons.External;
using NewHorizons.External.Modules.Props.Audio;
using NewHorizons.Utility;
using NewHorizons.Utility.OWML;
using OWML.Common;
using OWML.Utils;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
@ -36,27 +38,16 @@ namespace NewHorizons.Builder.Props.Audio
};
NumberOfFrequencies = EnumUtils.GetValues<SignalFrequency>().Length;
_qmSignals = new (){ SearchUtilities.Find("QuantumMoon_Body/Signal_Quantum").GetComponent<AudioSignal>() };
_qmSignals = new () { SearchUtilities.Find("QuantumMoon_Body/Signal_Quantum").GetComponent<AudioSignal>() };
_cloakedSignals = new();
Initialized = true;
SceneManager.sceneUnloaded -= OnSceneUnloaded;
SceneManager.sceneUnloaded += OnSceneUnloaded;
Main.Instance.OnStarSystemLoaded.RemoveListener(OnStarSystemLoaded);
Main.Instance.OnStarSystemLoaded.AddListener(OnStarSystemLoaded);
}
private static HashSet<SignalFrequency> _frequenciesInUse = new();
private static void OnSceneUnloaded(Scene _)
{
_frequenciesInUse.Clear();
}
private static void OnStarSystemLoaded(string starSystem)
{
// If its the base game solar system or eye we get all the main frequencies
var starSystem = Main.Instance.CurrentStarSystem;
if (starSystem == "SolarSystem" || starSystem == "EyeOfTheUniverse")
{
_frequenciesInUse.Add(SignalFrequency.Quantum);
@ -69,19 +60,43 @@ namespace NewHorizons.Builder.Props.Audio
// We don't want a scenario where the player knows no frequencies
_frequenciesInUse.Add(SignalFrequency.Traveler);
// Make sure the NH save file has all the right frequencies
// Skip "default"
for (int i = 1; i < PlayerData._currentGameSave.knownFrequencies.Length; i++)
{
if (PlayerData._currentGameSave.knownFrequencies[i])
{
NewHorizonsData.LearnFrequency(AudioSignal.IndexToFrequency(i).ToString());
}
}
NHLogger.LogVerbose($"Frequencies in use in {starSystem}: {_frequenciesInUse.Join(x => x.ToString())}");
}
private static HashSet<SignalFrequency> _frequenciesInUse = new();
private static void OnSceneUnloaded(Scene _)
{
_frequenciesInUse.Clear();
}
public static bool IsFrequencyInUse(SignalFrequency freq) => _frequenciesInUse.Contains(freq);
public static bool IsFrequencyInUse(string freqString)
{
if (Enum.TryParse<SignalFrequency>(freqString, out var freq))
{
return IsFrequencyInUse(freq);
}
return false;
}
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();
var freq = CollectionUtilities.KeyByValue(_customFrequencyNames, str);
if (freq != default) return freq;
@ -99,23 +114,19 @@ namespace NewHorizons.Builder.Props.Audio
NumberOfFrequencies = EnumUtils.GetValues<SignalFrequency>().Length;
// This stuff happens after the signalscope is Awake so we have to change the number of frequencies now
Object.FindObjectOfType<Signalscope>()._strongestSignals = new AudioSignal[NumberOfFrequencies + 1];
GameObject.FindObjectOfType<Signalscope>()._strongestSignals = new AudioSignal[NumberOfFrequencies + 1];
return freq;
}
public static string GetCustomFrequencyName(SignalFrequency frequencyName)
{
if (_customFrequencyNames == null) Init();
_customFrequencyNames.TryGetValue(frequencyName, out string name);
return name;
}
public static SignalName AddSignalName(string str)
{
if (_customSignalNames == null) Init();
var name = CollectionUtilities.KeyByValue(_customSignalNames, str);
if (name != default) return name;
@ -129,8 +140,6 @@ namespace NewHorizons.Builder.Props.Audio
public static string GetCustomSignalName(SignalName signalName)
{
if (_customSignalNames == null) Init();
_customSignalNames.TryGetValue(signalName, out string name);
return name;
}

View File

@ -6,6 +6,7 @@ using NewHorizons.Handlers;
using NewHorizons.Utility;
using NewHorizons.Utility.OuterWilds;
using NewHorizons.Utility.OWML;
using Newtonsoft.Json;
using OWML.Common;
using System.Collections.Generic;
using System.Linq;
@ -414,7 +415,13 @@ namespace NewHorizons.Builder.Props
{
foreach (var signalConfig in connectedSignals)
{
var signalGO = SignalBuilder.Make(go, sector, signalConfig, mod);
// Have to ensure that this new signal doesn't use parent path, else it looks for a parent that only exists on the original body
// Have to make a copy of it as well to avoid modifying the old body's info
var signalConfigCopy = JsonConvert.DeserializeObject<SignalInfo>(JsonConvert.SerializeObject(signalConfig));
signalConfigCopy.parentPath = null;
signalConfigCopy.isRelativeToParent = false;
var signalGO = SignalBuilder.Make(go, sector, signalConfigCopy, mod);
signalGO.GetComponent<AudioSignal>()._identificationDistance = 0;
signalGO.GetComponent<AudioSignal>()._sourceRadius = 1;
signalGO.transform.position = brambleNode.transform.position;

View File

@ -101,6 +101,7 @@ namespace NewHorizons.Builder.Props
GameObject prop;
bool isItem;
bool invalidComponentFound = false;
bool isFromAssetBundle = !string.IsNullOrEmpty(detail.assetBundle);
// We save copies with all their components fixed, good if the user is placing the same detail more than once
if (detail?.path != null && _fixedPrefabCache.TryGetValue((sector, detail.path), out var storedPrefab))
@ -139,12 +140,21 @@ namespace NewHorizons.Builder.Props
}
else
{
FixSectoredComponent(component, sector, existingSectors, detail.keepLoaded);
// Fix cull groups only when not from an asset bundle (because then they're there on purpose!)
// keepLoaded should remove existing groups
// renderers/colliders get enabled later so we dont have to do that here
if (detail.keepLoaded && !isFromAssetBundle && component is SectorCullGroup or SectorCollisionGroup or SectorLightsCullGroup)
{
UnityEngine.Object.DestroyImmediate(component);
continue;
}
FixSectoredComponent(component, sector, existingSectors);
}
// Asset bundle is a real string -> Object loaded from unity
// If they're adding dialogue we have to manually register the xml text
if (!string.IsNullOrEmpty(detail.assetBundle) && component is CharacterDialogueTree dialogue)
if (isFromAssetBundle && component is CharacterDialogueTree dialogue)
{
DialogueBuilder.AddTranslation(dialogue._xmlCharacterDialogueAsset.text, null);
}
@ -278,16 +288,8 @@ namespace NewHorizons.Builder.Props
/// <summary>
/// Fix components that have sectors. Has a specific fix if there is a VisionTorchItem on the object.
/// </summary>
private static void FixSectoredComponent(Component component, Sector sector, HashSet<Sector> existingSectors, bool keepLoaded)
private static void FixSectoredComponent(Component component, Sector sector, HashSet<Sector> existingSectors)
{
// keepLoaded should remove existing groups
// renderers/colliders get enabled later so we dont have to do that here
if (keepLoaded && component is SectorCullGroup or SectorCollisionGroup or SectorLightsCullGroup)
{
UnityEngine.Object.DestroyImmediate(component);
return;
}
// fix Sector stuff, eg SectorCullGroup (without this, props that have a SectorCullGroup component will become invisible inappropriately)
if (component is ISectorGroup sectorGroup && !existingSectors.Contains(sectorGroup.GetSector()))
{
@ -296,14 +298,7 @@ namespace NewHorizons.Builder.Props
// Not doing else if here because idk if any of the classes below implement ISectorGroup
// Null check else shuttles controls break
// parent sector is always null before Awake so this code actually never runs lol
if (component is Sector s && s.GetParentSector() != null && !existingSectors.Contains(s.GetParentSector()))
{
s.SetParentSector(sector);
}
else if(component is SectoredMonoBehaviour behaviour && !existingSectors.Contains(behaviour._sector))
if(component is SectoredMonoBehaviour behaviour && !existingSectors.Contains(behaviour._sector))
{
// not using SetSector here because it registers the events twice
// perhaps this happens with ISectorGroup.SetSector or Sector.SetParentSector too? idk and nothing seems to break because of it yet

View File

@ -102,10 +102,12 @@ namespace NewHorizons.Builder.Props
// We just have to merge the dialogue options
var dialogueOptions = newDialogueNode.GetChildNode("DialogueOptionsList").GetChildNodes("DialogueOption");
var existingDialogueOptionsList = existingNode.GetChildNode("DialogueOptionsList");
var firstNode = existingDialogueOptionsList.ChildNodes[0];
foreach (XmlNode node in dialogueOptions)
{
var importedNode = existingDialogueOptionsList.OwnerDocument.ImportNode(node, true);
existingDialogueOptionsList.AppendChild(importedNode);
// We add them to the start because normally the last option is to return to menu or exit
existingDialogueOptionsList.PrependChild(importedNode);
}
}
else

View File

@ -51,6 +51,10 @@ namespace NewHorizons.Builder.Props
item.DisplayName = itemName;
item.ItemType = itemType;
item.Droppable = info.droppable;
item.HoldOffset = info.holdOffset ?? Vector3.zero;
item.HoldRotation = info.holdRotation ?? Vector3.zero;
item.SocketOffset = info.socketOffset ?? Vector3.zero;
item.SocketRotation = info.socketRotation ?? Vector3.zero;
if (!string.IsNullOrEmpty(info.pickupAudio))
{
item.PickupAudio = AudioTypeHandler.GetAudioType(info.pickupAudio, mod);

View File

@ -476,7 +476,7 @@ namespace NewHorizons.Builder.Props.TranslatorText
}
ArcCacheData[] cachedData = null;
if (nhBody.Cache?.ContainsKey(cacheKey) ?? false)
if (nhBody?.Cache?.ContainsKey(cacheKey) ?? false)
cachedData = nhBody.Cache.Get<ArcCacheData[]>(cacheKey);
var arranger = nomaiWallText.gameObject.AddComponent<NomaiTextArcArranger>();

View File

@ -30,7 +30,7 @@ namespace NewHorizons.Builder.ShipLog
{
if (body.Config.ShipLog == null) continue;
if (body.Config.ShipLog?.mapMode?.manualPosition == null)
if (body.Config.ShipLog.mapMode?.manualPosition == null)
{
flagAutoPositionUsed = true;
}
@ -45,6 +45,12 @@ namespace NewHorizons.Builder.ShipLog
}
}
// If they're both false, just default to auto (this means that no planets even have ship log info)
if (!flagManualPositionUsed && !flagAutoPositionUsed)
{
flagAutoPositionUsed = true;
}
var isBaseSolarSystem = systemName == "SolarSystem";
// Default to MANUAL in Base Solar System (we can't automatically fix them so it might just break, but AUTO breaks even more!)
@ -142,6 +148,7 @@ namespace NewHorizons.Builder.ShipLog
astroObject._imageObj = CreateImage(gameObject, image, body.Config.name + " Revealed", layer);
astroObject._outlineObj = CreateImage(gameObject, outline, body.Config.name + " Outline", layer);
if (ShipLogHandler.BodyHasEntries(body))
{
Image revealedImage = astroObject._imageObj.GetComponent<Image>();
@ -156,6 +163,12 @@ namespace NewHorizons.Builder.ShipLog
Rect imageRect = astroObject._imageObj.GetComponent<RectTransform>().rect;
astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0);
// Set all icons inactive, they will be conditionally activated when the map mode is opened for the first time
astroObject._unviewedObj.SetActive(false);
astroObject._imageObj.SetActive(false);
astroObject._outlineObj.SetActive(false);
return astroObject;
}
#endregion

View File

@ -0,0 +1,33 @@
using NewHorizons.Utility.OWML;
using UnityEngine;
namespace NewHorizons.Components.Fixers;
/// <summary>
/// Fixes a bug where spawning into the ship would not trigger the hatch entryway, so the player could drown if the ship flew into water
/// </summary>
internal class PlayerShipAtmosphereDetectorFix : MonoBehaviour
{
private PlayerCameraFluidDetector _fluidDetector;
private SimpleFluidVolume _shipAtmosphereVolume;
public void Start()
{
_fluidDetector = Locator.GetPlayerCameraDetector().GetComponent<PlayerCameraFluidDetector>();
_shipAtmosphereVolume = Locator.GetShipBody().transform.Find("Volumes/ShipAtmosphereVolume").GetComponent<SimpleFluidVolume>();
}
public void Update()
{
if (PlayerState.IsInsideShip())
{
if (!_fluidDetector._activeVolumes.Contains(_shipAtmosphereVolume))
{
NHLogger.LogVerbose($"{nameof(PlayerShipAtmosphereDetectorFix)} had to add the ship atmosphere volume [{_shipAtmosphereVolume}] to the fluid detector");
_fluidDetector.AddVolume(_shipAtmosphereVolume);
}
NHLogger.LogVerbose($"{nameof(PlayerShipAtmosphereDetectorFix)} applied its fix");
Component.Destroy(this);
}
}
}

View File

@ -14,6 +14,11 @@ namespace NewHorizons.Components.Orbital
public bool invulnerableToSun;
public bool isVanilla;
/// <summary>
/// The unique name of the mod that created this body or, if it is an existing body being edited, the last mod to edit it
/// </summary>
public string modUniqueName;
public void SetOrbitalParametersFromConfig(OrbitModule orbit)
{
SetOrbitalParametersFromTrueAnomaly(orbit.eccentricity, orbit.semiMajorAxis, orbit.inclination, orbit.argumentOfPeriapsis, orbit.longitudeOfAscendingNode, orbit.trueAnomaly);

View File

@ -19,6 +19,7 @@ namespace NewHorizons.Components.Props
{
var conditionalObjectActivationGO = new GameObject($"{go.name}_{condition}");
var component = conditionalObjectActivationGO.AddComponent<ConditionalObjectActivation>();
component.transform.parent = go.transform.parent;
component.GameObject = go;
component.DialogueCondition = condition;
component.CloseEyes = closeEyes;

View File

@ -19,6 +19,10 @@ namespace NewHorizons.Components.Props
public AudioType DropAudio;
public AudioType SocketAudio;
public AudioType UnsocketAudio;
public Vector3 HoldOffset;
public Vector3 HoldRotation;
public Vector3 SocketOffset;
public Vector3 SocketRotation;
public string PickupCondition;
public bool ClearPickupConditionOnDrop;
public string PickupFact;
@ -42,6 +46,8 @@ namespace NewHorizons.Components.Props
public override void PickUpItem(Transform holdTranform)
{
base.PickUpItem(holdTranform);
transform.localPosition = HoldOffset;
transform.localEulerAngles = HoldRotation;
TriggerPickupConditions();
PlayCustomSound(PickupAudio);
}
@ -56,6 +62,8 @@ namespace NewHorizons.Components.Props
public override void SocketItem(Transform socketTransform, Sector sector)
{
base.SocketItem(socketTransform, sector);
transform.localPosition = SocketOffset;
transform.localEulerAngles = SocketRotation;
TriggerDropConditions();
PlayCustomSound(SocketAudio);
}

View File

@ -33,13 +33,16 @@ namespace NewHorizons.Components.Sectored
}
private void Start()
{
DisableRenderers();
}
private void GetRenderers()
{
_renderers = gameObject.GetComponentsInChildren<Renderer>();
_tessellatedRenderers = gameObject.GetComponentsInChildren<TessellatedRenderer>();
_colliders = gameObject.GetComponentsInChildren<Collider>();
_lights = gameObject.GetComponentsInChildren<Light>();
DisableRenderers();
}
private void OnSectorOccupantsUpdated()
@ -54,54 +57,35 @@ namespace NewHorizons.Components.Sectored
}
}
private void EnableRenderers()
private void EnableRenderers() => ToggleRenderers(true);
private void DisableRenderers() => ToggleRenderers(false);
private void ToggleRenderers(bool visible)
{
GetRenderers();
foreach (var renderer in _renderers)
{
renderer.forceRenderingOff = false;
renderer.forceRenderingOff = !visible;
}
foreach (var tessellatedRenderer in _tessellatedRenderers)
{
tessellatedRenderer.enabled = true;
tessellatedRenderer.enabled = visible;
}
foreach (var collider in _colliders)
{
collider.enabled = true;
collider.enabled = visible;
}
foreach (var light in _lights)
{
light.enabled = true;
light.enabled = visible;
}
_renderersShown = true;
}
private void DisableRenderers()
{
foreach (var renderer in _renderers)
{
renderer.forceRenderingOff = true;
}
foreach (var tessellatedRenderer in _tessellatedRenderers)
{
tessellatedRenderer.enabled = false;
}
foreach (var collider in _colliders)
{
collider.enabled = false;
}
foreach (var light in _lights)
{
light.enabled = false;
}
_renderersShown = false;
_renderersShown = visible;
}
}
}

View File

@ -213,7 +213,6 @@ namespace NewHorizons.External.Configs
// Always have to have a base module
if (Base == null) Base = new BaseModule();
if (Orbit == null) Orbit = new OrbitModule();
if (ShipLog == null) ShipLog = new ShipLogModule();
if (ReferenceFrame == null) ReferenceFrame = new ReferenceFrameModule();
}

View File

@ -44,6 +44,22 @@ namespace NewHorizons.External.Modules.Props.Item
/// </summary>
public MVector3 dropNormal;
/// <summary>
/// A relative offset to apply to the item's position when holding it. The initial position varies for vanilla item types.
/// </summary>
public MVector3 holdOffset;
/// <summary>
/// A relative offset to apply to the item's rotation when holding it.
/// </summary>
public MVector3 holdRotation;
/// <summary>
/// A relative offset to apply to the item's position when placing it into a socket.
/// </summary>
public MVector3 socketOffset;
/// <summary>
/// A relative offset to apply to the item's rotation when placing it into a socket.
/// </summary>
public MVector3 socketRotation;
/// <summary>
/// The audio to play when this item is picked up. Only applies to custom/non-vanilla item types.
/// Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list.
/// </summary>

View File

@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NewHorizons.Builder.Props.Audio;
using NewHorizons.Utility.OWML;
namespace NewHorizons.External
@ -124,7 +126,6 @@ namespace NewHorizons.External
if (!KnowsFrequency(frequency))
{
_activeProfile.KnownFrequencies.Add(frequency);
Save();
}
}
@ -134,13 +135,12 @@ namespace NewHorizons.External
if (KnowsFrequency(frequency))
{
_activeProfile.KnownFrequencies.Remove(frequency);
Save();
}
}
public static bool KnowsMultipleFrequencies()
{
return _activeProfile != null && _activeProfile.KnownFrequencies.Count > 0;
return _activeProfile?.KnownFrequencies != null && _activeProfile.KnownFrequencies.Count(SignalBuilder.IsFrequencyInUse) > 1;
}
#endregion
@ -159,7 +159,6 @@ namespace NewHorizons.External
if (!KnowsSignal(signal))
{
_activeProfile.KnownSignals.Add(signal);
Save();
}
}
@ -170,7 +169,6 @@ namespace NewHorizons.External
public static void AddNewlyRevealedFactID(string id)
{
_activeProfile?.NewlyRevealedFactIDs.Add(id);
Save();
}
public static List<string> GetNewlyRevealedFactIDs()
@ -181,7 +179,6 @@ namespace NewHorizons.External
public static void ClearNewlyRevealedFactIDs()
{
_activeProfile?.NewlyRevealedFactIDs.Clear();
Save();
}
#endregion
@ -191,7 +188,6 @@ namespace NewHorizons.External
public static void ReadOneTimePopup(string id)
{
_activeProfile?.PopupsRead.Add(id);
Save();
}
public static bool HasReadOneTimePopup(string id)
@ -208,7 +204,6 @@ namespace NewHorizons.External
{
if (name == CharacterDialogueTree.RECORDING_NAME || name == CharacterDialogueTree.SIGN_NAME) return;
_activeProfile?.CharactersTalkedTo.SafeAdd(name);
Save();
}
public static bool HasTalkedToFiveCharacters()

View File

@ -371,7 +371,7 @@ namespace NewHorizons.Handlers
const float sphereOfInfluence = 2000f;
var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config);
var ao = AstroObjectBuilder.Make(go, null, body.Config, false);
var ao = AstroObjectBuilder.Make(go, null, body, false);
var sector = SectorBuilder.Make(go, owRigidBody, sphereOfInfluence);
ao._rootSector = sector;
@ -447,7 +447,7 @@ namespace NewHorizons.Handlers
var sphereOfInfluence = GetSphereOfInfluence(body);
var owRigidBody = RigidBodyBuilder.Make(go, sphereOfInfluence, body.Config);
var ao = AstroObjectBuilder.Make(go, primaryBody, body.Config, false);
var ao = AstroObjectBuilder.Make(go, primaryBody, body, false);
var sector = SectorBuilder.Make(go, owRigidBody, sphereOfInfluence * 2f);
ao._rootSector = sector;
@ -788,7 +788,7 @@ namespace NewHorizons.Handlers
}
// Just destroy the existing AO after copying everything over
var newAO = AstroObjectBuilder.Make(go, primary, body.Config, true);
var newAO = AstroObjectBuilder.Make(go, primary, body, true);
newAO._gravityVolume = ao._gravityVolume;
newAO._moon = ao._moon;
newAO._name = ao._name;

View File

@ -115,6 +115,17 @@ namespace NewHorizons.Handlers
}
// For some reason none of this seems to apply to the Player.
// If somebody ever makes a sound volume thats somehow always applying to the player tho then itd probably be this
// Sometimes the ship isn't added to the volumes it's meant to now be in
foreach (var volume in SpawnPointBuilder.ShipSpawn.GetAttachedOWRigidbody().GetComponentsInChildren<EffectVolume>())
{
if (volume.GetOWTriggerVolume().GetPenetrationDistance(ship.transform.position) > 0)
{
// Add ship to volume
// If it's already tracking it it will complain here but thats fine
volume.GetOWTriggerVolume().AddObjectToVolume(Locator.GetShipDetector());
}
}
}
}
else if (Main.Instance.CurrentStarSystem != "SolarSystem" && !Main.Instance.IsWarpingFromShip)

View File

@ -11,8 +11,8 @@ namespace NewHorizons.Handlers
{
class SubtitlesHandler : MonoBehaviour
{
public static int SUBTITLE_HEIGHT = 97;
public static int SUBTITLE_WIDTH = 669; // nice
public static float SUBTITLE_HEIGHT = 97;
public static float SUBTITLE_WIDTH = 669; // nice
public float fadeSpeed = 0.005f;
public float fade = 1;
@ -67,7 +67,7 @@ namespace NewHorizons.Handlers
CheckForEOTE();
// We add our subtitles as a child object so that their sizing doesnt shift the layout of the main menu
_subtitleDisplay = new GameObject().AddComponent<Image>();
_subtitleDisplay = new GameObject("SubtitleDisplay").AddComponent<Image>();
_subtitleDisplay.transform.parent = transform;
_subtitleDisplay.transform.localPosition = new Vector3(0, 0, 0);
_subtitleDisplay.transform.localScale = new Vector3(0.75f, 0.75f, 0.75f);
@ -173,9 +173,12 @@ namespace NewHorizons.Handlers
{
subtitleIndex = (subtitleIndex + 1) % possibleSubtitles.Count;
_subtitleDisplay.sprite = possibleSubtitles[subtitleIndex];
var ratio = SUBTITLE_WIDTH / _subtitleDisplay.sprite.texture.width;
_subtitleDisplay.rectTransform.sizeDelta = new Vector2(_subtitleDisplay.sprite.texture.width, _subtitleDisplay.sprite.texture.height) * ratio;
var subtitle = possibleSubtitles[subtitleIndex];
_subtitleDisplay.sprite = subtitle;
var width = subtitle.texture.width;
var height = subtitle.texture.height;
var ratio = SUBTITLE_WIDTH / width; // one of these needs to be a float so that compiler doesn't think "oh 2 integers! let's round to nearest whole"
_subtitleDisplay.rectTransform.sizeDelta = new Vector2(width, height) * ratio;
}
}
}

View File

@ -2,9 +2,11 @@ using NewHorizons.External.Configs;
using NewHorizons.Utility;
using NewHorizons.Utility.OWML;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using static TextTranslation;
namespace NewHorizons.Handlers
{
@ -50,30 +52,46 @@ namespace NewHorizons.Handlers
}
// Get the translated text
if (dictionary.TryGetValue(language, out var table))
if (TryGetTranslatedText(dictionary, language, text, out var translatedText))
{
if (table.TryGetValue(text, out var translatedText))
return translatedText;
}
if (warn)
{
NHLogger.LogVerbose($"Defaulting to english for {text}");
}
if (TryGetTranslatedText(dictionary, Language.ENGLISH, text, out translatedText))
{
return translatedText;
}
if (warn)
{
NHLogger.LogVerbose($"Defaulting to key for {text}");
}
return text;
}
private static bool TryGetTranslatedText(Dictionary<Language, Dictionary<string, string>> dict, Language language, string text, out string translatedText)
{
if (dict.TryGetValue(language, out var table))
{
if (table.TryGetValue(text, out translatedText))
{
return translatedText;
return true;
}
// Try without whitespace if its missing
else if (table.TryGetValue(text.TruncateWhitespaceAndToLower(), out translatedText))
{
return translatedText;
return true;
}
}
if (warn) NHLogger.LogVerbose($"Defaulting to english for {text}");
// Try to default to English
if (dictionary.TryGetValue(TextTranslation.Language.ENGLISH, out var englishTable))
if (englishTable.TryGetValue(text, out var englishText))
return englishText;
if (warn) NHLogger.LogVerbose($"Defaulting to key for {text}");
// Default to the key
return text;
translatedText = null;
return false;
}
public static void RegisterTranslation(TextTranslation.Language language, TranslationConfig config)

View File

@ -1,4 +1,3 @@
using NewHorizons.Handlers;
using OWML.Common;
using System;
using System.Collections.Generic;

View File

@ -263,7 +263,6 @@ namespace NewHorizons
// Call this from the menu since we hadn't hooked onto the event yet
Delay.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single));
Delay.FireOnNextUpdate(() => _firstLoad = false);
Instance.ModHelper.Menus.PauseMenu.OnInit += DebugReload.InitializePauseMenu;
MenuHandler.Init();
AchievementHandler.Init();
@ -275,6 +274,13 @@ namespace NewHorizons
LoadAddonManifest("Assets/addon-manifest.json", this);
}
public override void SetupPauseMenu(IPauseMenuManager pauseMenu)
{
base.SetupPauseMenu(pauseMenu);
DebugReload.InitializePauseMenu(pauseMenu);
DebugMenu.InitializePauseMenu(pauseMenu);
}
public void OnDestroy()
{
NHLogger.Log($"Destroying NewHorizons");
@ -512,8 +518,10 @@ namespace NewHorizons
// We are in a custom system on the first loop -> The time loop isn't active, that's not very good
// TimeLoop uses the launch codes condition to know if the loop is active or not
// We also skip them to loop 2, else if they enter a credits volume in this loop they get reset
if (CurrentStarSystem != "SolarSystem" && PlayerData.LoadLoopCount() == 1)
{
PlayerData.SaveLoopCount(2);
PlayerData.SetPersistentCondition("LAUNCH_CODES_GIVEN", true);
}
}
@ -595,6 +603,7 @@ namespace NewHorizons
Locator.GetPlayerBody().gameObject.AddComponent<DebugRaycaster>();
Locator.GetPlayerBody().gameObject.AddComponent<DebugPropPlacer>();
Locator.GetPlayerBody().gameObject.AddComponent<DebugMenu>();
Locator.GetPlayerBody().gameObject.AddComponent<PlayerShipAtmosphereDetectorFix>();
PlayerSpawnHandler.OnSystemReady(shouldWarpInFromShip, shouldWarpInFromVessel);

View File

@ -16,7 +16,7 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="OuterWildsGameLibs" Version="1.1.14.768" />
<PackageReference Include="OWML" Version="2.9.8" />
<PackageReference Include="OWML" Version="2.11.1" />
<Reference Include="../Lib/System.ComponentModel.Annotations.dll" />
</ItemGroup>
<ItemGroup>

View File

@ -1,20 +0,0 @@
using UnityEngine;
using UnityEngine.UI;
namespace NewHorizons.OtherMods.MenuFramework
{
public interface IMenuAPI
{
GameObject TitleScreen_MakeMenuOpenButton(string name, int index, Menu menuToOpen);
GameObject TitleScreen_MakeSceneLoadButton(string name, int index, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null);
Button TitleScreen_MakeSimpleButton(string name, int index);
GameObject PauseMenu_MakeMenuOpenButton(string name, Menu menuToOpen, Menu customMenu = null);
GameObject PauseMenu_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null, Menu customMenu = null);
Button PauseMenu_MakeSimpleButton(string name, Menu customMenu = null);
Menu PauseMenu_MakePauseListMenu(string title);
PopupMenu MakeTwoChoicePopup(string message, string confirmText, string cancelText);
PopupInputMenu MakeInputFieldPopup(string message, string placeholderMessage, string confirmText, string cancelText);
PopupMenu MakeInfoPopup(string message, string continueButtonText);
void RegisterStartupPopup(string message);
}
}

View File

@ -11,15 +11,11 @@ namespace NewHorizons.OtherMods.MenuFramework
{
public static class MenuHandler
{
private static IMenuAPI _menuApi;
private static List<(IModBehaviour mod, string message, bool repeat)> _registeredPopups = new();
private static List<string> _failedFiles = new();
public static void Init()
{
_menuApi = Main.Instance.ModHelper.Interaction.TryGetModApi<IMenuAPI>("_nebula.MenuFramework");
TextTranslation.Get().OnLanguageChanged += OnLanguageChanged;
}
@ -35,14 +31,14 @@ namespace NewHorizons.OtherMods.MenuFramework
Application.version);
NHLogger.LogError(warning);
_menuApi.RegisterStartupPopup(warning);
Main.Instance.ModHelper.MenuHelper.PopupMenuManager.RegisterStartupPopup(warning);
}
foreach(var (mod, message, repeat) in _registeredPopups)
{
if (repeat || !NewHorizonsData.HasReadOneTimePopup(mod.ModHelper.Manifest.UniqueName))
{
_menuApi.RegisterStartupPopup(TranslationHandler.GetTranslation(message, TranslationHandler.TextType.UI));
Main.Instance.ModHelper.MenuHelper.PopupMenuManager.RegisterStartupPopup(TranslationHandler.GetTranslation(message, TranslationHandler.TextType.UI));
NewHorizonsData.ReadOneTimePopup(mod.ModHelper.Manifest.UniqueName);
}
}
@ -52,7 +48,7 @@ namespace NewHorizons.OtherMods.MenuFramework
var message = TranslationHandler.GetTranslation("JSON_FAILED_TO_LOAD", TranslationHandler.TextType.UI);
var mods = string.Join(",", _failedFiles.Take(10));
if (_failedFiles.Count > 10) mods += "...";
_menuApi.RegisterStartupPopup(string.Format(message, mods));
Main.Instance.ModHelper.MenuHelper.PopupMenuManager.RegisterStartupPopup(string.Format(message, mods));
}
_registeredPopups.Clear();

View File

@ -0,0 +1,26 @@
using HarmonyLib;
namespace NewHorizons.Patches;
/// <summary>
/// Bug fix from the Outsider
/// </summary>
[HarmonyPatch]
internal class BrambleProjectionFixPatches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(FogWarpVolume), nameof(FogWarpVolume.WarpDetector))]
public static bool FogWarpVolume_WarpDetector()
{
// Do not warp the player if they have entered the fog via a projection
return !PlayerState.UsingNomaiRemoteCamera();
}
[HarmonyPrefix]
[HarmonyPatch(typeof(FogWarpDetector), nameof(FogWarpDetector.FixedUpdate))]
public static bool FogWarpDetector_FixedUpdate()
{
// Do not warp the player if they have entered the fog via a projection
return !PlayerState.UsingNomaiRemoteCamera();
}
}

View File

@ -1,4 +1,6 @@
using HarmonyLib;
using System.Collections;
using UnityEngine.InputSystem;
namespace NewHorizons.Patches.DialoguePatches
{
@ -7,6 +9,29 @@ namespace NewHorizons.Patches.DialoguePatches
{
private static bool _wasLastDialogueInactive = false;
[HarmonyPostfix]
[HarmonyPatch(nameof(RemoteDialogueTrigger.Awake))]
public static void RemoteDialogueTrigger_Awake(RemoteDialogueTrigger __instance)
{
// Wait for player to be up and moving before allowing them to trigger remote dialogue
// Stops you getting locked into dialogue while waking up
if (OWInput.GetInputMode() != InputMode.Character)
{
__instance._collider.enabled = false;
__instance.StartCoroutine(AwakeCoroutine(__instance));
}
}
private static IEnumerator AwakeCoroutine(RemoteDialogueTrigger instance)
{
while (OWInput.GetInputMode() != InputMode.Character)
{
yield return null;
}
instance._collider.enabled = true;
}
/// <summary>
/// Should fix a bug where disabled a CharacterDialogueTree makes its related RemoteDialogueTriggers softlock your game
/// </summary>

View File

@ -1,6 +1,7 @@
using HarmonyLib;
using NewHorizons.Components.Sectored;
using NewHorizons.Handlers;
using NewHorizons.Utility.OWML;
namespace NewHorizons.Patches.HUDPatches
{
@ -27,15 +28,21 @@ namespace NewHorizons.Patches.HUDPatches
[HarmonyPatch(nameof(ProbeHUDMarker.RefreshOwnVisibility))]
public static bool ProbeHUDMarker_RefreshOwnVisibility(ProbeHUDMarker __instance)
{
// Probe marker seems to never appear in the eye or QM in base game (inside eye being past the vortex) ?? at least thats what its code implies
bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye();
bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsProbeInside());
bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside == Locator.GetRingWorldController().isProbeInside;
bool insideIP = Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isProbeInsideCloak;
bool insideCloak = CloakSectorController.isPlayerInside == CloakSectorController.isProbeInside;
// Either the controllers wtv are null or the player and probe state are the same
bool sameRW = Locator.GetRingWorldController() == null || Locator.GetRingWorldController().isPlayerInside == Locator.GetRingWorldController().isProbeInside;
bool sameIP = Locator.GetCloakFieldController() == null || Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isProbeInsideCloak;
bool sameCloak = CloakSectorController.isPlayerInside == CloakSectorController.isProbeInside;
bool sameInterference = InterferenceHandler.IsPlayerSameAsProbe();
bool isActive = __instance.gameObject.activeInHierarchy || __instance._isTLCDuplicate;
__instance._isVisible = isActive && !insideEYE && !insideQM && !__instance._translatorEquipped && !__instance._inConversation && __instance._launched && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideRW && insideIP && insideCloak && sameInterference;
__instance._isVisible = isActive && !insideEYE && !insideQM && !__instance._translatorEquipped
&& !__instance._inConversation && __instance._launched && (__instance._isWearingHelmet || __instance._atFlightConsole)
&& sameRW && sameIP && sameCloak && sameInterference;
if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible);

View File

@ -85,12 +85,8 @@ namespace NewHorizons.Patches.PlayerPatches
[HarmonyPatch(nameof(PlayerData.KnowsMultipleFrequencies))]
public static bool PlayerData_KnowsMultipleFrequencies(ref bool __result)
{
if (NewHorizonsData.KnowsMultipleFrequencies())
{
__result = true;
return false;
}
return true;
__result = NewHorizonsData.KnowsMultipleFrequencies();
return false;
}
[HarmonyPrefix]
@ -140,5 +136,12 @@ namespace NewHorizons.Patches.PlayerPatches
{
NewHorizonsData.Reset();
}
[HarmonyPostfix]
[HarmonyPatch(nameof(PlayerData.SaveCurrentGame))]
public static void PlayerData_SaveCurrentGame()
{
NewHorizonsData.Save();
}
}
}

View File

@ -25,9 +25,32 @@ namespace NewHorizons.Patches.ShipLogPatches
}
}
[HarmonyPrefix]
[HarmonyPatch(nameof(ShipLogAstroObject.UpdateState))]
public static bool ShipLogAstroObject_UpdateState_Pre(ShipLogAstroObject __instance)
{
// Custom astro objects might have no entries, in this case they will be permanently hidden
// Just treat it as if it were revealed
if (__instance._entries.Count == 0)
{
__instance._state = ShipLogEntry.State.Explored;
__instance._imageObj.SetActive(true);
__instance._outlineObj?.SetActive(false);
if (__instance._image != null)
{
__instance.SetMaterialGreyscale(false);
__instance._image.color = Color.white;
}
return false;
}
return true;
}
[HarmonyPostfix]
[HarmonyPatch(nameof(ShipLogAstroObject.UpdateState))]
public static void ShipLogAstroObject_UpdateState(ShipLogAstroObject __instance)
public static void ShipLogAstroObject_UpdateState_Post(ShipLogAstroObject __instance)
{
Transform detailsParent = __instance.transform.Find("Details");
if (detailsParent != null)

View File

@ -1,5 +1,6 @@
using HarmonyLib;
using NewHorizons.Builder.Props.Audio;
using NewHorizons.Utility.OWML;
namespace NewHorizons.Patches.SignalPatches
{
@ -19,13 +20,18 @@ namespace NewHorizons.Patches.SignalPatches
{
var count = SignalBuilder.NumberOfFrequencies;
__instance._frequencyFilterIndex += increment;
// Base game does 1 here but we use frequency index 0 as "default" or "???"
__instance._frequencyFilterIndex = __instance._frequencyFilterIndex >= count ? 0 : __instance._frequencyFilterIndex;
__instance._frequencyFilterIndex = __instance._frequencyFilterIndex < 0 ? count - 1 : __instance._frequencyFilterIndex;
var signalFrequency = AudioSignal.IndexToFrequency(__instance._frequencyFilterIndex);
NHLogger.Log($"Changed freq to {signalFrequency} at {__instance._frequencyFilterIndex}");
// Skip over this frequency
var isUnknown = !PlayerData.KnowsFrequency(signalFrequency) && !(__instance._isUnknownFreqNearby && __instance._unknownFrequency == signalFrequency);
if (isUnknown || !SignalBuilder.IsFrequencyInUse(signalFrequency))
// Never skip traveler (always known)
var isTraveler = __instance._frequencyFilterIndex == 1;
var isUnknown = !PlayerData.KnowsFrequency(signalFrequency) && (!__instance._isUnknownFreqNearby || __instance._unknownFrequency != signalFrequency);
if (!isTraveler && (isUnknown || !SignalBuilder.IsFrequencyInUse(signalFrequency)))
{
__instance.SwitchFrequencyFilter(increment);
}

View File

@ -26,5 +26,25 @@ namespace NewHorizons.Patches.VolumePatches
return false;
}
/// <summary>
/// This method detects Nomai shuttles that are inactive
/// When active, it swaps the position of the NomaiShuttleController and the Rigidbody, so its not found as a child here and explodes continuously forever
/// Just ignore the shuttle if its inactive
/// </summary>
[HarmonyPrefix]
[HarmonyPatch(nameof(DestructionVolume.VanishNomaiShuttle))]
public static bool DestructionVolume_VanishNomaiShuttle(DestructionVolume __instance, OWRigidbody shuttleBody, RelativeLocationData entryLocation)
{
if (shuttleBody.GetComponentInChildren<NomaiShuttleController>() == null)
{
if (__instance._nomaiShuttleBody == shuttleBody)
{
__instance._nomaiShuttleBody = null;
}
return false;
}
return true;
}
}
}

View File

@ -1429,6 +1429,22 @@
"description": "The direction the item will be oriented when dropping it on the ground. Defaults to up (0, 1, 0).",
"$ref": "#/definitions/MVector3"
},
"holdOffset": {
"description": "A relative offset to apply to the item's position when holding it. The initial position varies for vanilla item types.",
"$ref": "#/definitions/MVector3"
},
"holdRotation": {
"description": "A relative offset to apply to the item's rotation when holding it.",
"$ref": "#/definitions/MVector3"
},
"socketOffset": {
"description": "A relative offset to apply to the item's position when placing it into a socket.",
"$ref": "#/definitions/MVector3"
},
"socketRotation": {
"description": "A relative offset to apply to the item's rotation when placing it into a socket.",
"$ref": "#/definitions/MVector3"
},
"pickupAudio": {
"type": "string",
"description": "The audio to play when this item is picked up. Only applies to custom/non-vanilla item types.\nCan be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list."

View File

@ -3,6 +3,7 @@ using NewHorizons.Utility.Files;
using NewHorizons.Utility.OWML;
using OWML.Common;
using OWML.Common.Menus;
using OWML.Utils;
using System;
namespace NewHorizons.Utility.DebugTools
@ -10,22 +11,18 @@ namespace NewHorizons.Utility.DebugTools
public static class DebugReload
{
private static IModButton _reloadButton;
private static SubmitAction _reloadButton;
public static void InitializePauseMenu()
public static void InitializePauseMenu(IPauseMenuManager pauseMenu)
{
_reloadButton = Main.Instance.ModHelper.Menus.PauseMenu.OptionsButton.Duplicate(TranslationHandler.GetTranslation("Reload Configs", TranslationHandler.TextType.UI).ToUpper());
_reloadButton.OnClick += ReloadConfigs;
_reloadButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Reload Configs", TranslationHandler.TextType.UI).ToUpper(), 3, true);
_reloadButton.OnSubmitAction += ReloadConfigs;
UpdateReloadButton();
}
public static void UpdateReloadButton()
{
if (_reloadButton != null)
{
if (Main.Debug) _reloadButton.Show();
else _reloadButton.Hide();
}
_reloadButton?.SetButtonVisible(Main.Debug);
}
private static void ReloadConfigs()

View File

@ -5,6 +5,7 @@ using NewHorizons.Utility.OWML;
using Newtonsoft.Json;
using OWML.Common;
using OWML.Common.Menus;
using OWML.Utils;
using System;
using System.Collections.Generic;
using System.IO;
@ -15,7 +16,7 @@ namespace NewHorizons.Utility.DebugTools.Menu
{
class DebugMenu : MonoBehaviour
{
private static IModButton pauseMenuButton;
private static SubmitAction pauseMenuButton;
public GUIStyle _editorMenuStyle;
public GUIStyle _tabBarStyle;
@ -23,7 +24,6 @@ namespace NewHorizons.Utility.DebugTools.Menu
internal Vector2 EditorMenuSize = new Vector2(600, 900);
bool menuOpen = false;
static bool openMenuOnPause;
static bool staticInitialized;
// Menu params
internal static IModBehaviour loadedMod = null;
@ -35,6 +35,8 @@ namespace NewHorizons.Utility.DebugTools.Menu
private List<DebugSubmenu> submenus;
private int activeSubmenu = 0;
private static DebugMenu _instance;
internal static JsonSerializerSettings jsonSettings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
@ -55,28 +57,13 @@ namespace NewHorizons.Utility.DebugTools.Menu
private void Start()
{
if (!staticInitialized)
{
staticInitialized = true;
_instance = this;
Main.Instance.ModHelper.Menus.PauseMenu.OnInit += PauseMenuInitHook;
Main.Instance.ModHelper.Menus.PauseMenu.OnClosed += CloseMenu;
Main.Instance.ModHelper.Menus.PauseMenu.OnOpened += RestoreMenuOpennessState;
Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuOpened += OnOpenMenu;
Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuClosed += OnCloseMenu;
Main.Instance.OnChangeStarSystem.AddListener(OnChangeStarSystem);
PauseMenuInitHook();
Main.Instance.OnChangeStarSystem.AddListener((string s) => {
if (saveButtonUnlocked)
{
SaveLoadedConfigsForRecentSystem();
saveButtonUnlocked = false;
}
});
}
else
{
InitMenu();
}
InitMenu();
if (loadedMod != null)
{
@ -84,26 +71,38 @@ namespace NewHorizons.Utility.DebugTools.Menu
}
}
private void PauseMenuInitHook()
public void OnDestroy()
{
pauseMenuButton = Main.Instance.ModHelper.Menus.PauseMenu.OptionsButton.Duplicate(TranslationHandler.GetTranslation("Toggle Dev Tools Menu", TranslationHandler.TextType.UI).ToUpper());
InitMenu();
Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuOpened -= OnOpenMenu;
Main.Instance.ModHelper.MenuHelper.PauseMenuManager.PauseMenuClosed -= OnCloseMenu;
Main.Instance.OnChangeStarSystem.RemoveListener(OnChangeStarSystem);
}
private void OnChangeStarSystem(string _)
{
if (saveButtonUnlocked)
{
SaveLoadedConfigsForRecentSystem();
saveButtonUnlocked = false;
}
}
public static void InitializePauseMenu(IPauseMenuManager pauseMenu)
{
pauseMenuButton = pauseMenu.MakeSimpleButton(TranslationHandler.GetTranslation("Toggle Dev Tools Menu", TranslationHandler.TextType.UI).ToUpper(), 3, true);
_instance?.InitMenu();
}
public static void UpdatePauseMenuButton()
{
if (pauseMenuButton != null)
{
if (Main.Debug) pauseMenuButton.Show();
else pauseMenuButton.Hide();
}
pauseMenuButton?.SetButtonVisible(Main.Debug);
}
private void RestoreMenuOpennessState() { menuOpen = openMenuOnPause; }
private void OnOpenMenu() { menuOpen = openMenuOnPause; }
private void ToggleMenu() { menuOpen = !menuOpen; openMenuOnPause = !openMenuOnPause; }
private void CloseMenu() { menuOpen = false; }
private void OnCloseMenu() { menuOpen = false; }
private void OnGUI()
{
@ -284,7 +283,7 @@ namespace NewHorizons.Utility.DebugTools.Menu
UpdatePauseMenuButton();
// TODO: figure out how to clear this event list so that we don't pile up useless instances of the DebugMenu that can't get garbage collected
pauseMenuButton.OnClick += ToggleMenu;
pauseMenuButton.OnSubmitAction += ToggleMenu;
submenus.ForEach(submenu => submenu.OnInit(this));

View File

@ -19,10 +19,17 @@ namespace NewHorizons.Utility.OWML
Main.Instance.ModHelper.Console.WriteLine($"{Enum.GetName(typeof(LogType), type)} : {text}", LogTypeToMessageType(type));
}
public static void LogVerbose(params object[] obj) => LogVerbose(string.Join(", ", obj));
public static void LogVerbose(object text) => Log(text, LogType.Verbose);
public static void Log(object text) => Log(text, LogType.Log);
public static void Log(params object[] obj) => Log(string.Join(", ", obj));
public static void LogWarning(object text) => Log(text, LogType.Warning);
public static void LogWarning(params object[] obj) => LogWarning(string.Join(", ", obj));
public static void LogError(object text) => Log(text, LogType.Error);
public static void LogError(params object[] obj) => LogError(string.Join(", ", obj));
public enum LogType
{

View File

@ -4,9 +4,9 @@
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, Clay, Trifid, and friends",
"name": "New Horizons",
"uniqueName": "xen.NewHorizons",
"version": "1.19.3",
"owmlVersion": "2.9.8",
"dependencies": [ "JohnCorby.VanillaFix", "_nebula.MenuFramework", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
"version": "1.19.9",
"owmlVersion": "2.10.3",
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "PacificEngine.OW_CommonResources" ],
"pathsToPreserve": [ "planets", "systems", "translations" ],
"donateLink": "https://www.patreon.com/ownh"

View File

@ -30,7 +30,7 @@ Once in VSCode, paste this code into the file:
```json title="wetrock.json"
{
"name": "Wetrock",
"$schema": "https://raw.githubusercontent.com/Outer-Wilds-New-Horizons/new-horizons/main/NewHorizons/Schemas/body_schema.json",
"$schema": "https://raw.githubusercontent.com/Outer-Wilds-New-Horizons/new-horizons/main/NewHorizons/Schemas/body_schema.json",
"starSystem": "SolarSystem",
"Base": {
"groundSize": 100,