mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
v1.13.0 (#669)
## Major features - New API methods to: Add ship logs from xml, add dialogue from xml, create a new planet from json string. All of these methods work directly with strings or XElements and don't load files on their own. ## Improvements - Pitch anglerfish sounds based on scale. Resolves #160. ## Bug fixes - Fixes ship being broken when spawning on the center of the universe. Resolves #648 - Fix Stranger cloak breaking on second loop onwards. Resolves #673.
This commit is contained in:
commit
07f67484d1
@ -13,6 +13,9 @@ namespace NewHorizons.Builder.General
|
|||||||
public static class SpawnPointBuilder
|
public static class SpawnPointBuilder
|
||||||
{
|
{
|
||||||
private static bool suitUpQueued = false;
|
private static bool suitUpQueued = false;
|
||||||
|
public static SpawnPoint ShipSpawn { get; private set; }
|
||||||
|
public static Vector3 ShipSpawnOffset { get; private set; }
|
||||||
|
|
||||||
public static SpawnPoint Make(GameObject planetGO, SpawnModule module, OWRigidbody owRigidBody)
|
public static SpawnPoint Make(GameObject planetGO, SpawnModule module, OWRigidbody owRigidBody)
|
||||||
{
|
{
|
||||||
SpawnPoint playerSpawn = null;
|
SpawnPoint playerSpawn = null;
|
||||||
@ -35,41 +38,21 @@ namespace NewHorizons.Builder.General
|
|||||||
|
|
||||||
if (module.shipSpawn != null)
|
if (module.shipSpawn != null)
|
||||||
{
|
{
|
||||||
GameObject spawnGO = GeneralPropBuilder.MakeNew("ShipSpawnPoint", planetGO, null, module.shipSpawn);
|
var spawnGO = GeneralPropBuilder.MakeNew("ShipSpawnPoint", planetGO, null, module.shipSpawn);
|
||||||
spawnGO.SetActive(false);
|
spawnGO.SetActive(false);
|
||||||
spawnGO.layer = Layer.PlayerSafetyCollider;
|
spawnGO.layer = Layer.PlayerSafetyCollider;
|
||||||
|
|
||||||
var shipSpawn = spawnGO.AddComponent<SpawnPoint>();
|
ShipSpawn = spawnGO.AddComponent<SpawnPoint>();
|
||||||
shipSpawn._isShipSpawn = true;
|
ShipSpawn._isShipSpawn = true;
|
||||||
shipSpawn._attachedBody = owRigidBody;
|
ShipSpawn._attachedBody = owRigidBody;
|
||||||
shipSpawn._spawnLocation = SpawnLocation.None;
|
ShipSpawn._spawnLocation = SpawnLocation.None;
|
||||||
|
|
||||||
// #601 we need to actually set the right trigger volumes here
|
// #601 we need to actually set the right trigger volumes here
|
||||||
shipSpawn._triggerVolumes = new OWTriggerVolume[0];
|
ShipSpawn._triggerVolumes = new OWTriggerVolume[0];
|
||||||
|
|
||||||
// TODO: this should happen elsewhere
|
ShipSpawnOffset = module.shipSpawn.offset ?? (module.shipSpawn.alignRadial.GetValueOrDefault() ? Vector3.up * 4 : Vector3.zero);
|
||||||
var ship = SearchUtilities.Find("Ship_Body");
|
|
||||||
if (ship != null)
|
|
||||||
{
|
|
||||||
ship.transform.position = spawnGO.transform.position;
|
|
||||||
ship.transform.rotation = spawnGO.transform.rotation;
|
|
||||||
|
|
||||||
// Move it up a bit more when aligning to surface
|
|
||||||
if (module.shipSpawn.offset != null)
|
|
||||||
{
|
|
||||||
ship.transform.position += spawnGO.transform.TransformDirection(module.shipSpawn.offset);
|
|
||||||
}
|
|
||||||
else if (module.shipSpawn.alignRadial.GetValueOrDefault())
|
|
||||||
{
|
|
||||||
ship.transform.position += ship.transform.up * 4f;
|
|
||||||
}
|
|
||||||
|
|
||||||
ship.GetRequiredComponent<MatchInitialMotion>().SetBodyToMatch(owRigidBody);
|
|
||||||
}
|
|
||||||
spawnGO.SetActive(true);
|
spawnGO.SetActive(true);
|
||||||
|
|
||||||
// Ship doesn't get activated sometimes
|
|
||||||
Delay.RunWhen(() => Main.IsSystemReady, () => ship.gameObject.SetActive(true));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Main.Instance.IsWarpingFromVessel || (!Main.Instance.IsWarpingFromShip && (module.playerSpawn?.startWithSuit ?? false))) && !suitUpQueued)
|
if ((Main.Instance.IsWarpingFromVessel || (!Main.Instance.IsWarpingFromShip && (module.playerSpawn?.startWithSuit ?? false))) && !suitUpQueued)
|
||||||
|
|||||||
@ -7,6 +7,7 @@ using NewHorizons.Utility.OWML;
|
|||||||
using OWML.Common;
|
using OWML.Common;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Xml;
|
using System.Xml;
|
||||||
|
using System.Xml.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace NewHorizons.Builder.Props
|
namespace NewHorizons.Builder.Props
|
||||||
@ -15,6 +16,14 @@ namespace NewHorizons.Builder.Props
|
|||||||
{
|
{
|
||||||
// Returns the character dialogue tree and remote dialogue trigger, if applicable.
|
// Returns the character dialogue tree and remote dialogue trigger, if applicable.
|
||||||
public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, Sector sector, DialogueInfo info, IModBehaviour mod)
|
public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, Sector sector, DialogueInfo info, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
var xml = File.ReadAllText(Path.Combine(mod.ModHelper.Manifest.ModFolderPath, info.xmlFile));
|
||||||
|
var dialogueName = Path.GetFileNameWithoutExtension(info.xmlFile);
|
||||||
|
return Make(go, sector, info, xml, dialogueName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create dialogue directly from xml string instead of loading it from a file
|
||||||
|
public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, Sector sector, DialogueInfo info, string xml, string dialogueName)
|
||||||
{
|
{
|
||||||
NHLogger.LogVerbose($"[DIALOGUE] Created a new character dialogue [{info.rename}] on [{info.parentPath}]");
|
NHLogger.LogVerbose($"[DIALOGUE] Created a new character dialogue [{info.rename}] on [{info.parentPath}]");
|
||||||
|
|
||||||
@ -26,7 +35,7 @@ namespace NewHorizons.Builder.Props
|
|||||||
return (null, null);
|
return (null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dialogue = MakeConversationZone(go, sector, info, mod.ModHelper);
|
var dialogue = MakeConversationZone(go, sector, info, xml, dialogueName);
|
||||||
|
|
||||||
RemoteDialogueTrigger remoteTrigger = null;
|
RemoteDialogueTrigger remoteTrigger = null;
|
||||||
if (info.remoteTrigger != null)
|
if (info.remoteTrigger != null)
|
||||||
@ -76,7 +85,7 @@ namespace NewHorizons.Builder.Props
|
|||||||
return remoteDialogueTrigger;
|
return remoteDialogueTrigger;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, Sector sector, DialogueInfo info, IModHelper mod)
|
private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, Sector sector, DialogueInfo info, string xml, string dialogueName)
|
||||||
{
|
{
|
||||||
var conversationZone = GeneralPropBuilder.MakeNew("ConversationZone", planetGO, sector, info, defaultParentPath: info.pathToAnimController);
|
var conversationZone = GeneralPropBuilder.MakeNew("ConversationZone", planetGO, sector, info, defaultParentPath: info.pathToAnimController);
|
||||||
|
|
||||||
@ -100,13 +109,11 @@ namespace NewHorizons.Builder.Props
|
|||||||
|
|
||||||
var dialogueTree = conversationZone.AddComponent<NHCharacterDialogueTree>();
|
var dialogueTree = conversationZone.AddComponent<NHCharacterDialogueTree>();
|
||||||
|
|
||||||
var xml = File.ReadAllText(Path.Combine(mod.Manifest.ModFolderPath, info.xmlFile));
|
|
||||||
var text = new TextAsset(xml)
|
var text = new TextAsset(xml)
|
||||||
{
|
{
|
||||||
// Text assets need a name to be used with VoiceMod
|
// Text assets need a name to be used with VoiceMod
|
||||||
name = Path.GetFileNameWithoutExtension(info.xmlFile)
|
name = dialogueName
|
||||||
};
|
};
|
||||||
|
|
||||||
dialogueTree.SetTextXml(text);
|
dialogueTree.SetTextXml(text);
|
||||||
AddTranslation(xml);
|
AddTranslation(xml);
|
||||||
|
|
||||||
|
|||||||
@ -55,15 +55,20 @@ namespace NewHorizons.Builder.ShipLog
|
|||||||
{
|
{
|
||||||
string systemName = body.Config.starSystem;
|
string systemName = body.Config.starSystem;
|
||||||
XElement astroBodyFile = XElement.Load(Path.Combine(body.Mod.ModHelper.Manifest.ModFolderPath, body.Config.ShipLog.xmlFile));
|
XElement astroBodyFile = XElement.Load(Path.Combine(body.Mod.ModHelper.Manifest.ModFolderPath, body.Config.ShipLog.xmlFile));
|
||||||
XElement astroBodyId = astroBodyFile.Element("ID");
|
AddShipLogXML(manager, astroBodyFile, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void AddShipLogXML(ShipLogManager manager, XElement xml, NewHorizonsBody body)
|
||||||
|
{
|
||||||
|
XElement astroBodyId = xml.Element("ID");
|
||||||
if (astroBodyId == null)
|
if (astroBodyId == null)
|
||||||
{
|
{
|
||||||
NHLogger.LogError("Failed to load ship logs for " + systemName + "!");
|
NHLogger.LogError("Failed to load ship logs for " + body.Config.name + "!");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var entryIDs = new List<string>();
|
var entryIDs = new List<string>();
|
||||||
foreach (XElement entryElement in astroBodyFile.DescendantsAndSelf("Entry"))
|
foreach (XElement entryElement in xml.DescendantsAndSelf("Entry"))
|
||||||
{
|
{
|
||||||
XElement curiosityName = entryElement.Element("Curiosity");
|
XElement curiosityName = entryElement.Element("Curiosity");
|
||||||
XElement id = entryElement.Element("ID");
|
XElement id = entryElement.Element("ID");
|
||||||
@ -98,8 +103,8 @@ namespace NewHorizons.Builder.ShipLog
|
|||||||
}
|
}
|
||||||
AddTranslation(entryElement);
|
AddTranslation(entryElement);
|
||||||
}
|
}
|
||||||
TextAsset newAsset = new TextAsset(astroBodyFile.ToString());
|
var newAsset = new TextAsset(xml.ToString());
|
||||||
List<TextAsset> newBodies = new List<TextAsset>(manager._shipLogXmlAssets) { newAsset };
|
var newBodies = new List<TextAsset>(manager._shipLogXmlAssets) { newAsset };
|
||||||
manager._shipLogXmlAssets = newBodies.ToArray();
|
manager._shipLogXmlAssets = newBodies.ToArray();
|
||||||
ShipLogHandler.AddConfig(astroBodyId.Value, entryIDs, body);
|
ShipLogHandler.AddConfig(astroBodyId.Value, entryIDs, body);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using NewHorizons.Components.Stars;
|
using NewHorizons.Components.Stars;
|
||||||
using NewHorizons.Handlers;
|
using NewHorizons.Handlers;
|
||||||
using NewHorizons.Utility.OWML;
|
using NewHorizons.Utility.OWML;
|
||||||
|
using System.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
namespace NewHorizons.Components.EOTE
|
namespace NewHorizons.Components.EOTE
|
||||||
@ -11,6 +12,8 @@ namespace NewHorizons.Components.EOTE
|
|||||||
private CloakFieldController _currentController;
|
private CloakFieldController _currentController;
|
||||||
|
|
||||||
public void Start()
|
public void Start()
|
||||||
|
{
|
||||||
|
if (CloakHandler.Cloaks.Any())
|
||||||
{
|
{
|
||||||
// Enable and disable all cloaks, else Stranger state is weird at the start
|
// Enable and disable all cloaks, else Stranger state is weird at the start
|
||||||
foreach (var cloak in CloakHandler.Cloaks)
|
foreach (var cloak in CloakHandler.Cloaks)
|
||||||
@ -18,6 +21,10 @@ namespace NewHorizons.Components.EOTE
|
|||||||
SetCurrentCloak(cloak);
|
SetCurrentCloak(cloak);
|
||||||
cloak.enabled = false;
|
cloak.enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure a cloak is enabled
|
||||||
|
SetCurrentCloak(CloakHandler.Cloaks.First());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always makes sure the Locator's cloak field controller is the one that is between the player and the sun
|
// Always makes sure the Locator's cloak field controller is the one that is between the player and the sun
|
||||||
|
|||||||
@ -201,6 +201,8 @@ namespace NewHorizons.Components.Ship
|
|||||||
|
|
||||||
GlobalMessenger.FireEvent("EnterShip");
|
GlobalMessenger.FireEvent("EnterShip");
|
||||||
PlayerState.OnEnterShip();
|
PlayerState.OnEnterShip();
|
||||||
|
|
||||||
|
PlayerSpawnHandler.SpawnShip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,6 +14,11 @@ namespace NewHorizons.External.SerializableData
|
|||||||
this.a = a;
|
this.a = a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static MColor FromColor(Color color)
|
||||||
|
{
|
||||||
|
return new MColor((int)(color.r * 255), (int)(color.g * 255), (int)(color.b * 255), (int)(color.a * 255));
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The red component of this colour from 0-255, higher values will make the colour glow if applicable.
|
/// The red component of this colour from 0-255, higher values will make the colour glow if applicable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using NewHorizons.Builder.General;
|
||||||
using NewHorizons.Utility;
|
using NewHorizons.Utility;
|
||||||
using NewHorizons.Utility.OWML;
|
using NewHorizons.Utility.OWML;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
@ -45,35 +46,73 @@ namespace NewHorizons.Handlers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SpawnShip()
|
||||||
|
{
|
||||||
|
var ship = SearchUtilities.Find("Ship_Body");
|
||||||
|
if (ship != null)
|
||||||
|
{
|
||||||
|
ship.SetActive(true);
|
||||||
|
|
||||||
|
var pos = SpawnPointBuilder.ShipSpawn.transform.position;
|
||||||
|
|
||||||
|
// Move it up a bit more when aligning to surface
|
||||||
|
if (SpawnPointBuilder.ShipSpawnOffset != null)
|
||||||
|
{
|
||||||
|
pos += SpawnPointBuilder.ShipSpawn.transform.TransformDirection(SpawnPointBuilder.ShipSpawnOffset);
|
||||||
|
}
|
||||||
|
|
||||||
|
SpawnBody(ship.GetAttachedOWRigidbody(), SpawnPointBuilder.ShipSpawn, pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static IEnumerator SpawnCoroutine(int length)
|
private static IEnumerator SpawnCoroutine(int length)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < length; i++)
|
for(int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
FixVelocity();
|
FixPlayerVelocity();
|
||||||
yield return new WaitForEndOfFrame();
|
yield return new WaitForEndOfFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
InvulnerabilityHandler.MakeInvulnerable(false);
|
InvulnerabilityHandler.MakeInvulnerable(false);
|
||||||
|
|
||||||
|
if (!Main.Instance.IsWarpingFromShip)
|
||||||
|
{
|
||||||
|
if (SpawnPointBuilder.ShipSpawn != null)
|
||||||
|
{
|
||||||
|
NHLogger.Log("Spawning player ship");
|
||||||
|
SpawnShip();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NHLogger.Log("System has no ship spawn. Deactivating it.");
|
||||||
|
SearchUtilities.Find("Ship_Body")?.SetActive(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void FixVelocity()
|
private static void FixPlayerVelocity()
|
||||||
{
|
{
|
||||||
var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody();
|
var playerBody = SearchUtilities.Find("Player_Body").GetAttachedOWRigidbody();
|
||||||
var spawn = GetDefaultSpawn();
|
|
||||||
var resources = playerBody.GetComponent<PlayerResources>();
|
var resources = playerBody.GetComponent<PlayerResources>();
|
||||||
|
|
||||||
playerBody.WarpToPositionRotation(spawn.transform.position, spawn.transform.rotation);
|
SpawnBody(playerBody, GetDefaultSpawn());
|
||||||
|
|
||||||
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._currentHealth = 100f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SpawnBody(OWRigidbody body, SpawnPoint spawn, Vector3? positionOverride = null)
|
||||||
|
{
|
||||||
|
var pos = positionOverride ?? spawn.transform.position;
|
||||||
|
|
||||||
|
body.WarpToPositionRotation(pos, spawn.transform.rotation);
|
||||||
|
|
||||||
|
var spawnVelocity = spawn._attachedBody.GetVelocity();
|
||||||
|
var spawnAngularVelocity = spawn._attachedBody.GetPointTangentialVelocity(pos);
|
||||||
|
var velocity = spawnVelocity + spawnAngularVelocity;
|
||||||
|
|
||||||
|
body.SetVelocity(velocity);
|
||||||
|
}
|
||||||
|
|
||||||
private static Vector3 CalculateMatchVelocity(OWRigidbody owRigidbody, OWRigidbody bodyToMatch, bool ignoreAngularVelocity)
|
private static Vector3 CalculateMatchVelocity(OWRigidbody owRigidbody, OWRigidbody bodyToMatch, bool ignoreAngularVelocity)
|
||||||
{
|
{
|
||||||
var vector = Vector3.zero;
|
var vector = Vector3.zero;
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
using OWML.Common;
|
using OWML.Common;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Xml.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
|
|
||||||
@ -8,11 +9,13 @@ namespace NewHorizons
|
|||||||
{
|
{
|
||||||
public interface INewHorizons
|
public interface INewHorizons
|
||||||
{
|
{
|
||||||
|
#region Obsolete
|
||||||
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
||||||
void Create(Dictionary<string, object> config);
|
void Create(Dictionary<string, object> config);
|
||||||
|
|
||||||
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
|
||||||
void Create(Dictionary<string, object> config, IModBehaviour mod);
|
void Create(Dictionary<string, object> config, IModBehaviour mod);
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Will load all configs in the regular folders (planets, systems, translations, etc) for this mod.
|
/// Will load all configs in the regular folders (planets, systems, translations, etc) for this mod.
|
||||||
@ -26,11 +29,30 @@ namespace NewHorizons
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
GameObject GetPlanet(string name);
|
GameObject GetPlanet(string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the uniqueIDs of each installed NH addon.
|
||||||
|
/// </summary>
|
||||||
|
string[] GetInstalledAddons();
|
||||||
|
|
||||||
|
#region Get/set/change star system
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The name of the current star system loaded.
|
/// The name of the current star system loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string GetCurrentStarSystem();
|
string GetCurrentStarSystem();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to overwrite the default system. This is where the player is respawned after dying.
|
||||||
|
/// </summary>
|
||||||
|
bool SetDefaultSystem(string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows you to instantly begin a warp to a new star system.
|
||||||
|
/// Will return false if that system does not exist (cannot be warped to).
|
||||||
|
/// </summary>
|
||||||
|
bool ChangeCurrentStarSystem(string name);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region events
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An event invoked when the player begins loading the new star system, before the scene starts to load.
|
/// An event invoked when the player begins loading the new star system, before the scene starts to load.
|
||||||
/// Gives the name of the star system being switched to.
|
/// Gives the name of the star system being switched to.
|
||||||
@ -48,7 +70,9 @@ namespace NewHorizons
|
|||||||
/// Gives the name of the planet that was just loaded.
|
/// Gives the name of the planet that was just loaded.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
UnityEvent<string> GetBodyLoadedEvent();
|
UnityEvent<string> GetBodyLoadedEvent();
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Querying configs
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Uses JSONPath to query a body
|
/// Uses JSONPath to query a body
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -68,23 +92,9 @@ namespace NewHorizons
|
|||||||
/// Uses JSONPath to query the current star system
|
/// Uses JSONPath to query the current star system
|
||||||
///</summary>
|
///</summary>
|
||||||
T QuerySystem<T>(string path);
|
T QuerySystem<T>(string path);
|
||||||
|
#endregion
|
||||||
|
|
||||||
/// <summary>
|
#region Spawn props
|
||||||
/// Allows you to overwrite the default system. This is where the player is respawned after dying.
|
|
||||||
/// </summary>
|
|
||||||
bool SetDefaultSystem(string name);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Allows you to instantly begin a warp to a new star system.
|
|
||||||
/// Will return false if that system does not exist (cannot be warped to).
|
|
||||||
/// </summary>
|
|
||||||
bool ChangeCurrentStarSystem(string name);
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Returns the uniqueIDs of each installed NH addon.
|
|
||||||
/// </summary>
|
|
||||||
string[] GetInstalledAddons();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows you to spawn a copy of a prop by specifying its path.
|
/// Allows you to spawn a copy of a prop by specifying its path.
|
||||||
/// This is the same as using Props->details in a config, but also returns the spawned gameObject to you.
|
/// This is the same as using Props->details in a config, but also returns the spawned gameObject to you.
|
||||||
@ -109,5 +119,44 @@ namespace NewHorizons
|
|||||||
(CharacterDialogueTree, RemoteDialogueTrigger) SpawnDialogue(IModBehaviour mod, GameObject root, string xmlFile, float radius = 1f,
|
(CharacterDialogueTree, RemoteDialogueTrigger) SpawnDialogue(IModBehaviour mod, GameObject root, string xmlFile, float radius = 1f,
|
||||||
float range = 1f, string blockAfterPersistentCondition = null, float lookAtRadius = 1f, string pathToAnimController = null,
|
float range = 1f, string blockAfterPersistentCondition = null, float lookAtRadius = 1f, string pathToAnimController = null,
|
||||||
float remoteTriggerRadius = 0f);
|
float remoteTriggerRadius = 0f);
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Load json/xml directly
|
||||||
|
/// <summary>
|
||||||
|
/// Allows creation of a planet by directly passing the json contents as a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="config"></param>
|
||||||
|
/// <param name="mod"></param>
|
||||||
|
void CreatePlanet(string config, IModBehaviour mod);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows defining details of a star system by directly passing the json contents as a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name"></param>
|
||||||
|
/// <param name="config"></param>
|
||||||
|
/// <param name="mod"></param>
|
||||||
|
void DefineStarSystem(string name, string config, IModBehaviour mod);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Allows creation of dialogue by directly passing the xml and dialogueInfo json contents as strings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="textAssetID">TextAsset name used for compatibility with voice mod. Just has to be a unique identifier.</param>
|
||||||
|
/// <param name="xml">The contents of the dialogue xml file as a string</param>
|
||||||
|
/// <param name="dialogueInfo">The json dialogue info as a string. See the documentation/schema for what this can contain.</param>
|
||||||
|
/// <param name="planetGO">The root planet rigidbody that this dialogue is attached to. Any paths in the dialogueInfo are relative to this body.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
(CharacterDialogueTree, RemoteDialogueTrigger) CreateDialogueFromXML(string textAssetID, string xml, string dialogueInfo, GameObject planetGO);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Directly add ship logs from XML. Call this method right before ShipLogManager awake.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mod">The mod this method is being called from. This is required for loading files.</param>
|
||||||
|
/// <param name="xml">The ship log xml contents</param>
|
||||||
|
/// <param name="planetName">The planet that these ship logs correspond to in the map mode</param>
|
||||||
|
/// <param name="imageFolder">The relative path from your mod manifest.json where the ship log images are located. The filename must be the same as the fact id. Optional.</param>
|
||||||
|
/// <param name="entryPositions">A dictionary of each fact id to its 2D position in the ship log. Optional.</param>
|
||||||
|
/// <param name="curiousityColours">A dictionary of each curiousity ID to its colour and highlight colour in the ship log. Optional.</param>
|
||||||
|
void AddShipLogXML(IModBehaviour mod, XElement xml, string planetName, string imageFolder = null, Dictionary<string, Vector2> entryPositions = null, Dictionary<string, (Color colour, Color highlight)> curiousityColours = null);
|
||||||
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -33,6 +33,7 @@ using NewHorizons.Utility.DebugTools;
|
|||||||
using NewHorizons.Utility.DebugTools.Menu;
|
using NewHorizons.Utility.DebugTools.Menu;
|
||||||
using NewHorizons.Components.Ship;
|
using NewHorizons.Components.Ship;
|
||||||
using NewHorizons.Builder.Props.Audio;
|
using NewHorizons.Builder.Props.Audio;
|
||||||
|
using Epic.OnlineServices;
|
||||||
|
|
||||||
namespace NewHorizons
|
namespace NewHorizons
|
||||||
{
|
{
|
||||||
@ -600,6 +601,33 @@ namespace NewHorizons
|
|||||||
|
|
||||||
|
|
||||||
#region Load
|
#region Load
|
||||||
|
public void LoadStarSystemConfig(string starSystemName, StarSystemConfig starSystemConfig, string relativePath, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
starSystemConfig.Migrate();
|
||||||
|
starSystemConfig.FixCoordinates();
|
||||||
|
|
||||||
|
if (starSystemConfig.startHere)
|
||||||
|
{
|
||||||
|
// We always want to allow mods to overwrite setting the main SolarSystem as default but not the other way around
|
||||||
|
if (starSystemName != "SolarSystem")
|
||||||
|
{
|
||||||
|
SetDefaultSystem(starSystemName);
|
||||||
|
_currentStarSystem = starSystemName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SystemDict.ContainsKey(starSystemName))
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(SystemDict[starSystemName].Config.travelAudio) && SystemDict[starSystemName].Config.Skybox == null)
|
||||||
|
SystemDict[starSystemName].Mod = mod;
|
||||||
|
SystemDict[starSystemName].Config.Merge(starSystemConfig);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SystemDict[starSystemName] = new NewHorizonsSystem(starSystemName, starSystemConfig, relativePath, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void LoadConfigs(IModBehaviour mod)
|
public void LoadConfigs(IModBehaviour mod)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -627,35 +655,13 @@ namespace NewHorizons
|
|||||||
|
|
||||||
foreach (var file in systemFiles)
|
foreach (var file in systemFiles)
|
||||||
{
|
{
|
||||||
var name = Path.GetFileNameWithoutExtension(file);
|
var starSystemName = Path.GetFileNameWithoutExtension(file);
|
||||||
|
|
||||||
NHLogger.LogVerbose($"Loading system {name}");
|
NHLogger.LogVerbose($"Loading system {starSystemName}");
|
||||||
|
|
||||||
var relativePath = file.Replace(folder, "");
|
var relativePath = file.Replace(folder, "");
|
||||||
var starSystemConfig = mod.ModHelper.Storage.Load<StarSystemConfig>(relativePath, false);
|
var starSystemConfig = mod.ModHelper.Storage.Load<StarSystemConfig>(relativePath, false);
|
||||||
starSystemConfig.Migrate();
|
LoadStarSystemConfig(starSystemName, starSystemConfig, relativePath, mod);
|
||||||
starSystemConfig.FixCoordinates();
|
|
||||||
|
|
||||||
if (starSystemConfig.startHere)
|
|
||||||
{
|
|
||||||
// We always want to allow mods to overwrite setting the main SolarSystem as default but not the other way around
|
|
||||||
if (name != "SolarSystem")
|
|
||||||
{
|
|
||||||
SetDefaultSystem(name);
|
|
||||||
_currentStarSystem = name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SystemDict.ContainsKey(name))
|
|
||||||
{
|
|
||||||
if (string.IsNullOrEmpty(SystemDict[name].Config.travelAudio) && SystemDict[name].Config.Skybox == null)
|
|
||||||
SystemDict[name].Mod = mod;
|
|
||||||
SystemDict[name].Config.Merge(starSystemConfig);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
SystemDict[name] = new NewHorizonsSystem(name, starSystemConfig, relativePath, mod);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (Directory.Exists(planetsFolder))
|
if (Directory.Exists(planetsFolder))
|
||||||
@ -766,6 +772,19 @@ namespace NewHorizons
|
|||||||
|
|
||||||
NHLogger.LogVerbose($"Loaded {config.name}");
|
NHLogger.LogVerbose($"Loaded {config.name}");
|
||||||
|
|
||||||
|
body = RegisterPlanetConfig(config, mod, relativePath);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Error encounter when loading {relativePath}:\n{e}");
|
||||||
|
MenuHandler.RegisterFailedConfig(Path.GetFileName(relativePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NewHorizonsBody RegisterPlanetConfig(PlanetConfig config, IModBehaviour mod, string relativePath)
|
||||||
|
{
|
||||||
if (!SystemDict.ContainsKey(config.starSystem))
|
if (!SystemDict.ContainsKey(config.starSystem))
|
||||||
{
|
{
|
||||||
// Since we didn't load it earlier there shouldn't be a star system config
|
// Since we didn't load it earlier there shouldn't be a star system config
|
||||||
@ -787,15 +806,7 @@ namespace NewHorizons
|
|||||||
config.Validate();
|
config.Validate();
|
||||||
config.Migrate();
|
config.Migrate();
|
||||||
|
|
||||||
body = new NewHorizonsBody(config, mod, relativePath);
|
return new NewHorizonsBody(config, mod, relativePath);
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
NHLogger.LogError($"Error encounter when loading {relativePath}:\n{e}");
|
|
||||||
MenuHandler.RegisterFailedConfig(Path.GetFileName(relativePath));
|
|
||||||
}
|
|
||||||
|
|
||||||
return body;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetDefaultSystem(string defaultSystem)
|
public void SetDefaultSystem(string defaultSystem)
|
||||||
|
|||||||
@ -1,10 +1,14 @@
|
|||||||
using NewHorizons.Builder.Props;
|
using NewHorizons.Builder.Props;
|
||||||
using NewHorizons.Builder.Props.Audio;
|
using NewHorizons.Builder.Props.Audio;
|
||||||
|
using NewHorizons.Builder.ShipLog;
|
||||||
using NewHorizons.External;
|
using NewHorizons.External;
|
||||||
|
using NewHorizons.External.Configs;
|
||||||
using NewHorizons.External.Modules;
|
using NewHorizons.External.Modules;
|
||||||
using NewHorizons.External.Modules.Props;
|
using NewHorizons.External.Modules.Props;
|
||||||
using NewHorizons.External.Modules.Props.Audio;
|
using NewHorizons.External.Modules.Props.Audio;
|
||||||
using NewHorizons.External.Modules.Props.Dialogue;
|
using NewHorizons.External.Modules.Props.Dialogue;
|
||||||
|
using NewHorizons.External.SerializableData;
|
||||||
|
using NewHorizons.OtherMods.MenuFramework;
|
||||||
using NewHorizons.Utility;
|
using NewHorizons.Utility;
|
||||||
using NewHorizons.Utility.OWML;
|
using NewHorizons.Utility.OWML;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@ -15,8 +19,10 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Xml.Linq;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using UnityEngine.Events;
|
using UnityEngine.Events;
|
||||||
|
using static NewHorizons.External.Modules.ShipLogModule;
|
||||||
|
|
||||||
namespace NewHorizons
|
namespace NewHorizons
|
||||||
{
|
{
|
||||||
@ -215,5 +221,88 @@ namespace NewHorizons
|
|||||||
|
|
||||||
return DialogueBuilder.Make(root, null, info, mod);
|
return DialogueBuilder.Make(root, null, info, mod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CreatePlanet(string config, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var planet = JsonConvert.DeserializeObject<PlanetConfig>(config);
|
||||||
|
if (planet == null)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Couldn't load planet via API. Is your Json formatted correctly? {config}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var body = Main.Instance.RegisterPlanetConfig(planet, mod, null);
|
||||||
|
|
||||||
|
if (!Main.BodyDict.ContainsKey(body.Config.starSystem)) Main.BodyDict.Add(body.Config.starSystem, new List<NewHorizonsBody>());
|
||||||
|
Main.BodyDict[body.Config.starSystem].Add(body);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Error in CreatePlanet API:\n{ex}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DefineStarSystem(string name, string config, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
var starSystemConfig = JsonConvert.DeserializeObject<StarSystemConfig>(config);
|
||||||
|
Main.Instance.LoadStarSystemConfig(name, starSystemConfig, null, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
public (CharacterDialogueTree, RemoteDialogueTrigger) CreateDialogueFromXML(string textAssetID, string xml, string dialogueInfo, GameObject planetGO)
|
||||||
|
{
|
||||||
|
var info = JsonConvert.DeserializeObject<DialogueInfo>(dialogueInfo);
|
||||||
|
return DialogueBuilder.Make(planetGO, null, info, xml, textAssetID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddShipLogXML(IModBehaviour mod, XElement xml, string planetName, string imageFolder, Dictionary<string, Vector2> entryPositions, Dictionary<string, (Color colour, Color highlight)> curiousityColours)
|
||||||
|
{
|
||||||
|
// This method has to be called each time the ship log manager is created, i.e. each time a system loads so it will only ever be relevant to the current one.
|
||||||
|
var starSystem = Main.Instance.CurrentStarSystem;
|
||||||
|
|
||||||
|
var body = new NewHorizonsBody(new PlanetConfig()
|
||||||
|
{
|
||||||
|
name = planetName,
|
||||||
|
starSystem = starSystem,
|
||||||
|
ShipLog = new ShipLogModule()
|
||||||
|
{
|
||||||
|
spriteFolder = imageFolder
|
||||||
|
}
|
||||||
|
}, mod);
|
||||||
|
|
||||||
|
if (!Main.BodyDict.ContainsKey(starSystem))
|
||||||
|
{
|
||||||
|
Main.BodyDict.Add(starSystem, new List<NewHorizonsBody>());
|
||||||
|
Main.BodyDict[starSystem].Add(body);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var existingBody = Main.BodyDict[starSystem]
|
||||||
|
.FirstOrDefault(x => x.Config.name == planetName && x.Mod.ModHelper.Manifest.UniqueName == mod.ModHelper.Manifest.UniqueName);
|
||||||
|
if (existingBody != null)
|
||||||
|
{
|
||||||
|
body = existingBody;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Main.BodyDict[starSystem].Add(body);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var system = new StarSystemConfig()
|
||||||
|
{
|
||||||
|
entryPositions = entryPositions?
|
||||||
|
.Select((pair) => new EntryPositionInfo() { id = pair.Key, position = pair.Value })
|
||||||
|
.ToArray(),
|
||||||
|
curiosities = curiousityColours?
|
||||||
|
.Select((pair) => new CuriosityColorInfo() { id = pair.Key, color = MColor.FromColor(pair.Value.colour), highlightColor = MColor.FromColor(pair.Value.highlight) })
|
||||||
|
.ToArray()
|
||||||
|
};
|
||||||
|
|
||||||
|
Main.Instance.LoadStarSystemConfig(starSystem, system, null, mod);
|
||||||
|
|
||||||
|
RumorModeBuilder.AddShipLogXML(GameObject.FindObjectOfType<ShipLogManager>(), xml, body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
NewHorizons/Patches/AnglerfishAudioControllerPatches.cs
Normal file
47
NewHorizons/Patches/AnglerfishAudioControllerPatches.cs
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
using HarmonyLib;
|
||||||
|
using UnityEngine;
|
||||||
|
using static AnglerfishController;
|
||||||
|
|
||||||
|
namespace NewHorizons.Patches
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(AnglerfishAudioController))]
|
||||||
|
public static class AnglerfishAudioControllerPatches
|
||||||
|
{
|
||||||
|
[HarmonyPrefix]
|
||||||
|
[HarmonyPatch(nameof(AnglerfishAudioController.OnChangeAnglerState))]
|
||||||
|
public static bool AnglerfishAudioController_OnChangeAnglerState(AnglerfishAudioController __instance, AnglerState anglerState)
|
||||||
|
{
|
||||||
|
var scale = __instance.transform.parent.localScale.x;
|
||||||
|
|
||||||
|
if (scale == 1)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var modifier = 1f / Mathf.Clamp(scale, 0.5f, 2f);
|
||||||
|
|
||||||
|
__instance.UpdateLoopingAudio(anglerState);
|
||||||
|
if (anglerState == AnglerState.Investigating)
|
||||||
|
{
|
||||||
|
__instance._longRangeOneShotSource.pitch = modifier * Random.Range(0.8f, 1f);
|
||||||
|
__instance._longRangeOneShotSource.PlayOneShot(AudioType.DBAnglerfishDetectDisturbance, 1f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (anglerState == AnglerState.Chasing)
|
||||||
|
{
|
||||||
|
if (Time.time > AnglerfishAudioController.s_lastDetectTime + 2f)
|
||||||
|
{
|
||||||
|
AnglerfishAudioController.s_lastDetectTime = Time.time;
|
||||||
|
__instance._oneShotSource.pitch = modifier * Random.Range(0.8f, 1f);
|
||||||
|
__instance._oneShotSource.PlayOneShot(AudioType.DBAnglerfishDetectTarget, 1f);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
MonoBehaviour.print("ANGLER DETECT TARGET SOUND BLOCKED");
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,7 @@
|
|||||||
"author": "xen, Bwc9876, clay, MegaPiggy, John, Trifid, Hawkbar, Book",
|
"author": "xen, Bwc9876, clay, MegaPiggy, John, Trifid, Hawkbar, Book",
|
||||||
"name": "New Horizons",
|
"name": "New Horizons",
|
||||||
"uniqueName": "xen.NewHorizons",
|
"uniqueName": "xen.NewHorizons",
|
||||||
"version": "1.12.7",
|
"version": "1.13.0",
|
||||||
"owmlVersion": "2.9.3",
|
"owmlVersion": "2.9.3",
|
||||||
"dependencies": [ "JohnCorby.VanillaFix", "_nebula.MenuFramework", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
"dependencies": [ "JohnCorby.VanillaFix", "_nebula.MenuFramework", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
||||||
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "PacificEngine.OW_CommonResources" ],
|
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "PacificEngine.OW_CommonResources" ],
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user