Merge branch 'dev' into bramble-nodes

This commit is contained in:
JohnCorby 2022-07-01 12:44:57 -07:00
commit e4254ee6ec
35 changed files with 762 additions and 604 deletions

View File

@ -1,7 +1,6 @@
using NewHorizons.External.Configs; using NewHorizons.External.Configs;
using NewHorizons.Utility; using NewHorizons.Utility;
using OWML.ModHelper; using OWML.ModHelper;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -21,7 +21,7 @@ namespace NewHorizons.Builder.Atmosphere
if (info.isRaining) if (info.isRaining)
{ {
var rainGO = GameObject.Instantiate(SearchUtilities.CachedFind("/GiantsDeep_Body/Sector_GD/Sector_GDInterior/Effects_GDInterior/Effects_GD_Rain"), effectsGO.transform); var rainGO = GameObject.Instantiate(SearchUtilities.Find("GiantsDeep_Body/Sector_GD/Sector_GDInterior/Effects_GDInterior/Effects_GD_Rain"), effectsGO.transform);
rainGO.transform.position = planetGO.transform.position; rainGO.transform.position = planetGO.transform.position;
var pvc = rainGO.GetComponent<PlanetaryVectionController>(); var pvc = rainGO.GetComponent<PlanetaryVectionController>();
@ -44,7 +44,7 @@ namespace NewHorizons.Builder.Atmosphere
snowGO.transform.position = planetGO.transform.position; snowGO.transform.position = planetGO.transform.position;
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
{ {
var snowEmitter = GameObject.Instantiate(SearchUtilities.CachedFind("/BrittleHollow_Body/Sector_BH/Effects_BH/Effects_BH_Snowflakes"), snowGO.transform); var snowEmitter = GameObject.Instantiate(SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Effects_BH/Effects_BH_Snowflakes"), snowGO.transform);
snowEmitter.name = "SnowEmitter"; snowEmitter.name = "SnowEmitter";
snowEmitter.transform.position = planetGO.transform.position; snowEmitter.transform.position = planetGO.transform.position;

View File

@ -1,21 +1,43 @@
using NewHorizons.External.Modules; using NewHorizons.External.Modules;
using NewHorizons.External.Modules.VariableSize;
using UnityEngine; using UnityEngine;
namespace NewHorizons.Builder.Atmosphere namespace NewHorizons.Builder.Atmosphere
{ {
public static class SunOverrideBuilder public static class SunOverrideBuilder
{ {
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, float surfaceSize) public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, WaterModule water, float surfaceSize)
{ {
GameObject overrideGO = new GameObject("SunOverride"); GameObject overrideGO = new GameObject("SunOverride");
overrideGO.SetActive(false); overrideGO.SetActive(false);
overrideGO.transform.parent = sector?.transform ?? planetGO.transform; overrideGO.transform.parent = sector?.transform ?? planetGO.transform;
GiantsDeepSunOverrideVolume GDSOV = overrideGO.AddComponent<GiantsDeepSunOverrideVolume>(); if (water != null)
GDSOV._sector = sector; {
GDSOV._cloudsOuterRadius = atmo.size; var GDSOV = overrideGO.AddComponent<GiantsDeepSunOverrideVolume>();
GDSOV._cloudsInnerRadius = atmo.size * 0.9f; GDSOV._sector = sector;
GDSOV._waterOuterRadius = surfaceSize; GDSOV._cloudsOuterRadius = atmo.clouds.outerCloudRadius;
GDSOV._waterInnerRadius = 0f; GDSOV._cloudsInnerRadius = atmo.clouds.innerCloudRadius;
GDSOV._waterOuterRadius = water.size;
GDSOV._waterInnerRadius = 0f;
}
else
{
var sunOverride = overrideGO.AddComponent<SunOverrideVolume>();
sunOverride._sector = sector;
sunOverride._overrideColor = true;
sunOverride._color = Color.black;
sunOverride._overrideIntensity = true;
sunOverride._intensity = 0f;
sunOverride._overrideShadowStrength = true;
sunOverride._shadowStrength = 1f;
sunOverride.shape = SimpleVolume.Shape.Sphere;
sunOverride.height = 2;
sunOverride.radius = atmo.clouds.innerCloudRadius;
}
overrideGO.transform.position = planetGO.transform.position; overrideGO.transform.position = planetGO.transform.position;
overrideGO.SetActive(true); overrideGO.SetActive(true);

View File

@ -62,7 +62,7 @@ namespace NewHorizons.Builder.Body
} }
if (body.Config.Star != null) if (body.Config.Star != null)
{ {
var starGO = StarBuilder.MakeStarProxy(planetGO, newProxy, body.Config.Star); var starGO = StarBuilder.MakeStarProxy(planetGO, newProxy, body.Config.Star, body.Mod);
if (realSize < body.Config.Star.size) realSize = body.Config.Star.size; if (realSize < body.Config.Star.size) realSize = body.Config.Star.size;
} }
@ -93,18 +93,21 @@ namespace NewHorizons.Builder.Body
if (realSize < body.Config.Sand.size) realSize = body.Config.Sand.size; if (realSize < body.Config.Sand.size) realSize = body.Config.Sand.size;
} }
// Could improve this to actually use the proper renders and materials // Could improve this to actually use the proper renders and materials
if (body.Config.Singularity != null) if (body.Config.Props?.singularities != null)
{ {
if (body.Config.Singularity.type == SingularityModule.SingularityType.BlackHole) foreach(var singularity in body.Config.Props.singularities)
{ {
MakeBlackHole(newProxy, body.Config.Singularity.size); if (singularity.type == SingularityModule.SingularityType.BlackHole)
} {
else MakeBlackHole(newProxy, singularity.size);
{ }
MakeWhiteHole(newProxy, body.Config.Singularity.size); else
} {
MakeWhiteHole(newProxy, singularity.size);
}
if (realSize < body.Config.Singularity.size) realSize = body.Config.Singularity.size; if (realSize < singularity.size) realSize = singularity.size;
}
} }
if (body.Config.Base.hasCometTail) if (body.Config.Base.hasCometTail)
{ {

View File

@ -1,4 +1,4 @@
using NewHorizons.Components; using NewHorizons.Components;
using NewHorizons.Components.SizeControllers; using NewHorizons.Components.SizeControllers;
using NewHorizons.Utility; using NewHorizons.Utility;
using OWML.Common; using OWML.Common;
@ -45,7 +45,7 @@ namespace NewHorizons.Builder.Body
var trigger = ringVolume.AddComponent<OWTriggerVolume>(); var trigger = ringVolume.AddComponent<OWTriggerVolume>();
trigger._shape = ringShape; trigger._shape = ringShape;
var sfv = ringVolume.AddComponent<SimpleFluidVolume>(); var sfv = ringVolume.AddComponent<RingFluidVolume>();
var fluidType = FluidVolume.Type.NONE; var fluidType = FluidVolume.Type.NONE;
try try

View File

@ -5,6 +5,9 @@ using System;
using NewHorizons.External.Modules.VariableSize; using NewHorizons.External.Modules.VariableSize;
using UnityEngine; using UnityEngine;
using Logger = NewHorizons.Utility.Logger; using Logger = NewHorizons.Utility.Logger;
using System.Collections.Generic;
using System.Linq;
namespace NewHorizons.Builder.Body namespace NewHorizons.Builder.Body
{ {
public static class SingularityBuilder public static class SingularityBuilder
@ -18,61 +21,73 @@ namespace NewHorizons.Builder.Body
private static readonly int DistortFadeDist = Shader.PropertyToID("_DistortFadeDist"); private static readonly int DistortFadeDist = Shader.PropertyToID("_DistortFadeDist");
private static readonly int Color1 = Shader.PropertyToID("_Color"); private static readonly int Color1 = Shader.PropertyToID("_Color");
public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config) private static Dictionary<string, GameObject> _singularitiesByID;
public static void Make(GameObject go, Sector sector, OWRigidbody OWRB, PlanetConfig config, SingularityModule singularity)
{ {
var size = config.Singularity.size; // If we've reloaded the first one will now be null so we have to refresh the list
var pairedSingularity = config.Singularity.pairedSingularity; if (_singularitiesByID?.Values?.FirstOrDefault() == null) _singularitiesByID = new Dictionary<string, GameObject>();
var polarity = config.Singularity.type; var size = singularity.size;
var pairedSingularity = singularity.pairedSingularity;
bool isWormHole = config.Singularity?.targetStarSystem != null; var polarity = singularity.type;
bool isWormHole = singularity?.targetStarSystem != null;
bool hasHazardVolume = !isWormHole && (pairedSingularity == null); bool hasHazardVolume = !isWormHole && (pairedSingularity == null);
bool makeZeroGVolume = config.Singularity == null ? true : config.Singularity.makeZeroGVolume; bool makeZeroGVolume = singularity == null ? true : singularity.makeZeroGVolume;
Vector3 localPosition = config.Singularity?.position == null ? Vector3.zero : (Vector3)config.Singularity.position; Vector3 localPosition = singularity?.position == null ? Vector3.zero : singularity.position;
GameObject newSingularity = null; GameObject newSingularity = null;
switch (polarity) switch (polarity)
{ {
case SingularityModule.SingularityType.BlackHole: case SingularityModule.SingularityType.BlackHole:
newSingularity = MakeBlackHole(go, sector, localPosition, size, hasHazardVolume, config.Singularity.targetStarSystem); newSingularity = MakeBlackHole(go, sector, localPosition, size, hasHazardVolume, singularity.targetStarSystem);
break; break;
case SingularityModule.SingularityType.WhiteHole: case SingularityModule.SingularityType.WhiteHole:
newSingularity = MakeWhiteHole(go, sector, OWRB, localPosition, size, makeZeroGVolume); newSingularity = MakeWhiteHole(go, sector, OWRB, localPosition, size, makeZeroGVolume);
break; break;
} }
var uniqueID = string.IsNullOrEmpty(singularity.uniqueID) ? config.name : singularity.uniqueID;
_singularitiesByID.Add(uniqueID, newSingularity);
// Try to pair them // Try to pair them
if (pairedSingularity != null && newSingularity != null) if (!string.IsNullOrEmpty(pairedSingularity) && newSingularity != null)
{ {
var pairedSingularityAO = AstroObjectLocator.GetAstroObject(pairedSingularity); if (_singularitiesByID.TryGetValue(pairedSingularity, out var pairedSingularityGO))
if (pairedSingularityAO != null)
{ {
switch (polarity) switch (polarity)
{ {
case SingularityModule.SingularityType.BlackHole: case SingularityModule.SingularityType.BlackHole:
PairSingularities(newSingularity, pairedSingularityAO.gameObject); PairSingularities(uniqueID, pairedSingularity, newSingularity, pairedSingularityGO);
break; break;
case SingularityModule.SingularityType.WhiteHole: case SingularityModule.SingularityType.WhiteHole:
PairSingularities(pairedSingularityAO.gameObject, newSingularity); PairSingularities(pairedSingularity, uniqueID, pairedSingularityGO, newSingularity);
break; break;
} }
} }
} }
} }
public static void PairSingularities(GameObject blackHole, GameObject whiteHole) public static void PairSingularities(string blackHoleID, string whiteHoleID, GameObject blackHole, GameObject whiteHole)
{ {
Logger.Log($"Pairing singularities {blackHole?.name}, {whiteHole?.name}"); if (blackHole == null || whiteHole == null) return;
try
Logger.Log($"Pairing singularities [{blackHoleID}], [{whiteHoleID}]");
var whiteHoleVolume = whiteHole.GetComponentInChildren<WhiteHoleVolume>();
var blackHoleVolume = blackHole.GetComponentInChildren<BlackHoleVolume>();
if (whiteHoleVolume == null || blackHoleVolume == null)
{ {
blackHole.GetComponentInChildren<BlackHoleVolume>()._whiteHole = whiteHole.GetComponentInChildren<WhiteHoleVolume>(); Logger.Log($"[{blackHoleID}] and [{whiteHoleID}] do not have compatible polarities");
} return;
catch (Exception)
{
Logger.LogError($"Couldn't pair singularities");
} }
blackHoleVolume._whiteHole = whiteHoleVolume;
} }
public static GameObject MakeBlackHole(GameObject planetGO, Sector sector, Vector3 localPosition, float size, bool hasDestructionVolume, string targetSolarSystem, bool makeAudio = true) public static GameObject MakeBlackHole(GameObject planetGO, Sector sector, Vector3 localPosition, float size, bool hasDestructionVolume, string targetSolarSystem, bool makeAudio = true)

View File

@ -5,6 +5,8 @@ using OWML.Utils;
using UnityEngine; using UnityEngine;
using NewHorizons.External.Modules.VariableSize; using NewHorizons.External.Modules.VariableSize;
using Logger = NewHorizons.Utility.Logger; using Logger = NewHorizons.Utility.Logger;
using OWML.ModHelper;
using OWML.Common;
namespace NewHorizons.Builder.Body namespace NewHorizons.Builder.Body
{ {
@ -19,9 +21,9 @@ namespace NewHorizons.Builder.Body
private static readonly int InnerRadius = Shader.PropertyToID("_InnerRadius"); private static readonly int InnerRadius = Shader.PropertyToID("_InnerRadius");
private static readonly int OuterRadius = Shader.PropertyToID("_OuterRadius"); private static readonly int OuterRadius = Shader.PropertyToID("_OuterRadius");
public static StarController Make(GameObject planetGO, Sector sector, StarModule starModule) public static StarController Make(GameObject planetGO, Sector sector, StarModule starModule, IModBehaviour mod)
{ {
var starGO = MakeStarGraphics(planetGO, sector, starModule); var starGO = MakeStarGraphics(planetGO, sector, starModule, mod);
var sunAudio = Object.Instantiate(SearchUtilities.Find("Sun_Body/Sector_SUN/Audio_SUN"), starGO.transform); var sunAudio = Object.Instantiate(SearchUtilities.Find("Sun_Body/Sector_SUN/Audio_SUN"), starGO.transform);
sunAudio.transform.localPosition = Vector3.zero; sunAudio.transform.localPosition = Vector3.zero;
@ -152,9 +154,9 @@ namespace NewHorizons.Builder.Body
return starController; return starController;
} }
public static GameObject MakeStarProxy(GameObject planet, GameObject proxyGO, StarModule starModule) public static GameObject MakeStarProxy(GameObject planet, GameObject proxyGO, StarModule starModule, IModBehaviour mod)
{ {
var starGO = MakeStarGraphics(proxyGO, null, starModule); var starGO = MakeStarGraphics(proxyGO, null, starModule, mod);
var supernova = MakeSupernova(starGO, starModule); var supernova = MakeSupernova(starGO, starModule);
@ -175,7 +177,7 @@ namespace NewHorizons.Builder.Body
return proxyGO; return proxyGO;
} }
public static GameObject MakeStarGraphics(GameObject rootObject, Sector sector, StarModule starModule) public static GameObject MakeStarGraphics(GameObject rootObject, Sector sector, StarModule starModule, IModBehaviour mod)
{ {
if (_colorOverTime == null) _colorOverTime = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/StarColorOverTime.png"); if (_colorOverTime == null) _colorOverTime = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/StarColorOverTime.png");
@ -208,10 +210,10 @@ namespace NewHorizons.Builder.Body
starGO.transform.position = rootObject.transform.position; starGO.transform.position = rootObject.transform.position;
starGO.transform.localScale = starModule.size * Vector3.one; starGO.transform.localScale = starModule.size * Vector3.one;
TessellatedSphereRenderer surface = sunSurface.GetComponent<TessellatedSphereRenderer>();
if (starModule.tint != null) if (starModule.tint != null)
{ {
TessellatedSphereRenderer surface = sunSurface.GetComponent<TessellatedSphereRenderer>();
var colour = starModule.tint.ToColor(); var colour = starModule.tint.ToColor();
var sun = SearchUtilities.Find("Sun_Body"); var sun = SearchUtilities.Find("Sun_Body");
@ -219,8 +221,8 @@ namespace NewHorizons.Builder.Body
var giantMaterial = sun.GetComponent<SunController>()._endSurfaceMaterial; var giantMaterial = sun.GetComponent<SunController>()._endSurfaceMaterial;
surface.sharedMaterial = new Material(starModule.size >= 3000 ? giantMaterial : mainSequenceMaterial); surface.sharedMaterial = new Material(starModule.size >= 3000 ? giantMaterial : mainSequenceMaterial);
var mod = Mathf.Max(1f, 2f * Mathf.Sqrt(starModule.solarLuminosity)); var modifier = Mathf.Max(1f, 2f * Mathf.Sqrt(starModule.solarLuminosity));
var adjustedColour = new Color(colour.r * mod, colour.g * mod, colour.b * mod); var adjustedColour = new Color(colour.r * modifier, colour.g * modifier, colour.b * modifier);
surface.sharedMaterial.color = adjustedColour; surface.sharedMaterial.color = adjustedColour;
Color.RGBToHSV(adjustedColour, out var h, out var s, out var v); Color.RGBToHSV(adjustedColour, out var h, out var s, out var v);
@ -229,12 +231,21 @@ namespace NewHorizons.Builder.Body
if (starModule.endTint != null) if (starModule.endTint != null)
{ {
var endColour = starModule.endTint.ToColor(); var endColour = starModule.endTint.ToColor();
darkenedColor = new Color(endColour.r * mod, endColour.g * mod, endColour.b * mod); darkenedColor = new Color(endColour.r * modifier, endColour.g * modifier, endColour.b * modifier);
} }
surface.sharedMaterial.SetTexture(ColorRamp, ImageUtilities.LerpGreyscaleImage(_colorOverTime, adjustedColour, darkenedColor)); surface.sharedMaterial.SetTexture(ColorRamp, ImageUtilities.LerpGreyscaleImage(_colorOverTime, adjustedColour, darkenedColor));
} }
if (!string.IsNullOrEmpty(starModule.starRampTexture))
{
var ramp = ImageUtilities.GetTexture(mod, starModule.starRampTexture);
if (ramp != null)
{
surface.sharedMaterial.SetTexture(ColorRamp, ramp);
}
}
return starGO; return starGO;
} }

View File

@ -15,8 +15,8 @@ namespace NewHorizons.Builder.General
var gravityRadius = GM / 0.1f; var gravityRadius = GM / 0.1f;
if (exponent == 2f) gravityRadius = Mathf.Sqrt(gravityRadius); if (exponent == 2f) gravityRadius = Mathf.Sqrt(gravityRadius);
// To let you actually orbit things the way you would expect we cap this at 4x the diameter if its not a star or black hole (this is what giants deep has) // To let you actually orbit things the way you would expect we cap this at 4x the diameter if its not a star (this is what giants deep has)
if (config.Star == null && config.Singularity == null) gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.surfaceSize); if (config.Star == null) gravityRadius = Mathf.Min(gravityRadius, 4 * config.Base.surfaceSize);
else gravityRadius = Mathf.Min(gravityRadius, 15 * config.Base.surfaceSize); else gravityRadius = Mathf.Min(gravityRadius, 15 * config.Base.surfaceSize);
if (config.Base.soiOverride != 0f) gravityRadius = config.Base.soiOverride; if (config.Base.soiOverride != 0f) gravityRadius = config.Base.soiOverride;

View File

@ -1,5 +1,7 @@
using NewHorizons.Components.Orbital; using NewHorizons.Components.Orbital;
using NewHorizons.External.Modules; using NewHorizons.External.Modules;
using NewHorizons.Utility;
using System.Linq;
using UnityEngine; using UnityEngine;
using Logger = NewHorizons.Utility.Logger; using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Orbital namespace NewHorizons.Builder.Orbital
@ -13,7 +15,7 @@ namespace NewHorizons.Builder.Orbital
return SetInitialMotionFromConfig(initialMotion, primaryBody, secondaryBody, orbit); return SetInitialMotionFromConfig(initialMotion, primaryBody, secondaryBody, orbit);
} }
public static InitialMotion SetInitialMotionFromConfig(InitialMotion initialMotion, AstroObject primaryBody, AstroObject secondaryBody, OrbitModule orbit) public static InitialMotion SetInitialMotionFromConfig(InitialMotion initialMotion, AstroObject primaryBody, AstroObject secondaryBody, OrbitModule orbit, bool isCustom = true)
{ {
// This bit makes the initial motion not try to calculate the orbit velocity itself for reasons // This bit makes the initial motion not try to calculate the orbit velocity itself for reasons
initialMotion._orbitImpulseScalar = 0f; initialMotion._orbitImpulseScalar = 0f;
@ -21,7 +23,12 @@ namespace NewHorizons.Builder.Orbital
// Rotation // Rotation
initialMotion._initAngularSpeed = orbit.siderealPeriod == 0 ? 0f : 2f * Mathf.PI / (orbit.siderealPeriod * 60f); initialMotion._initAngularSpeed = orbit.siderealPeriod == 0 ? 0f : 2f * Mathf.PI / (orbit.siderealPeriod * 60f);
var rotationAxis = Quaternion.AngleAxis(orbit.axialTilt, Vector3.right) * Vector3.up; var rotationAxis = Quaternion.AngleAxis(orbit.axialTilt, Vector3.right) * Vector3.up;
secondaryBody.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
// For things with children this is broken
if (AstroObjectLocator.GetChildren(secondaryBody).Length == 0)
{
secondaryBody.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
}
if (!orbit.isStatic && primaryBody != null) if (!orbit.isStatic && primaryBody != null)
{ {

View File

@ -52,7 +52,6 @@ namespace NewHorizons.Builder.Orbital
if (config.Orbit.tint != null) color = config.Orbit.tint.ToColor(); if (config.Orbit.tint != null) color = config.Orbit.tint.ToColor();
else if (config.Star?.tint != null) color = config.Star.tint.ToColor(); else if (config.Star?.tint != null) color = config.Star.tint.ToColor();
else if (config.Atmosphere?.clouds?.tint != null) color = config.Atmosphere.clouds.tint.ToColor(); else if (config.Atmosphere?.clouds?.tint != null) color = config.Atmosphere.clouds.tint.ToColor();
else if (config.Singularity != null) color = new Color(1f, 0.5f, 1f);
else if (config.Water != null) color = new Color(0.5f, 0.5f, 1f); else if (config.Water != null) color = new Color(0.5f, 0.5f, 1f);
else if (config.Lava != null) color = new Color(1f, 0.5f, 0.5f); else if (config.Lava != null) color = new Color(1f, 0.5f, 0.5f);
else if (config.Atmosphere != null && config.Atmosphere.fogTint != null) color = config.Atmosphere.fogTint.ToColor(); else if (config.Atmosphere != null && config.Atmosphere.fogTint != null) color = config.Atmosphere.fogTint.ToColor();

View File

@ -30,19 +30,27 @@ namespace NewHorizons.Builder.Props
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal); detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
} }
else detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal); else
if (detailGO != null && detail.removeChildren != null)
{ {
detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
if (detailGO == null) return;
if (detail.removeChildren != null)
{
var detailPath = detailGO.transform.GetPath();
foreach (var childPath in detail.removeChildren) foreach (var childPath in detail.removeChildren)
{ {
var childObj = detailGO.transform.Find(childPath); // We purposefully use GameObject.Find here because we don't want to find inactive things.
// If you were to try and disable two children with the same name, if we were finding inactive then we'd disable the first one twice
var childObj = GameObject.Find($"{detailPath}/{childPath}");
if (childObj != null) childObj.gameObject.SetActive(false); if (childObj != null) childObj.gameObject.SetActive(false);
else Logger.LogWarning($"Couldn't find {childPath}"); else Logger.LogWarning($"Couldn't find {childPath}");
} }
} }
if (detailGO != null && detail.removeComponents) if (detail.removeComponents)
{ {
// Just swap all the children to a new game object // Just swap all the children to a new game object
var newDetailGO = new GameObject(detailGO.name); var newDetailGO = new GameObject(detailGO.name);
@ -67,6 +75,15 @@ namespace NewHorizons.Builder.Props
detailGO.name = detail.rename; detailGO.name = detail.rename;
} }
if (!string.IsNullOrEmpty(detail.parentPath))
{
var newParent = go.transform.Find(detail.parentPath);
if (newParent != null)
{
detailGO.transform.parent = newParent.transform;
}
}
detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO; detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO;
} }

View File

@ -1,6 +1,7 @@
using NewHorizons.External.Modules; using NewHorizons.External.Modules;
using NewHorizons.Handlers; using NewHorizons.Handlers;
using OWML.Common; using OWML.Common;
using System.IO;
using System.Xml; using System.Xml;
using UnityEngine; using UnityEngine;
namespace NewHorizons.Builder.Props namespace NewHorizons.Builder.Props
@ -76,8 +77,9 @@ namespace NewHorizons.Builder.Props
var dialogueTree = conversationZone.AddComponent<CharacterDialogueTree>(); var dialogueTree = conversationZone.AddComponent<CharacterDialogueTree>();
var xml = System.IO.File.ReadAllText(mod.Manifest.ModFolderPath + info.xmlFile); var xml = File.ReadAllText(mod.Manifest.ModFolderPath + info.xmlFile);
var text = new TextAsset(xml); var text = new TextAsset(xml);
text.name = Path.GetFileNameWithoutExtension(info.xmlFile);
dialogueTree.SetTextXml(text); dialogueTree.SetTextXml(text);
AddTranslation(xml); AddTranslation(xml);

View File

@ -3,6 +3,7 @@ using NewHorizons.Handlers;
using NewHorizons.Utility; using NewHorizons.Utility;
using OWML.Common; using OWML.Common;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO;
using System.Linq; using System.Linq;
using System.Xml; using System.Xml;
using UnityEngine; using UnityEngine;
@ -100,191 +101,194 @@ namespace NewHorizons.Builder.Props
switch (info.type) switch (info.type)
{ {
case PropModule.NomaiTextInfo.NomaiTextType.Wall: case PropModule.NomaiTextInfo.NomaiTextType.Wall:
{
var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject;
nomaiWallTextObj.transform.parent = sector?.transform ?? planetGO.transform;
nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(info.position);
if (info.normal != null)
{ {
// In global coordinates (normal was in local coordinates) var nomaiWallTextObj = MakeWallText(planetGO, sector, info, xmlPath).gameObject;
var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized;
var forward = planetGO.transform.TransformDirection(info.normal).normalized;
nomaiWallTextObj.transform.up = up; nomaiWallTextObj.transform.parent = sector?.transform ?? planetGO.transform;
nomaiWallTextObj.transform.forward = forward; nomaiWallTextObj.transform.position = planetGO.transform.TransformPoint(info.position);
} if (info.normal != null)
if (info.rotation != null)
{
nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation));
}
nomaiWallTextObj.SetActive(true);
conversationInfoToCorrespondingSpawnedGameObject[info] = nomaiWallTextObj;
break;
}
case PropModule.NomaiTextInfo.NomaiTextType.Scroll:
{
var customScroll = _scrollPrefab.InstantiateInactive();
var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath);
nomaiWallText.transform.parent = customScroll.transform;
nomaiWallText.transform.localPosition = Vector3.zero;
nomaiWallText.transform.localRotation = Quaternion.identity;
nomaiWallText._showTextOnStart = false;
// Don't want to be able to translate until its in a socket
nomaiWallText.GetComponent<Collider>().enabled = false;
nomaiWallText.gameObject.SetActive(true);
var scrollItem = customScroll.GetComponent<ScrollItem>();
// Idk why this thing is always around
GameObject.Destroy(customScroll.transform.Find("Arc_BH_City_Forum_2").gameObject);
// This variable is the bane of my existence i dont get it
scrollItem._nomaiWallText = nomaiWallText;
// Because the scroll was already awake it does weird shit in Awake and makes some of the entries in this array be null
scrollItem._colliders = new OWCollider[] { scrollItem.GetComponent<OWCollider>() };
// Else when you put them down you can't pick them back up
customScroll.GetComponent<OWCollider>()._physicsRemoved = false;
// Place scroll
customScroll.transform.parent = sector?.transform ?? planetGO.transform;
customScroll.transform.position = planetGO.transform.TransformPoint(info.position ?? Vector3.zero);
var up = planetGO.transform.InverseTransformPoint(customScroll.transform.position).normalized;
customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation;
customScroll.SetActive(true);
// Enable the collider and renderer
Main.Instance.ModHelper.Events.Unity.RunWhen(
() => Main.IsSystemReady,
() =>
{ {
Logger.Log("Fixing scroll!"); // In global coordinates (normal was in local coordinates)
scrollItem._nomaiWallText = nomaiWallText; var up = (nomaiWallTextObj.transform.position - planetGO.transform.position).normalized;
scrollItem.SetSector(sector); var forward = planetGO.transform.TransformDirection(info.normal).normalized;
customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Geo").GetComponent<MeshRenderer>().enabled = true;
customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Collider").gameObject.SetActive(true); nomaiWallTextObj.transform.up = up;
nomaiWallText.gameObject.GetComponent<Collider>().enabled = false; nomaiWallTextObj.transform.forward = forward;
customScroll.GetComponent<CapsuleCollider>().enabled = true;
} }
); if (info.rotation != null)
conversationInfoToCorrespondingSpawnedGameObject[info] = customScroll; {
break; nomaiWallTextObj.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation));
} }
nomaiWallTextObj.SetActive(true);
conversationInfoToCorrespondingSpawnedGameObject[info] = nomaiWallTextObj;
break;
}
case PropModule.NomaiTextInfo.NomaiTextType.Scroll:
{
var customScroll = _scrollPrefab.InstantiateInactive();
var nomaiWallText = MakeWallText(planetGO, sector, info, xmlPath);
nomaiWallText.transform.parent = customScroll.transform;
nomaiWallText.transform.localPosition = Vector3.zero;
nomaiWallText.transform.localRotation = Quaternion.identity;
nomaiWallText._showTextOnStart = false;
// Don't want to be able to translate until its in a socket
nomaiWallText.GetComponent<Collider>().enabled = false;
nomaiWallText.gameObject.SetActive(true);
var scrollItem = customScroll.GetComponent<ScrollItem>();
// Idk why this thing is always around
GameObject.Destroy(customScroll.transform.Find("Arc_BH_City_Forum_2").gameObject);
// This variable is the bane of my existence i dont get it
scrollItem._nomaiWallText = nomaiWallText;
// Because the scroll was already awake it does weird shit in Awake and makes some of the entries in this array be null
scrollItem._colliders = new OWCollider[] { scrollItem.GetComponent<OWCollider>() };
// Else when you put them down you can't pick them back up
customScroll.GetComponent<OWCollider>()._physicsRemoved = false;
// Place scroll
customScroll.transform.parent = sector?.transform ?? planetGO.transform;
customScroll.transform.position = planetGO.transform.TransformPoint(info.position ?? Vector3.zero);
var up = planetGO.transform.InverseTransformPoint(customScroll.transform.position).normalized;
customScroll.transform.rotation = Quaternion.FromToRotation(customScroll.transform.up, up) * customScroll.transform.rotation;
customScroll.SetActive(true);
// Enable the collider and renderer
Main.Instance.ModHelper.Events.Unity.RunWhen(
() => Main.IsSystemReady,
() =>
{
Logger.Log("Fixing scroll!");
scrollItem._nomaiWallText = nomaiWallText;
scrollItem.SetSector(sector);
customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Geo").GetComponent<MeshRenderer>().enabled = true;
customScroll.transform.Find("Props_NOM_Scroll/Props_NOM_Scroll_Collider").gameObject.SetActive(true);
nomaiWallText.gameObject.GetComponent<Collider>().enabled = false;
customScroll.GetComponent<CapsuleCollider>().enabled = true;
}
);
conversationInfoToCorrespondingSpawnedGameObject[info] = customScroll;
break;
}
case PropModule.NomaiTextInfo.NomaiTextType.Computer: case PropModule.NomaiTextInfo.NomaiTextType.Computer:
{ {
var computerObject = _computerPrefab.InstantiateInactive(); var computerObject = _computerPrefab.InstantiateInactive();
computerObject.transform.parent = sector?.transform ?? planetGO.transform; computerObject.transform.parent = sector?.transform ?? planetGO.transform;
computerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero); computerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero);
var up = computerObject.transform.position - planetGO.transform.position; var up = computerObject.transform.position - planetGO.transform.position;
if (info.normal != null) up = planetGO.transform.TransformDirection(info.normal); if (info.normal != null) up = planetGO.transform.TransformDirection(info.normal);
computerObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * computerObject.transform.rotation; computerObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * computerObject.transform.rotation;
var computer = computerObject.GetComponent<NomaiComputer>(); var computer = computerObject.GetComponent<NomaiComputer>();
computer.SetSector(sector); computer.SetSector(sector);
computer._dictNomaiTextData = MakeNomaiTextDict(xmlPath); computer._dictNomaiTextData = MakeNomaiTextDict(xmlPath);
computer._nomaiTextAsset = new TextAsset(xmlPath); computer._nomaiTextAsset = new TextAsset(xmlPath);
AddTranslation(xmlPath); computer._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile);
AddTranslation(xmlPath);
// Make sure the computer model is loaded // Make sure the computer model is loaded
OWAssetHandler.LoadObject(computerObject); OWAssetHandler.LoadObject(computerObject);
sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(computerObject)); sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(computerObject));
computerObject.SetActive(true); computerObject.SetActive(true);
conversationInfoToCorrespondingSpawnedGameObject[info] = computerObject; conversationInfoToCorrespondingSpawnedGameObject[info] = computerObject;
break; break;
} }
case PropModule.NomaiTextInfo.NomaiTextType.Cairn: case PropModule.NomaiTextInfo.NomaiTextType.Cairn:
{
var cairnObject = _cairnPrefab.InstantiateInactive();
cairnObject.transform.parent = sector?.transform ?? planetGO.transform;
cairnObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero);
if (info.rotation != null)
{ {
cairnObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); var cairnObject = _cairnPrefab.InstantiateInactive();
cairnObject.transform.parent = sector?.transform ?? planetGO.transform;
cairnObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero);
if (info.rotation != null)
{
cairnObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation));
}
else
{
// By default align it to normal
var up = (cairnObject.transform.position - planetGO.transform.position).normalized;
cairnObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * cairnObject.transform.rotation;
}
// Idk do we have to set it active before finding things?
cairnObject.SetActive(true);
// Make it do the thing when it finishes being knocked over
foreach (var rock in cairnObject.GetComponent<NomaiCairn>()._rocks)
{
rock._returning = false;
rock._owCollider.SetActivation(true);
rock.enabled = false;
}
// So we can actually knock it over
cairnObject.GetComponent<CapsuleCollider>().enabled = true;
var nomaiWallText = cairnObject.transform.Find("Props_TH_ClutterSmall/Arc_Short").GetComponent<NomaiWallText>();
nomaiWallText.SetSector(sector);
nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlPath);
nomaiWallText._nomaiTextAsset = new TextAsset(xmlPath);
nomaiWallText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile);
AddTranslation(xmlPath);
// Make sure the computer model is loaded
OWAssetHandler.LoadObject(cairnObject);
sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(cairnObject));
conversationInfoToCorrespondingSpawnedGameObject[info] = cairnObject;
break;
} }
else
{
// By default align it to normal
var up = (cairnObject.transform.position - planetGO.transform.position).normalized;
cairnObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * cairnObject.transform.rotation;
}
// Idk do we have to set it active before finding things?
cairnObject.SetActive(true);
// Make it do the thing when it finishes being knocked over
foreach (var rock in cairnObject.GetComponent<NomaiCairn>()._rocks)
{
rock._returning = false;
rock._owCollider.SetActivation(true);
rock.enabled = false;
}
// So we can actually knock it over
cairnObject.GetComponent<CapsuleCollider>().enabled = true;
var nomaiWallText = cairnObject.transform.Find("Props_TH_ClutterSmall/Arc_Short").GetComponent<NomaiWallText>();
nomaiWallText.SetSector(sector);
nomaiWallText._dictNomaiTextData = MakeNomaiTextDict(xmlPath);
nomaiWallText._nomaiTextAsset = new TextAsset(xmlPath);
AddTranslation(xmlPath);
// Make sure the computer model is loaded
OWAssetHandler.LoadObject(cairnObject);
sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(cairnObject));
conversationInfoToCorrespondingSpawnedGameObject[info] = cairnObject;
break;
}
case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder: case PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder:
case PropModule.NomaiTextInfo.NomaiTextType.Recorder: case PropModule.NomaiTextInfo.NomaiTextType.Recorder:
{
var recorderObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder? _preCrashRecorderPrefab : _recorderPrefab).InstantiateInactive();
recorderObject.transform.parent = sector?.transform ?? planetGO.transform;
recorderObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero);
if (info.rotation != null)
{ {
recorderObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation)); var recorderObject = (info.type == PropModule.NomaiTextInfo.NomaiTextType.PreCrashRecorder ? _preCrashRecorderPrefab : _recorderPrefab).InstantiateInactive();
recorderObject.transform.parent = sector?.transform ?? planetGO.transform;
recorderObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero);
if (info.rotation != null)
{
recorderObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation));
}
else
{
var up = recorderObject.transform.position - planetGO.transform.position;
recorderObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * recorderObject.transform.rotation;
}
var nomaiText = recorderObject.GetComponentInChildren<NomaiText>();
nomaiText.SetSector(sector);
nomaiText._dictNomaiTextData = MakeNomaiTextDict(xmlPath);
nomaiText._nomaiTextAsset = new TextAsset(xmlPath);
nomaiText._nomaiTextAsset.name = Path.GetFileNameWithoutExtension(info.xmlFile);
AddTranslation(xmlPath);
// Make sure the recorder model is loaded
OWAssetHandler.LoadObject(recorderObject);
sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(recorderObject));
recorderObject.SetActive(true);
recorderObject.transform.Find("InteractSphere").gameObject.GetComponent<SphereShape>().enabled = true;
conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject;
break;
} }
else
{
var up = recorderObject.transform.position - planetGO.transform.position;
recorderObject.transform.rotation = Quaternion.FromToRotation(Vector3.up, up) * recorderObject.transform.rotation;
}
var nomaiText = recorderObject.GetComponentInChildren<NomaiText>();
nomaiText.SetSector(sector);
nomaiText._dictNomaiTextData = MakeNomaiTextDict(xmlPath);
nomaiText._nomaiTextAsset = new TextAsset(xmlPath);
AddTranslation(xmlPath);
// Make sure the recorder model is loaded
OWAssetHandler.LoadObject(recorderObject);
sector.OnOccupantEnterSector.AddListener((x) => OWAssetHandler.LoadObject(recorderObject));
recorderObject.SetActive(true);
recorderObject.transform.Find("InteractSphere").gameObject.GetComponent<SphereShape>().enabled = true;
conversationInfoToCorrespondingSpawnedGameObject[info] = recorderObject;
break;
}
default: default:
Logger.LogError($"Unsupported NomaiText type {info.type}"); Logger.LogError($"Unsupported NomaiText type {info.type}");
break; break;
@ -306,6 +310,7 @@ namespace NewHorizons.Builder.Props
var nomaiWallText = nomaiWallTextObj.AddComponent<NomaiWallText>(); var nomaiWallText = nomaiWallTextObj.AddComponent<NomaiWallText>();
var text = new TextAsset(xmlPath); var text = new TextAsset(xmlPath);
text.name = Path.GetFileNameWithoutExtension(info.xmlFile);
BuildArcs(xmlPath, nomaiWallText, nomaiWallTextObj, info); BuildArcs(xmlPath, nomaiWallText, nomaiWallTextObj, info);
AddTranslation(xmlPath); AddTranslation(xmlPath);

View File

@ -265,7 +265,7 @@ namespace NewHorizons.Builder.Props
// setup for visually supporting async texture loading // setup for visually supporting async texture loading
mindSlideProjector.enabled = false; mindSlideProjector.enabled = false;
var visionBeamEffect = SearchUtilities.FindChild(standingTorch, "VisionBeam"); var visionBeamEffect = standingTorch.FindChild("VisionBeam");
visionBeamEffect.SetActive(false); visionBeamEffect.SetActive(false);
// //

View File

@ -1,3 +1,4 @@
using NewHorizons.Builder.Body;
using NewHorizons.Builder.ShipLog; using NewHorizons.Builder.ShipLog;
using NewHorizons.External.Configs; using NewHorizons.External.Configs;
using OWML.Common; using OWML.Common;
@ -191,6 +192,13 @@ namespace NewHorizons.Builder.Props
} }
} }
} }
if (config.Props.singularities != null)
{
foreach (var singularity in config.Props.singularities)
{
SingularityBuilder.Make(go, sector, go.GetComponent<OWRigidbody>(), config, singularity);
}
}
} }
} }
} }

View File

@ -101,7 +101,7 @@ namespace NewHorizons.Builder.ShipLog
Logger.Log($"Adding ship log astro object for {body.Config.name}"); Logger.Log($"Adding ship log astro object for {body.Config.name}");
GameObject unviewedReference = SearchUtilities.CachedFind(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"); GameObject unviewedReference = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon");
ShipLogAstroObject astroObject = gameObject.AddComponent<ShipLogAstroObject>(); ShipLogAstroObject astroObject = gameObject.AddComponent<ShipLogAstroObject>();
astroObject._id = ShipLogHandler.GetAstroObjectId(body); astroObject._id = ShipLogHandler.GetAstroObjectId(body);
@ -249,7 +249,7 @@ namespace NewHorizons.Builder.ShipLog
} }
else if (Main.Instance.CurrentStarSystem == "SolarSystem") else if (Main.Instance.CurrentStarSystem == "SolarSystem")
{ {
GameObject gameObject = SearchUtilities.CachedFind(ShipLogHandler.PAN_ROOT_PATH + "/" + name); GameObject gameObject = SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + name);
if (body.Config.destroy || (body.Config.ShipLog?.mapMode?.remove ?? false)) if (body.Config.destroy || (body.Config.ShipLog?.mapMode?.remove ?? false))
{ {
ShipLogAstroObject astroObject = gameObject.GetComponent<ShipLogAstroObject>(); ShipLogAstroObject astroObject = gameObject.GetComponent<ShipLogAstroObject>();
@ -522,14 +522,6 @@ namespace NewHorizons.Builder.ShipLog
{ {
try try
{ {
switch (body.Config?.Singularity?.type)
{
case SingularityModule.SingularityType.BlackHole:
return Color.black;
case SingularityModule.SingularityType.WhiteHole:
return Color.white;
}
var starColor = body.Config?.Star?.tint; var starColor = body.Config?.Star?.tint;
if (starColor != null) return starColor.ToColor(); if (starColor != null) return starColor.ToColor();
@ -555,6 +547,14 @@ namespace NewHorizons.Builder.ShipLog
var sandColor = body.Config.Sand?.tint; var sandColor = body.Config.Sand?.tint;
if (sandColor != null) return sandColor.ToColor(); if (sandColor != null) return sandColor.ToColor();
switch (body.Config?.Props?.singularities?.FirstOrDefault()?.type)
{
case SingularityModule.SingularityType.BlackHole:
return Color.black;
case SingularityModule.SingularityType.WhiteHole:
return Color.white;
}
} }
catch (Exception) catch (Exception)
{ {

View File

@ -0,0 +1,21 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NewHorizons.Components
{
public class RingFluidVolume : SimpleFluidVolume
{
public override void OnEffectVolumeEnter(GameObject hitObj)
{
FluidDetector fluidDetector = hitObj.GetComponent<FluidDetector>();
if (fluidDetector == null) return;
ForceDetector forceDetector = hitObj.GetComponent<ForceDetector>();
if (forceDetector != null && forceDetector._activeVolumes != null && forceDetector._activeVolumes.Count > 0 && forceDetector._activeVolumes.Where(activeVolume => activeVolume is ForceVolume).Select(activeVolume => activeVolume as ForceVolume).Any(activeVolume => activeVolume.GetAffectsAlignment(forceDetector._attachedBody))) return;
fluidDetector.AddVolume(this);
}
}
}

View File

@ -50,6 +50,9 @@ namespace NewHorizons.External.Configs
[Obsolete("ChildrenToDestroy is deprecated, please use RemoveChildren instead")] [Obsolete("ChildrenToDestroy is deprecated, please use RemoveChildren instead")]
public string[] childrenToDestroy; public string[] childrenToDestroy;
[Obsolete("Singularity is deprecated, please use Props->singularities")]
public SingularityModule Singularity;
#endregion Obsolete #endregion Obsolete
/// <summary> /// <summary>
@ -138,11 +141,6 @@ namespace NewHorizons.External.Configs
/// </summary> /// </summary>
public SignalModule Signal; public SignalModule Signal;
/// <summary>
/// Add a black or white hole to this planet
/// </summary>
public SingularityModule Singularity;
/// <summary> /// <summary>
/// Spawn the player at this planet /// Spawn the player at this planet
/// </summary> /// </summary>
@ -329,6 +327,13 @@ namespace NewHorizons.External.Configs
} }
} }
// Singularity is now a list in props so you can have many per planet
if (Singularity != null)
{
if (Props == null) Props = new PropModule();
if (Props.singularities == null) Props.singularities = new SingularityModule[0];
Props.singularities = Props.singularities.Append(Singularity).ToArray();
}
} }
} }
} }

View File

@ -6,6 +6,7 @@ using System.Runtime.Serialization;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Converters; using Newtonsoft.Json.Converters;
using System; using System;
using NewHorizons.External.Modules.VariableSize;
namespace NewHorizons.External.Modules namespace NewHorizons.External.Modules
{ {
@ -77,6 +78,11 @@ namespace NewHorizons.External.Modules
/// </summary> /// </summary>
public VolcanoInfo[] volcanoes; public VolcanoInfo[] volcanoes;
/// <summary>
/// Add black/white-holes to this planet
/// </summary>
public SingularityModule[] singularities;
[JsonObject] [JsonObject]
public class ScatterInfo public class ScatterInfo
{ {
@ -169,6 +175,11 @@ namespace NewHorizons.External.Modules
/// If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is /// If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is
/// </summary> /// </summary>
public string quantumGroupID; public string quantumGroupID;
/// <summary>
/// The path (not including the root planet object) of the parent of this game object. Optional (will default to the root sector).
/// </summary>
public string parentPath;
} }
[JsonObject] [JsonObject]

View File

@ -1,4 +1,4 @@
using System.ComponentModel; using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using NewHorizons.Utility; using NewHorizons.Utility;
@ -24,11 +24,16 @@ namespace NewHorizons.External.Modules.VariableSize
[DefaultValue(true)] public bool makeZeroGVolume = true; [DefaultValue(true)] public bool makeZeroGVolume = true;
/// <summary> /// <summary>
/// The name of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill /// The uniqueID of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill
/// the player /// the player
/// </summary> /// </summary>
public string pairedSingularity; public string pairedSingularity;
/// <summary>
/// The uniqueID of this white hole or black hole. If not set it will default to the name of the planet
/// </summary>
public string uniqueID;
/// <summary> /// <summary>
/// Position of the singularity /// Position of the singularity
/// </summary> /// </summary>

View File

@ -56,6 +56,11 @@ namespace NewHorizons.External.Modules.VariableSize
/// </summary> /// </summary>
public MColor tint; public MColor tint;
/// <summary>
/// Path to the texture to put as the star ramp. Optional.
/// </summary>
public string starRampTexture;
/// <summary> /// <summary>
/// How far the light from the star can reach. /// How far the light from the star can reach.
/// </summary> /// </summary>

View File

@ -269,7 +269,9 @@ namespace NewHorizons.Handlers
{ {
foreach (var child in body.Config.removeChildren) foreach (var child in body.Config.removeChildren)
{ {
Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => SearchUtilities.Find(go.name + "/" + child)?.SetActive(false), 2); // We purposefully use GameObject.Find here because we don't want to find inactive things.
// If you were to try and disable two children with the same name, if we were finding inactive then we'd disable the first one twice
Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => GameObject.Find(go.name + "/" + child)?.SetActive(false), 2);
} }
} }
@ -456,7 +458,7 @@ namespace NewHorizons.Handlers
if (body.Config.Star != null) if (body.Config.Star != null)
{ {
StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star)); StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star, body.Mod));
} }
if (body.Config?.Bramble?.nodes != null) if (body.Config?.Bramble?.nodes != null)
@ -516,7 +518,7 @@ namespace NewHorizons.Handlers
if (!string.IsNullOrEmpty(body.Config.Atmosphere?.clouds?.texturePath)) if (!string.IsNullOrEmpty(body.Config.Atmosphere?.clouds?.texturePath))
{ {
CloudsBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod); CloudsBuilder.Make(go, sector, body.Config.Atmosphere, body.Mod);
SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, surfaceSize); SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, body.Config.Water, surfaceSize);
} }
if (body.Config.Atmosphere.hasRain || body.Config.Atmosphere.hasSnow) if (body.Config.Atmosphere.hasRain || body.Config.Atmosphere.hasSnow)
@ -538,11 +540,6 @@ namespace NewHorizons.Handlers
SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod); SignalBuilder.Make(go, sector, body.Config.Signal, body.Mod);
} }
if (body.Config.Singularity != null)
{
SingularityBuilder.Make(go, sector, rb, body.Config);
}
if (body.Config.Funnel != null) if (body.Config.Funnel != null)
{ {
FunnelBuilder.Make(go, go.GetComponentInChildren<ConstantForceDetector>(), rb, body.Config.Funnel); FunnelBuilder.Make(go, go.GetComponentInChildren<ConstantForceDetector>(), rb, body.Config.Funnel);

View File

@ -29,7 +29,7 @@ namespace NewHorizons.Handlers
GameObject panRoot = SearchUtilities.Find(PAN_ROOT_PATH); GameObject panRoot = SearchUtilities.Find(PAN_ROOT_PATH);
if (panRoot != null) if (panRoot != null)
{ {
List<GameObject> gameObjects = SearchUtilities.GetAllChildren(panRoot); List<GameObject> gameObjects = panRoot.GetAllChildren();
_vanillaBodies = gameObjects.ConvertAll(g => g.name).ToArray(); _vanillaBodies = gameObjects.ConvertAll(g => g.name).ToArray();
_vanillaBodyIDs = gameObjects.ConvertAll(g => g.GetComponent<ShipLogAstroObject>()?.GetID()).ToArray(); _vanillaBodyIDs = gameObjects.ConvertAll(g => g.GetComponent<ShipLogAstroObject>()?.GetID()).ToArray();
} }

View File

@ -0,0 +1,35 @@
using OWML.Common;
using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;
namespace NewHorizons
{
public interface INewHorizons
{
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
void Create(Dictionary<string, object> config);
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
void Create(Dictionary<string, object> config, IModBehaviour mod);
void LoadConfigs(IModBehaviour mod);
GameObject GetPlanet(string name);
string GetCurrentStarSystem();
UnityEvent<string> GetChangeStarSystemEvent();
UnityEvent<string> GetStarSystemLoadedEvent();
bool SetDefaultSystem(string name);
bool ChangeCurrentStarSystem(string name);
string[] GetInstalledAddons();
GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, float scale, bool alignWithNormal);
}
}

View File

@ -8,6 +8,7 @@ using NewHorizons.Handlers;
using NewHorizons.Utility; using NewHorizons.Utility;
using NewHorizons.Utility.DebugMenu; using NewHorizons.Utility.DebugMenu;
using NewHorizons.Utility.DebugUtilities; using NewHorizons.Utility.DebugUtilities;
using NewHorizons.VoiceActing;
using OWML.Common; using OWML.Common;
using OWML.ModHelper; using OWML.ModHelper;
using System; using System;
@ -183,6 +184,7 @@ namespace NewHorizons
Instance.ModHelper.Menus.PauseMenu.OnInit += DebugReload.InitializePauseMenu; Instance.ModHelper.Menus.PauseMenu.OnInit += DebugReload.InitializePauseMenu;
AchievementHandler.Init(); AchievementHandler.Init();
VoiceHandler.Init();
} }
public void OnDestroy() public void OnDestroy()
@ -198,15 +200,6 @@ namespace NewHorizons
private static void OnWakeUp() private static void OnWakeUp()
{ {
IsSystemReady = true; IsSystemReady = true;
try
{
Logger.Log($"Star system loaded [{Instance.CurrentStarSystem}]");
Instance.OnStarSystemLoaded?.Invoke(Instance.CurrentStarSystem);
}
catch (Exception e)
{
Logger.LogError($"Exception thrown when invoking star system loaded event with parameter [{Instance.CurrentStarSystem}] : {e.GetType().FullName} {e.Message} {e.StackTrace}");
}
} }
private void OnSceneUnloaded(Scene scene) private void OnSceneUnloaded(Scene scene)
@ -302,6 +295,16 @@ namespace NewHorizons
// Fix the map satellite // Fix the map satellite
SearchUtilities.Find("HearthianMapSatellite_Body", false).AddComponent<MapSatelliteOrbitFix>(); SearchUtilities.Find("HearthianMapSatellite_Body", false).AddComponent<MapSatelliteOrbitFix>();
try
{
Logger.Log($"Star system loaded [{Instance.CurrentStarSystem}]");
Instance.OnStarSystemLoaded?.Invoke(Instance.CurrentStarSystem);
}
catch (Exception e)
{
Logger.LogError($"Exception thrown when invoking star system loaded event with parameter [{Instance.CurrentStarSystem}] : {e.GetType().FullName} {e.Message} {e.StackTrace}");
}
} }
else else
{ {

View File

@ -9,9 +9,10 @@ using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.Events; using UnityEngine.Events;
using Logger = NewHorizons.Utility.Logger; using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons namespace NewHorizons
{ {
public class NewHorizonsApi public class NewHorizonsApi : INewHorizons
{ {
[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")]
public void Create(Dictionary<string, object> config) public void Create(Dictionary<string, object> config)

View File

@ -145,7 +145,7 @@ namespace NewHorizons.Patches
__instance._startingAstroObjectID = navMatrix[1][0].GetID(); __instance._startingAstroObjectID = navMatrix[1][0].GetID();
if (Main.Instance.CurrentStarSystem != "SolarSystem") if (Main.Instance.CurrentStarSystem != "SolarSystem")
{ {
List<GameObject> delete = SearchUtilities.GetAllChildren(panRoot).Where(g => g.name.Contains("_ShipLog") == false).ToList(); List<GameObject> delete = panRoot.GetAllChildren().Where(g => g.name.Contains("_ShipLog") == false).ToList();
foreach (GameObject gameObject in delete) foreach (GameObject gameObject in delete)
{ {
Object.Destroy(SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + gameObject.name)); Object.Destroy(SearchUtilities.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + gameObject.name));
@ -182,7 +182,7 @@ namespace NewHorizons.Patches
Transform detailsParent = __instance.transform.Find("Details"); Transform detailsParent = __instance.transform.Find("Details");
if (detailsParent != null) if (detailsParent != null)
{ {
foreach (GameObject child in SearchUtilities.GetAllChildren(detailsParent.gameObject)) foreach (GameObject child in detailsParent.gameObject.GetAllChildren())
{ {
if (child.TryGetComponent(typeof(ShipLogDetail), out Component detail)) if (child.TryGetComponent(typeof(ShipLogDetail), out Component detail))
{ {

View File

@ -102,10 +102,6 @@
"description": "Add signals that can be heard via the signal-scope to this planet", "description": "Add signals that can be heard via the signal-scope to this planet",
"$ref": "#/definitions/SignalModule" "$ref": "#/definitions/SignalModule"
}, },
"Singularity": {
"description": "Add a black or white hole to this planet",
"$ref": "#/definitions/SingularityModule"
},
"Spawn": { "Spawn": {
"description": "Spawn the player at this planet", "description": "Spawn the player at this planet",
"$ref": "#/definitions/SpawnModule" "$ref": "#/definitions/SpawnModule"
@ -811,6 +807,13 @@
"items": { "items": {
"$ref": "#/definitions/VolcanoInfo" "$ref": "#/definitions/VolcanoInfo"
} }
},
"singularities": {
"type": "array",
"description": "Add black/white-holes to this planet",
"items": {
"$ref": "#/definitions/SingularityModule"
}
} }
} }
}, },
@ -862,6 +865,10 @@
"quantumGroupID": { "quantumGroupID": {
"type": "string", "type": "string",
"description": "If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is" "description": "If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is"
},
"parentPath": {
"type": "string",
"description": "The path (not including the root planet object) of the parent of this game object. Optional (will default to the root sector)."
} }
} }
}, },
@ -1447,6 +1454,62 @@
} }
} }
}, },
"SingularityModule": {
"type": "object",
"additionalProperties": false,
"properties": {
"curve": {
"type": "array",
"description": "Scale this module over time",
"items": {
"$ref": "#/definitions/TimeValuePair"
}
},
"makeZeroGVolume": {
"type": "boolean",
"description": "Only for White Holes. Should this white hole repel the player from it.",
"default": true
},
"pairedSingularity": {
"type": "string",
"description": "The uniqueID of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill\nthe player"
},
"uniqueID": {
"type": "string",
"description": "The uniqueID of this white hole or black hole. If not set it will default to the name of the planet"
},
"position": {
"description": "Position of the singularity",
"$ref": "#/definitions/MVector3"
},
"size": {
"type": "number",
"description": "Radius of the singularity. Note that this isn't the same as the event horizon, but includes the entire volume that\nhas warped effects in it.",
"format": "float",
"minimum": 0.0
},
"targetStarSystem": {
"type": "string",
"description": "If you want a black hole to load a new star system scene, put its name here."
},
"type": {
"description": "Type of singularity (white hole or black hole)",
"$ref": "#/definitions/SingularityType"
}
}
},
"SingularityType": {
"type": "string",
"description": "",
"x-enumNames": [
"BlackHole",
"WhiteHole"
],
"enum": [
"blackHole",
"whiteHole"
]
},
"ReferenceFrameModule": { "ReferenceFrameModule": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@ -1725,58 +1788,6 @@
} }
} }
}, },
"SingularityModule": {
"type": "object",
"additionalProperties": false,
"properties": {
"curve": {
"type": "array",
"description": "Scale this module over time",
"items": {
"$ref": "#/definitions/TimeValuePair"
}
},
"makeZeroGVolume": {
"type": "boolean",
"description": "Only for White Holes. Should this white hole repel the player from it.",
"default": true
},
"pairedSingularity": {
"type": "string",
"description": "The name of the white hole or black hole that is paired to this one. If you don't set a value, entering will kill\nthe player"
},
"position": {
"description": "Position of the singularity",
"$ref": "#/definitions/MVector3"
},
"size": {
"type": "number",
"description": "Radius of the singularity. Note that this isn't the same as the event horizon, but includes the entire volume that\nhas warped effects in it.",
"format": "float",
"minimum": 0.0
},
"targetStarSystem": {
"type": "string",
"description": "If you want a black hole to load a new star system scene, put its name here."
},
"type": {
"description": "Type of singularity (white hole or black hole)",
"$ref": "#/definitions/SingularityType"
}
}
},
"SingularityType": {
"type": "string",
"description": "",
"x-enumNames": [
"BlackHole",
"WhiteHole"
],
"enum": [
"blackHole",
"whiteHole"
]
},
"SpawnModule": { "SpawnModule": {
"type": "object", "type": "object",
"additionalProperties": false, "additionalProperties": false,
@ -1859,6 +1870,10 @@
"description": "Colour of the star.", "description": "Colour of the star.",
"$ref": "#/definitions/MColor" "$ref": "#/definitions/MColor"
}, },
"starRampTexture": {
"type": "string",
"description": "Path to the texture to put as the star ramp. Optional."
},
"lightRadius": { "lightRadius": {
"type": "number", "type": "number",
"description": "How far the light from the star can reach.", "description": "How far the light from the star can reach.",

View File

@ -131,6 +131,15 @@ namespace NewHorizons.Utility
case AstroObject.Name.MapSatellite: case AstroObject.Name.MapSatellite:
otherChildren.Add(SearchUtilities.Find("HearthianRecorder_Body")); otherChildren.Add(SearchUtilities.Find("HearthianRecorder_Body"));
break; break;
case AstroObject.Name.DarkBramble:
otherChildren.Add(SearchUtilities.Find("DB_ClusterDimension_Body"));
otherChildren.Add(SearchUtilities.Find("DB_VesselDimension_Body"));
otherChildren.Add(SearchUtilities.Find("DB_PioneerDimension_Body"));
otherChildren.Add(SearchUtilities.Find("DB_HubDimension_Body"));
otherChildren.Add(SearchUtilities.Find("DB_ExitOnlyDimension_Body"));
otherChildren.Add(SearchUtilities.Find("DB_EscapePodDimension_Body"));
otherChildren.Add(SearchUtilities.Find("DB_AnglerNestDimension_Body"));
break;
// For some dumb reason the sun station doesn't use AstroObject.Name.SunStation // For some dumb reason the sun station doesn't use AstroObject.Name.SunStation
case AstroObject.Name.CustomString: case AstroObject.Name.CustomString:
if (primary._customName.Equals("Sun Station")) if (primary._customName.Equals("Sun Station"))

View File

@ -100,7 +100,7 @@ namespace NewHorizons.Utility.DebugUtilities
var hitAstroObject = o.GetComponent<AstroObject>() ?? o.GetComponentInParent<AstroObject>(); var hitAstroObject = o.GetComponent<AstroObject>() ?? o.GetComponentInParent<AstroObject>();
data.bodyName = o.name; data.bodyName = o.name;
data.bodyPath = SearchUtilities.GetPath(o.transform); data.bodyPath = o.transform.GetPath();
data.hitObject = o; data.hitObject = o;
data.hitBodyGameObject = hitAstroObject?.gameObject ?? o; data.hitBodyGameObject = hitAstroObject?.gameObject ?? o;
data.plane = ConstructPlane(data); data.plane = ConstructPlane(data);

View File

@ -36,7 +36,7 @@ namespace NewHorizons.Utility
public static void LogPath(GameObject go) public static void LogPath(GameObject go)
{ {
if (go == null) Log("Can't print path: GameObject is null"); if (go == null) Log("Can't print path: GameObject is null");
else Log($"{SearchUtilities.GetPath(go.transform)}"); else Log($"{go.transform.GetPath()}");
} }
public static void Log(string text, LogType type) public static void Log(string text, LogType type)

View File

@ -1,8 +1,10 @@
using System; using HarmonyLib;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
using UnityEngine.SceneManagement;
using Object = UnityEngine.Object; using Object = UnityEngine.Object;
namespace NewHorizons.Utility namespace NewHorizons.Utility
{ {
public static class SearchUtilities public static class SearchUtilities
@ -15,23 +17,6 @@ namespace NewHorizons.Utility
CachedGameObjects.Clear(); CachedGameObjects.Clear();
} }
public static GameObject CachedFind(string path)
{
if (CachedGameObjects.ContainsKey(path))
{
return CachedGameObjects[path];
}
else
{
GameObject foundObject = GameObject.Find(path);
if (foundObject != null)
{
CachedGameObjects.Add(path, foundObject);
}
return foundObject;
}
}
public static List<T> FindObjectsOfTypeAndName<T>(string name) where T : Object public static List<T> FindObjectsOfTypeAndName<T>(string name) where T : Object
{ {
T[] firstList = GameObject.FindObjectsOfType<T>(); T[] firstList = GameObject.FindObjectsOfType<T>();
@ -94,118 +79,47 @@ namespace NewHorizons.Utility
return null; return null;
} }
public static string GetPath(Transform current) public static string GetPath(this Transform current)
{ {
if (current.parent == null) return current.name; if (current.parent == null) return current.name;
return GetPath(current.parent) + "/" + current.name; return current.parent.GetPath() + "/" + current.name;
} }
/* public static GameObject FindChild(this GameObject g, string childPath) =>
public static GameObject Find(string path) g.transform.Find(childPath)?.gameObject;
{
var go = GameObject.Find(path);
if (go != null) return go;
var names = path.Split(new char[] { '\\', '/' });
foreach (var possibleMatch in FindObjectsOfTypeAndName<GameObject>(names.Last()))
{
Logger.LogPath(possibleMatch);
if (GetPath(possibleMatch.transform) == path) return possibleMatch;
}
return null;
}
*/
public static GameObject FindChild(GameObject g, string childName)
{
foreach(Transform child in g.transform)
{
if (child.gameObject.name == childName) return child.gameObject;
}
return null;
}
public static GameObject Find(string path, bool warn = true) public static GameObject Find(string path, bool warn = true)
{ {
if (CachedGameObjects.ContainsKey(path)) if (CachedGameObjects.TryGetValue(path, out var go)) return go;
{
return CachedGameObjects[path]; go = GameObject.Find(path);
} if (go != null) return go;
try
{ var names = path.Split('/');
var go = GameObject.Find(path); var rootName = names[0];
var root = SceneManager.GetActiveScene().GetRootGameObjects().FirstOrDefault(x => x.name == rootName);
var names = path.Split(new char[] { '\\', '/' }); if (root == null)
if (go == null)
{
// Get the root object and hope its the right one
var root = GameObject.Find(names[0]);
if (root == null) root = UnityEngine.SceneManagement.SceneManager.GetActiveScene().GetRootGameObjects().Where(x => x.name.Equals(names[0])).FirstOrDefault();
var t = root?.transform;
if (t == null)
{
if (warn) Logger.LogWarning($"Couldn't find root object in path ({names[0]})");
}
else
{
for (int i = 1; i < names.Length; i++)
{
var child = t.transform.Find(names[i]);
if (child == null)
{
foreach (Transform c in t.GetComponentsInChildren<Transform>(true))
{
if (c.name.Equals(names[i]))
{
child = c;
break;
}
}
}
if (child == null)
{
if (warn) Logger.LogWarning($"Couldn't find object in path ({names[i]})");
t = null;
break;
}
t = child;
}
}
go = t?.gameObject;
}
if (go == null)
{
var name = names.Last();
if (warn) Logger.LogWarning($"Couldn't find object {path}, will look for potential matches for name {name}");
go = FindObjectOfTypeAndName<GameObject>(name);
}
if (go != null)
{
CachedGameObjects.Add(path, go);
}
return go;
}
catch (Exception)
{ {
if (warn) Logger.LogWarning($"Couldn't find root object in path ({path})");
return null; return null;
} }
var childPath = names.Skip(1).Join(delimiter: "/");
go = root.FindChild(childPath);
if (go == null)
{
var name = names.Last();
if (warn) Logger.LogWarning($"Couldn't find object in path ({path}), will look for potential matches for name {name}");
go = FindObjectOfTypeAndName<GameObject>(name);
}
CachedGameObjects.Add(path, go);
return go;
} }
public static List<GameObject> GetAllChildren(GameObject parent) public static List<GameObject> GetAllChildren(this GameObject parent)
{ {
List<GameObject> children = new List<GameObject>(); var children = new List<GameObject>();
foreach (Transform child in parent.transform) foreach (Transform child in parent.transform)
{ {
children.Add(child.gameObject); children.Add(child.gameObject);

View File

@ -0,0 +1,7 @@
namespace NewHorizons.VoiceActing
{
public interface IVoiceMod
{
void RegisterAssets(string assetsFolder);
}
}

View File

@ -0,0 +1,41 @@
using NewHorizons.Utility;
using System.IO;
using System.Linq;
namespace NewHorizons.VoiceActing
{
public static class VoiceHandler
{
public static bool Enabled { get; private set; }
private static IVoiceMod API;
public static void Init()
{
API = Main.Instance.ModHelper.Interaction.TryGetModApi<IVoiceMod>("Krevace.VoiceMod");
if (API == null)
{
Logger.Log("VoiceMod isn't installed");
Enabled = false;
return;
}
Enabled = true;
foreach (var mod in Main.Instance.GetDependants().Append(Main.Instance))
{
var folder = $"{mod.ModHelper.Manifest.ModFolderPath}VoiceMod";
if (Directory.Exists(folder))
{
Logger.Log($"Registering VoiceMod audio for {mod.ModHelper.Manifest.Name} from {folder}");
API.RegisterAssets(folder);
}
else
{
Logger.Log($"Didn't find VoiceMod audio for {mod.ModHelper.Manifest.Name} at {folder}");
}
}
}
}
}

View File

@ -1,9 +1,10 @@
{ {
"$schema": "https://raw.githubusercontent.com/amazingalek/owml/master/schemas/manifest_schema.json",
"filename": "NewHorizons.dll", "filename": "NewHorizons.dll",
"author": "xen and Bwc9876", "author": "xen, Bwc9876, clay, MegaPiggy, John, Book",
"name": "New Horizons", "name": "New Horizons",
"uniqueName": "xen.NewHorizons", "uniqueName": "xen.NewHorizons",
"version": "1.3.1", "version": "1.3.2",
"owmlVersion": "2.5.2", "owmlVersion": "2.5.2",
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.AutoResume", "PacificEngine.OW_Randomizer" ], "conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.AutoResume", "PacificEngine.OW_Randomizer" ],
"pathsToPreserve": [ "planets", "systems", "translations" ] "pathsToPreserve": [ "planets", "systems", "translations" ]