mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
commit
bafe330c52
@ -14,12 +14,11 @@ namespace NewHorizons.Builder.Atmosphere
|
||||
private static Material[] _qmCloudMaterials;
|
||||
private static GameObject _lightningPrefab;
|
||||
private static Texture2D _colorRamp;
|
||||
private static readonly int Color1 = Shader.PropertyToID("_Color");
|
||||
private static readonly int TintColor = Shader.PropertyToID("_TintColor");
|
||||
private static readonly int Color = Shader.PropertyToID("_Color");
|
||||
private static readonly int ColorRamp = Shader.PropertyToID("_ColorRamp");
|
||||
private static readonly int MainTex = Shader.PropertyToID("_MainTex");
|
||||
private static readonly int RampTex = Shader.PropertyToID("_RampTex");
|
||||
private static readonly int CapTex = Shader.PropertyToID("_CapTex");
|
||||
private static readonly int ColorRamp = Shader.PropertyToID("_ColorRamp");
|
||||
|
||||
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, bool cloaked, IModBehaviour mod)
|
||||
{
|
||||
@ -49,8 +48,7 @@ namespace NewHorizons.Builder.Atmosphere
|
||||
var bottomTSRTempArray = new Material[2];
|
||||
|
||||
bottomTSRTempArray[0] = new Material(bottomTSRMaterials[0]);
|
||||
bottomTSRTempArray[0].SetColor(Color1, bottomColor);
|
||||
bottomTSRTempArray[0].SetColor(TintColor, bottomColor);
|
||||
bottomTSRTempArray[0].SetColor(Color, bottomColor);
|
||||
bottomTSRTempArray[0].SetTexture(ColorRamp, ImageUtilities.TintImage(_colorRamp, bottomColor));
|
||||
|
||||
bottomTSRTempArray[1] = new Material(bottomTSRMaterials[1]);
|
||||
@ -144,7 +142,7 @@ namespace NewHorizons.Builder.Atmosphere
|
||||
|
||||
public static GameObject MakeTopClouds(GameObject rootObject, AtmosphereModule atmo, IModBehaviour mod)
|
||||
{
|
||||
Color cloudTint = atmo.clouds.tint?.ToColor() ?? Color.white;
|
||||
Color cloudTint = atmo.clouds.tint?.ToColor() ?? UnityEngine.Color.white;
|
||||
|
||||
Texture2D image, cap, ramp;
|
||||
|
||||
@ -202,9 +200,6 @@ namespace NewHorizons.Builder.Atmosphere
|
||||
|
||||
foreach (var material in topMR.sharedMaterials)
|
||||
{
|
||||
material.SetColor(Color1, cloudTint);
|
||||
material.SetColor(TintColor, cloudTint);
|
||||
|
||||
material.SetTexture(MainTex, image);
|
||||
material.SetTexture(RampTex, ramp);
|
||||
material.SetTexture(CapTex, cap);
|
||||
|
||||
@ -2,6 +2,7 @@ using HarmonyLib;
|
||||
using NewHorizons.Builder.Props;
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.Components.Orbital;
|
||||
using NewHorizons.External.Modules;
|
||||
using NewHorizons.Handlers;
|
||||
using NewHorizons.Utility;
|
||||
using System.Collections.Generic;
|
||||
@ -56,7 +57,11 @@ namespace NewHorizons.Builder.Body
|
||||
var atmo = SearchUtilities.Find("DB_HubDimension_Body/Sector_HubDimension/Atmosphere_HubDimension").InstantiateInactive();
|
||||
var volumes = SearchUtilities.Find("DB_HubDimension_Body/Sector_HubDimension/Volumes_HubDimension").InstantiateInactive();
|
||||
var effects = SearchUtilities.Find("DB_HubDimension_Body/Sector_HubDimension/Effects_HubDimension").InstantiateInactive();
|
||||
var geometry = DetailBuilder.MakeDetail(go, sector, "DB_HubDimension_Body/Sector_HubDimension/Geometry_HubDimension", Vector3.zero, Vector3.zero, 1, false);
|
||||
|
||||
var prefab = SearchUtilities.Find("DB_HubDimension_Body/Sector_HubDimension/Geometry_HubDimension");
|
||||
var detailInfo = new PropModule.DetailInfo();
|
||||
var geometry = DetailBuilder.MakeDetail(go, sector, prefab, detailInfo);
|
||||
|
||||
var exitWarps = SearchUtilities.Find("DB_HubDimension_Body/Sector_HubDimension/OuterWarp_Hub").InstantiateInactive();
|
||||
var repelVolume = SearchUtilities.Find("DB_HubDimension_Body/BrambleRepelVolume").InstantiateInactive();
|
||||
|
||||
|
||||
@ -28,11 +28,13 @@ namespace NewHorizons.Builder.Props
|
||||
{
|
||||
var prefab = AssetBundleUtilities.LoadPrefab(detail.assetBundle, detail.path, mod);
|
||||
|
||||
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
|
||||
detailGO = MakeDetail(go, sector, prefab, detail);
|
||||
}
|
||||
else
|
||||
{
|
||||
detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
|
||||
var prefab = SearchUtilities.Find(detail.path);
|
||||
if (prefab == null) Logger.LogError($"Couldn't find detail {detail.path}");
|
||||
else detailGO = MakeDetail(go, sector, prefab, detail);
|
||||
}
|
||||
|
||||
if (detailGO == null) return;
|
||||
@ -94,14 +96,7 @@ namespace NewHorizons.Builder.Props
|
||||
detailInfoToCorrespondingSpawnedGameObject[detail] = detailGO;
|
||||
}
|
||||
|
||||
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
|
||||
{
|
||||
var prefab = SearchUtilities.Find(propToClone);
|
||||
if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}");
|
||||
return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal);
|
||||
}
|
||||
|
||||
public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
|
||||
public static GameObject MakeDetail(GameObject planetGO, Sector sector, GameObject prefab, PropModule.DetailInfo info)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
|
||||
@ -111,165 +106,24 @@ namespace NewHorizons.Builder.Props
|
||||
|
||||
StreamingHandler.SetUpStreaming(prop, sector);
|
||||
|
||||
var torchItem = prop.GetComponent<VisionTorchItem>();
|
||||
// Fix vision torch
|
||||
if (torchItem)
|
||||
{
|
||||
torchItem.enabled = true;
|
||||
torchItem.mindProjectorTrigger.enabled = true;
|
||||
torchItem.mindSlideProjector._mindProjectorImageEffect = SearchUtilities.Find("Player_Body/PlayerCamera").GetComponent<MindProjectorImageEffect>();
|
||||
}
|
||||
var isTorch = prop.GetComponent<VisionTorchItem>() != null;
|
||||
|
||||
foreach (var component in prop.GetComponentsInChildren<Component>(true))
|
||||
{
|
||||
/*
|
||||
// Enable all children or something
|
||||
// BUG doesnt work because enabled is a property, not a field
|
||||
var enabledField = component?.GetType()?.GetField("enabled");
|
||||
if (enabledField != null && enabledField.FieldType == typeof(bool)) Events.FireOnNextUpdate(() => enabledField.SetValue(component, true));
|
||||
*/
|
||||
|
||||
// Fix a bunch of sector stuff
|
||||
if (sector != null)
|
||||
if (sector == null)
|
||||
{
|
||||
if (component is Sector s)
|
||||
{
|
||||
s.SetParentSector(sector);
|
||||
}
|
||||
|
||||
if (component is SectorCullGroup sectorCullGroup)
|
||||
{
|
||||
sectorCullGroup._controllingProxy = null;
|
||||
}
|
||||
|
||||
// fix Sector stuff, eg SectorCullGroup (without this, props that have a SectorCullGroup component will become invisible inappropriately)
|
||||
if (component is ISectorGroup sectorGroup)
|
||||
{
|
||||
sectorGroup.SetSector(sector);
|
||||
}
|
||||
|
||||
if (component is GhostIK ik) ik.enabled = false;
|
||||
if (component is GhostEffects effects) effects.enabled = false;
|
||||
|
||||
if (component is DarkMatterVolume)
|
||||
{
|
||||
var probeVisuals = component.gameObject.transform.Find("ProbeVisuals");
|
||||
if (probeVisuals != null) probeVisuals.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
if (component is SectoredMonoBehaviour behaviour)
|
||||
{
|
||||
behaviour.SetSector(sector);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
// BUG: this doesnt find the field cuz _sector is private
|
||||
var sectorField = component?.GetType()?.GetField("_sector");
|
||||
if (sectorField != null && sectorField.FieldType == typeof(Sector))
|
||||
{
|
||||
Events.FireOnNextUpdate(() => sectorField.SetValue(component, sector));
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
if (component is AnglerfishController angler)
|
||||
{
|
||||
try
|
||||
{
|
||||
angler._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent<AstroObject>().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Couldn't update AnglerFish chase speed:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
// Fix slide reel
|
||||
// softlocks if this object is a vision torch
|
||||
if (!torchItem && component is SlideCollectionContainer container)
|
||||
{
|
||||
sector.OnOccupantEnterSector.AddListener(_ => container.LoadStreamingTextures());
|
||||
}
|
||||
|
||||
if (component is OWItemSocket socket)
|
||||
{
|
||||
socket._sector = sector;
|
||||
}
|
||||
|
||||
// fix campfires
|
||||
if (component is InteractVolume interactVolume)
|
||||
{
|
||||
interactVolume._playerCam = GameObject.Find("Player_Body/PlayerCamera").GetComponent<OWCamera>();
|
||||
}
|
||||
if (component is PlayerAttachPoint playerAttachPoint)
|
||||
{
|
||||
var playerBody = GameObject.Find("Player_Body");
|
||||
playerAttachPoint._playerController = playerBody.GetComponent<PlayerCharacterController>();
|
||||
playerAttachPoint._playerOWRigidbody = playerBody.GetComponent<OWRigidbody>();
|
||||
playerAttachPoint._playerTransform = playerBody.transform;
|
||||
playerAttachPoint._fpsCamController = GameObject.Find("Player_Body/PlayerCamera").GetComponent<PlayerCameraController>();
|
||||
}
|
||||
|
||||
if (component is NomaiInterfaceOrb orb)
|
||||
{
|
||||
orb._parentAstroObject = planetGO.GetComponent<AstroObject>();
|
||||
orb._parentBody = planetGO.GetComponent<OWRigidbody>();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Remove things that require sectors if the sector is null. Will just keep extending this as things pop up.
|
||||
if (component is FogLight or SectoredMonoBehaviour)
|
||||
{
|
||||
GameObject.DestroyImmediate(component);
|
||||
continue;
|
||||
}
|
||||
if (FixUnsectoredComponent(component)) continue;
|
||||
}
|
||||
else FixSectoredComponent(component, sector, isTorch);
|
||||
|
||||
// Fix a bunch of stuff when done loading
|
||||
Delay.RunWhen(() => Main.IsSystemReady, () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (component == null) return;
|
||||
if (component is Animator animator) animator.enabled = true;
|
||||
else if (component is Collider collider) collider.enabled = true;
|
||||
else if (component is Renderer renderer) renderer.enabled = true;
|
||||
else if (component is Shape shape) shape.enabled = true;
|
||||
else if (component is SectorCullGroup sectorCullGroup)
|
||||
{
|
||||
sectorCullGroup._inMapView = false;
|
||||
sectorCullGroup._isFastForwarding = false;
|
||||
sectorCullGroup.SetVisible(sectorCullGroup.ShouldBeVisible(), true, false);
|
||||
}
|
||||
// If it's not a moving anglerfish make sure the anim controller is regular
|
||||
else if (component is AnglerfishAnimController angler && angler.GetComponentInParent<AnglerfishController>() == null)
|
||||
{
|
||||
Logger.LogVerbose("Enabling anglerfish animation");
|
||||
// Remove any reference to its angler
|
||||
if (angler._anglerfishController)
|
||||
{
|
||||
angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState;
|
||||
angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn;
|
||||
angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended;
|
||||
angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended;
|
||||
}
|
||||
angler.enabled = true;
|
||||
angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] for prop [{prefab.name}]:\n{e}");
|
||||
}
|
||||
});
|
||||
FixComponent(component, planetGO, prefab.name);
|
||||
}
|
||||
|
||||
prop.transform.position = position == null ? planetGO.transform.position : planetGO.transform.TransformPoint((Vector3)position);
|
||||
prop.transform.position = info.position == null ? planetGO.transform.position : planetGO.transform.TransformPoint(info.position);
|
||||
|
||||
Quaternion rot = rotation == null ? Quaternion.identity : Quaternion.Euler((Vector3)rotation);
|
||||
if (alignWithNormal)
|
||||
Quaternion rot = info.rotation == null ? Quaternion.identity : Quaternion.Euler(info.rotation);
|
||||
|
||||
if (info.alignToNormal)
|
||||
{
|
||||
// Apply the rotation after aligning it with normal
|
||||
var up = planetGO.transform.InverseTransformPoint(prop.transform.position).normalized;
|
||||
@ -281,11 +135,163 @@ namespace NewHorizons.Builder.Props
|
||||
prop.transform.rotation = planetGO.transform.TransformRotation(rot);
|
||||
}
|
||||
|
||||
prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale;
|
||||
prop.transform.localScale = info.scale != 0 ? Vector3.one * info.scale : prefab.transform.localScale;
|
||||
|
||||
prop.SetActive(true);
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fix components that have sectors. Has a specific fix if there is a VisionTorchItem on the object.
|
||||
/// </summary>
|
||||
/// <param name="component"></param>
|
||||
/// <param name="sector"></param>
|
||||
/// <param name="isTorch"></param>
|
||||
private static void FixSectoredComponent(Component component, Sector sector, bool isTorch = false)
|
||||
{
|
||||
if (component is Sector s)
|
||||
{
|
||||
s.SetParentSector(sector);
|
||||
}
|
||||
|
||||
if (component is SectorCullGroup sectorCullGroup)
|
||||
{
|
||||
sectorCullGroup._controllingProxy = null;
|
||||
}
|
||||
|
||||
// fix Sector stuff, eg SectorCullGroup (without this, props that have a SectorCullGroup component will become invisible inappropriately)
|
||||
if (component is ISectorGroup sectorGroup)
|
||||
{
|
||||
sectorGroup.SetSector(sector);
|
||||
}
|
||||
|
||||
if (component is SectoredMonoBehaviour behaviour)
|
||||
{
|
||||
behaviour.SetSector(sector);
|
||||
}
|
||||
|
||||
if (component is OWItemSocket socket)
|
||||
{
|
||||
socket._sector = sector;
|
||||
}
|
||||
|
||||
// Fix slide reel - Softlocks if this object is a vision torch
|
||||
if (!isTorch && component is SlideCollectionContainer container)
|
||||
{
|
||||
sector.OnOccupantEnterSector.AddListener(_ => container.LoadStreamingTextures());
|
||||
}
|
||||
|
||||
if (component is NomaiRemoteCameraPlatform remoteCameraPlatform)
|
||||
{
|
||||
remoteCameraPlatform._visualSector = sector;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Remove things that require sectors if the sector is null. Will just keep extending this as things pop up.
|
||||
/// Returns true if the object is destroyed
|
||||
/// </summary>
|
||||
private static bool FixUnsectoredComponent(Component component)
|
||||
{
|
||||
if (component is FogLight or SectoredMonoBehaviour)
|
||||
{
|
||||
GameObject.DestroyImmediate(component);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void FixComponent(Component component, GameObject planetGO, string prefab)
|
||||
{
|
||||
// Fix other components
|
||||
// I forget why this is here
|
||||
if (component is GhostIK ik) ik.enabled = false;
|
||||
if (component is GhostEffects effects) effects.enabled = false;
|
||||
|
||||
if (component is DarkMatterVolume)
|
||||
{
|
||||
var probeVisuals = component.gameObject.transform.Find("ProbeVisuals");
|
||||
if (probeVisuals != null) probeVisuals.gameObject.SetActive(true);
|
||||
}
|
||||
|
||||
// Fix anglerfish speed on orbiting planets
|
||||
if (component is AnglerfishController angler)
|
||||
{
|
||||
try
|
||||
{
|
||||
angler._chaseSpeed += OWPhysics.CalculateOrbitVelocity(planetGO.GetAttachedOWRigidbody(), planetGO.GetComponent<AstroObject>().GetPrimaryBody().GetAttachedOWRigidbody()).magnitude;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Couldn't update AnglerFish chase speed:\n{e}");
|
||||
}
|
||||
}
|
||||
|
||||
// fix campfires
|
||||
if (component is InteractVolume interactVolume)
|
||||
{
|
||||
interactVolume._playerCam = GameObject.Find("Player_Body/PlayerCamera").GetComponent<OWCamera>();
|
||||
}
|
||||
if (component is PlayerAttachPoint playerAttachPoint)
|
||||
{
|
||||
var playerBody = GameObject.Find("Player_Body");
|
||||
playerAttachPoint._playerController = playerBody.GetComponent<PlayerCharacterController>();
|
||||
playerAttachPoint._playerOWRigidbody = playerBody.GetComponent<OWRigidbody>();
|
||||
playerAttachPoint._playerTransform = playerBody.transform;
|
||||
playerAttachPoint._fpsCamController = GameObject.Find("Player_Body/PlayerCamera").GetComponent<PlayerCameraController>();
|
||||
}
|
||||
|
||||
if (component is NomaiInterfaceOrb orb)
|
||||
{
|
||||
orb._parentAstroObject = planetGO.GetComponent<AstroObject>();
|
||||
orb._parentBody = planetGO.GetComponent<OWRigidbody>();
|
||||
}
|
||||
|
||||
if (component is VisionTorchItem torchItem)
|
||||
{
|
||||
torchItem.enabled = true;
|
||||
torchItem.mindProjectorTrigger.enabled = true;
|
||||
torchItem.mindSlideProjector._mindProjectorImageEffect = SearchUtilities.Find("Player_Body/PlayerCamera").GetComponent<MindProjectorImageEffect>();
|
||||
}
|
||||
|
||||
// Fix a bunch of stuff when done loading
|
||||
Delay.RunWhen(() => Main.IsSystemReady, () =>
|
||||
{
|
||||
try
|
||||
{
|
||||
if (component == null) return;
|
||||
if (component is Animator animator) animator.enabled = true;
|
||||
else if (component is Collider collider) collider.enabled = true;
|
||||
else if (component is Renderer renderer) renderer.enabled = true;
|
||||
else if (component is Shape shape) shape.enabled = true;
|
||||
else if (component is SectorCullGroup sectorCullGroup)
|
||||
{
|
||||
sectorCullGroup._inMapView = false;
|
||||
sectorCullGroup._isFastForwarding = false;
|
||||
sectorCullGroup.SetVisible(sectorCullGroup.ShouldBeVisible(), true, false);
|
||||
}
|
||||
// If it's not a moving anglerfish make sure the anim controller is regular
|
||||
else if (component is AnglerfishAnimController angler && angler.GetComponentInParent<AnglerfishController>() == null)
|
||||
{
|
||||
Logger.LogVerbose("Enabling anglerfish animation");
|
||||
// Remove any reference to its angler
|
||||
if (angler._anglerfishController)
|
||||
{
|
||||
angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState;
|
||||
angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn;
|
||||
angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended;
|
||||
angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended;
|
||||
}
|
||||
angler.enabled = true;
|
||||
angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] for prop [{prefab}]:\n{e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -276,7 +276,11 @@ namespace NewHorizons.Builder.Props
|
||||
}
|
||||
case PropModule.NomaiTextInfo.NomaiTextType.PreCrashComputer:
|
||||
{
|
||||
var computerObject = DetailBuilder.MakeDetail(planetGO, sector, _preCrashComputerPrefab, info.position, Vector3.zero, 1, false);
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = info.position
|
||||
};
|
||||
var computerObject = DetailBuilder.MakeDetail(planetGO, sector, _preCrashComputerPrefab, detailInfo);
|
||||
computerObject.SetActive(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(info.rename))
|
||||
|
||||
@ -222,7 +222,13 @@ namespace NewHorizons.Builder.Props
|
||||
{
|
||||
// spawn a trigger for the vision torch
|
||||
var path = "DreamWorld_Body/Sector_DreamWorld/Sector_Underground/Sector_PrisonCell/Ghosts_PrisonCell/GhostNodeMap_PrisonCell_Lower/Prefab_IP_GhostBird_Prisoner/Ghostbird_IP_ANIM/Ghostbird_Skin_01:Ghostbird_Rig_V01:Base/Ghostbird_Skin_01:Ghostbird_Rig_V01:Root/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine03/Ghostbird_Skin_01:Ghostbird_Rig_V01:Spine04/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck01/Ghostbird_Skin_01:Ghostbird_Rig_V01:Neck02/Ghostbird_Skin_01:Ghostbird_Rig_V01:Head/PrisonerHeadDetector";
|
||||
var g = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, Vector3.zero, 2, false);
|
||||
var prefab = SearchUtilities.Find(path);
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = info.position,
|
||||
scale = 2
|
||||
};
|
||||
var g = DetailBuilder.MakeDetail(planetGO, sector, prefab, detailInfo);
|
||||
|
||||
if (!string.IsNullOrEmpty(info.parentPath))
|
||||
{
|
||||
@ -280,12 +286,15 @@ namespace NewHorizons.Builder.Props
|
||||
|
||||
public static GameObject MakeStandingVisionTorch(GameObject planetGO, Sector sector, PropModule.ProjectionInfo info, IModBehaviour mod)
|
||||
{
|
||||
//
|
||||
// spawn the torch itself
|
||||
//
|
||||
|
||||
// Spawn the torch itself
|
||||
var path = "RingWorld_Body/Sector_RingWorld/Sector_SecretEntrance/Interactibles_SecretEntrance/Experiment_1/VisionTorchApparatus/VisionTorchRoot/Prefab_IP_VisionTorchProjector";
|
||||
var standingTorch = DetailBuilder.MakeDetail(planetGO, sector, path, info.position, info.rotation, 1, false);
|
||||
var prefab = SearchUtilities.Find(path);
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = info.position,
|
||||
rotation = info.rotation
|
||||
};
|
||||
var standingTorch = DetailBuilder.MakeDetail(planetGO, sector, prefab, detailInfo);
|
||||
|
||||
if (!string.IsNullOrEmpty(info.parentPath))
|
||||
{
|
||||
@ -306,22 +315,16 @@ namespace NewHorizons.Builder.Props
|
||||
return null;
|
||||
}
|
||||
|
||||
//
|
||||
// set some required properties on the torch
|
||||
//
|
||||
|
||||
// Set some required properties on the torch
|
||||
var mindSlideProjector = standingTorch.GetComponent<MindSlideProjector>();
|
||||
mindSlideProjector._mindProjectorImageEffect = SearchUtilities.Find("Player_Body/PlayerCamera").GetComponent<MindProjectorImageEffect>();
|
||||
|
||||
// setup for visually supporting async texture loading
|
||||
// Setup for visually supporting async texture loading
|
||||
mindSlideProjector.enabled = false;
|
||||
var visionBeamEffect = standingTorch.FindChild("VisionBeam");
|
||||
visionBeamEffect.SetActive(false);
|
||||
|
||||
//
|
||||
// set up slides
|
||||
//
|
||||
|
||||
// Set up slides
|
||||
// The number of slides is unlimited, 15 is only for texturing the actual slide reel item. This is not a slide reel item
|
||||
var slides = info.slides;
|
||||
var slidesCount = slides.Length;
|
||||
@ -340,8 +343,8 @@ namespace NewHorizons.Builder.Props
|
||||
slideCollection.slides[i] = slide;
|
||||
}
|
||||
|
||||
// this variable just lets us track how many of the slides have been loaded.
|
||||
// this way as soon as the last one is loaded (due to async loading, this may be
|
||||
// This variable just lets us track how many of the slides have been loaded.
|
||||
// This way as soon as the last one is loaded (due to async loading, this may be
|
||||
// slide 7, or slide 3, or whatever), we can enable the vision torch. This allows us
|
||||
// to avoid doing a "is every element in the array `slideCollection.slides` not null" check every time a texture finishes loading
|
||||
int displaySlidesLoaded = 0;
|
||||
@ -359,13 +362,13 @@ namespace NewHorizons.Builder.Props
|
||||
}
|
||||
);
|
||||
|
||||
// set up the containers for the slides
|
||||
// Set up the containers for the slides
|
||||
var slideCollectionContainer = standingTorch.AddComponent<SlideCollectionContainer>();
|
||||
slideCollectionContainer.slideCollection = slideCollection;
|
||||
var mindSlideCollection = standingTorch.AddComponent<MindSlideCollection>();
|
||||
mindSlideCollection._slideCollectionContainer = slideCollectionContainer;
|
||||
|
||||
// make sure that these slides play when the player wanders into the beam
|
||||
// Make sure that these slides play when the player wanders into the beam
|
||||
mindSlideProjector.SetMindSlideCollection(mindSlideCollection);
|
||||
|
||||
|
||||
|
||||
@ -181,7 +181,7 @@ namespace NewHorizons.Builder.Props
|
||||
{
|
||||
if (!propsByGroup.ContainsKey(quantumGroup.id)) continue;
|
||||
var propsInGroup = propsByGroup[quantumGroup.id];
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
QuantumBuilder.Make(go, sector, config, mod, quantumGroup, propsInGroup.ToArray());
|
||||
@ -220,6 +220,20 @@ namespace NewHorizons.Builder.Props
|
||||
SignalBuilder.Make(go, sector, signal, mod);
|
||||
}
|
||||
}
|
||||
if (config.Props.remotes != null)
|
||||
{
|
||||
foreach (var remoteInfo in config.Props.remotes)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoteBuilder.Make(go, sector, remoteInfo, mod);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Couldn't make remote [{remoteInfo.id}] for [{go.name}]:\n{ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
298
NewHorizons/Builder/Props/RemoteBuilder.cs
Normal file
298
NewHorizons/Builder/Props/RemoteBuilder.cs
Normal file
@ -0,0 +1,298 @@
|
||||
using NewHorizons.External.Modules;
|
||||
using NewHorizons.Handlers;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.Builder.Props
|
||||
{
|
||||
public static class RemoteBuilder
|
||||
{
|
||||
private static Material _decalMaterial;
|
||||
private static Material _decalMaterialGold;
|
||||
private static GameObject _remoteCameraPlatformPrefab;
|
||||
private static GameObject _whiteboardPrefab;
|
||||
private static GameObject _shareStonePrefab;
|
||||
|
||||
private static void InitPrefabs()
|
||||
{
|
||||
_decalMaterial = new Material(Shader.Find("Standard (Decal)"));
|
||||
_decalMaterial.name = "Decal";
|
||||
_decalMaterial.SetTexture("_MainTex", Texture2D.whiteTexture);
|
||||
_decalMaterial.SetTexture("_EmissionMap", Texture2D.whiteTexture);
|
||||
_decalMaterial.SetFloat("_Glossiness", 0);
|
||||
_decalMaterial.SetFloat("_BumpScale", 0);
|
||||
_decalMaterial.SetColor("_Color", new Color(0.3529412f, 0.3843137f, 1));
|
||||
_decalMaterial.SetColor("_EmissionColor", new Color(0.2422811f, 0.2917706f, 2.440062f));
|
||||
_decalMaterialGold = new Material(_decalMaterial);
|
||||
_decalMaterialGold.name = "DecalGold";
|
||||
_decalMaterialGold.SetColor("_Color", new Color(1, 0.6392157f, 0.3803922f));
|
||||
_decalMaterialGold.SetColor("_EmissionColor", new Color(1, 0.3662527f, 0.1195384f));
|
||||
|
||||
_remoteCameraPlatformPrefab = SearchUtilities.Find("OrbitalProbeCannon_Body/Sector_OrbitalProbeCannon/Sector_Module_Broken/Interactables_Module_Broken/Prefab_NOM_RemoteViewer").InstantiateInactive();
|
||||
_remoteCameraPlatformPrefab.name = "Prefab_NOM_RemoteViewer";
|
||||
var remoteCameraPlatform = _remoteCameraPlatformPrefab.GetComponent<NomaiRemoteCameraPlatform>();
|
||||
remoteCameraPlatform.enabled = true;
|
||||
remoteCameraPlatform._id = NomaiRemoteCameraPlatform.ID.None;
|
||||
remoteCameraPlatform._platformState = NomaiRemoteCameraPlatform.State.Disconnected;
|
||||
remoteCameraPlatform._dataPointID = string.Empty;
|
||||
remoteCameraPlatform._visualSector = null;
|
||||
var AstroBodySymbolRenderer = _remoteCameraPlatformPrefab.FindChild("PedestalAnchor/Prefab_NOM_SharedPedestal/SharedPedestal_side01_bottom_jnt/SharedPedestal_side01_top_jnt/AstroBodySymbolRenderer");
|
||||
var quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
|
||||
quad.transform.parent = AstroBodySymbolRenderer.transform.parent;
|
||||
quad.transform.localPosition = AstroBodySymbolRenderer.transform.localPosition;
|
||||
quad.transform.localRotation = AstroBodySymbolRenderer.transform.localRotation;
|
||||
quad.transform.localScale = AstroBodySymbolRenderer.transform.localScale;
|
||||
quad.AddComponent<OWRenderer>();
|
||||
quad.GetComponent<MeshRenderer>().sharedMaterial = _decalMaterial;
|
||||
quad.name = "AstroBodySymbolRenderer";
|
||||
GameObject.DestroyImmediate(AstroBodySymbolRenderer);
|
||||
|
||||
_whiteboardPrefab = SearchUtilities.Find("OrbitalProbeCannon_Body/Sector_OrbitalProbeCannon/Sector_Module_Broken/Interactables_Module_Broken/Prefab_NOM_Whiteboard_Shared").InstantiateInactive();
|
||||
_whiteboardPrefab.name = "Prefab_NOM_Whiteboard_Shared";
|
||||
var whiteboard = _whiteboardPrefab.GetComponent<NomaiSharedWhiteboard>();
|
||||
whiteboard.enabled = true;
|
||||
whiteboard._id = NomaiRemoteCameraPlatform.ID.None;
|
||||
_whiteboardPrefab.FindChild("ArcSocket").transform.DestroyAllChildrenImmediate();
|
||||
whiteboard._remoteIDs = new NomaiRemoteCameraPlatform.ID[0];
|
||||
whiteboard._nomaiTexts = new NomaiWallText[0];
|
||||
var AstroBodySymbolRendererW = _whiteboardPrefab.FindChild("PedestalAnchor/Prefab_NOM_SharedPedestal/SharedPedestal_side01_bottom_jnt/SharedPedestal_side01_top_jnt/AstroBodySymbolRenderer");
|
||||
var quadW = GameObject.CreatePrimitive(PrimitiveType.Quad);
|
||||
quadW.transform.parent = AstroBodySymbolRendererW.transform.parent;
|
||||
quadW.transform.localPosition = AstroBodySymbolRendererW.transform.localPosition;
|
||||
quadW.transform.localRotation = AstroBodySymbolRendererW.transform.localRotation;
|
||||
quadW.transform.localScale = AstroBodySymbolRendererW.transform.localScale;
|
||||
quadW.AddComponent<OWRenderer>();
|
||||
quadW.GetComponent<MeshRenderer>().sharedMaterial = _decalMaterial;
|
||||
quadW.name = "AstroBodySymbolRenderer";
|
||||
GameObject.DestroyImmediate(AstroBodySymbolRendererW);
|
||||
|
||||
GameObject stone = new GameObject("ShareStoneFallback");
|
||||
stone.layer = LayerMask.NameToLayer("Interactible");
|
||||
stone.SetActive(false);
|
||||
SphereCollider sc = stone.AddComponent<SphereCollider>();
|
||||
sc.center = Vector3.zero;
|
||||
sc.radius = 0.4f;
|
||||
sc.isTrigger = false;
|
||||
OWCollider owc = stone.AddComponent<OWCollider>();
|
||||
owc._collider = sc;
|
||||
SharedStone item = stone.AddComponent<SharedStone>();
|
||||
item._connectedPlatform = NomaiRemoteCameraPlatform.ID.None;
|
||||
item._animDuration = 0.4f;
|
||||
item._animOffsetY = 0.08f;
|
||||
GameObject animRoot = new GameObject("AnimRoot");
|
||||
animRoot.transform.parent = stone.transform;
|
||||
TransformAnimator transformAnimator = animRoot.AddComponent<TransformAnimator>();
|
||||
item._animator = transformAnimator;
|
||||
OWRenderer renderer = SearchUtilities.FindResourceOfTypeAndName<OWRenderer>("Props_NOM_SharedStone");
|
||||
if (renderer != null) GameObject.Instantiate(renderer.gameObject, animRoot.transform);
|
||||
GameObject planetDecal = GameObject.CreatePrimitive(PrimitiveType.Quad);
|
||||
planetDecal.name = "PlanetDecal";
|
||||
planetDecal.transform.parent = animRoot.transform;
|
||||
planetDecal.transform.localPosition = new Vector3(0, 0.053f, 0);
|
||||
planetDecal.transform.localEulerAngles = new Vector3(90, 0, 0);
|
||||
planetDecal.transform.localScale = new Vector3(0.4f, 0.4f, 0.4f);
|
||||
planetDecal.AddComponent<OWRenderer>();
|
||||
planetDecal.GetComponent<MeshRenderer>().sharedMaterial = _decalMaterialGold;
|
||||
_shareStonePrefab = stone;
|
||||
}
|
||||
|
||||
public static void Make(GameObject go, Sector sector, PropModule.RemoteInfo info, IModBehaviour mod)
|
||||
{
|
||||
if (_shareStonePrefab == null) InitPrefabs();
|
||||
|
||||
var id = RemoteHandler.GetPlatformID(info.id);
|
||||
|
||||
var decal = ImageUtilities.GetTexture(mod, info.decalPath, false, false);
|
||||
|
||||
if (info.platform != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoteBuilder.MakePlatform(go, sector, id, decal, info.platform, mod);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Couldn't make remote platform [{info.id}] for [{go.name}]:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
if (info.whiteboard != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoteBuilder.MakeWhiteboard(go, sector, id, decal, info.whiteboard, mod);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Couldn't make remote whiteboard [{info.id}] for [{go.name}]:\n{ex}");
|
||||
}
|
||||
}
|
||||
|
||||
if (info.stones != null)
|
||||
{
|
||||
foreach (var stoneInfo in info.stones)
|
||||
{
|
||||
try
|
||||
{
|
||||
RemoteBuilder.MakeStone(go, sector, id, decal, stoneInfo, mod);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.LogError($"Couldn't make remote stone [{info.id}] for [{go.name}]:\n{ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void MakeWhiteboard(GameObject go, Sector sector, NomaiRemoteCameraPlatform.ID id, Texture2D decal, PropModule.RemoteInfo.WhiteboardInfo info, IModBehaviour mod)
|
||||
{
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = info.position,
|
||||
rotation = info.rotation
|
||||
};
|
||||
var whiteboard = DetailBuilder.MakeDetail(go, sector, _whiteboardPrefab, detailInfo);
|
||||
whiteboard.SetActive(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(info.rename))
|
||||
{
|
||||
whiteboard.name = info.rename;
|
||||
}
|
||||
|
||||
whiteboard.transform.parent = sector?.transform ?? go.transform;
|
||||
|
||||
if (!string.IsNullOrEmpty(info.parentPath))
|
||||
{
|
||||
var newParent = go.transform.Find(info.parentPath);
|
||||
if (newParent != null)
|
||||
{
|
||||
whiteboard.transform.parent = newParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning($"Cannot find parent object at path: {go.name}/{info.parentPath}");
|
||||
}
|
||||
}
|
||||
|
||||
var decalMat = new Material(_decalMaterial);
|
||||
decalMat.SetTexture("_MainTex", decal);
|
||||
decalMat.SetTexture("_EmissionMap", decal);
|
||||
whiteboard.FindChild("PedestalAnchor/Prefab_NOM_SharedPedestal/SharedPedestal_side01_bottom_jnt/SharedPedestal_side01_top_jnt/AstroBodySymbolRenderer").GetComponent<OWRenderer>().sharedMaterial = decalMat;
|
||||
|
||||
var component = whiteboard.GetComponent<NomaiSharedWhiteboard>();
|
||||
component._id = id;
|
||||
|
||||
component._remoteIDs = new NomaiRemoteCameraPlatform.ID[info.nomaiText.Length];
|
||||
component._nomaiTexts = new NomaiWallText[info.nomaiText.Length];
|
||||
for (int i = 0; i < info.nomaiText.Length; i++)
|
||||
{
|
||||
var textInfo = info.nomaiText[i];
|
||||
component._remoteIDs[i] = RemoteHandler.GetPlatformID(textInfo.id);
|
||||
var wallText = NomaiTextBuilder.Make(whiteboard, sector, new PropModule.NomaiTextInfo
|
||||
{
|
||||
arcInfo = textInfo.arcInfo,
|
||||
location = textInfo.location,
|
||||
parentPath = "ArcSocket",
|
||||
position = new MVector3(0, 1, 0),
|
||||
rename = textInfo.rename,
|
||||
rotation = Vector3.zero,
|
||||
seed = textInfo.seed,
|
||||
type = PropModule.NomaiTextInfo.NomaiTextType.Wall,
|
||||
xmlFile = textInfo.xmlFile
|
||||
}, mod).GetComponent<NomaiWallText>();
|
||||
wallText._showTextOnStart = false;
|
||||
component._nomaiTexts[i] = wallText;
|
||||
}
|
||||
|
||||
whiteboard.SetActive(true);
|
||||
}
|
||||
|
||||
public static void MakePlatform(GameObject go, Sector sector, NomaiRemoteCameraPlatform.ID id, Texture2D decal, PropModule.RemoteInfo.PlatformInfo info, IModBehaviour mod)
|
||||
{
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = info.position,
|
||||
rotation = info.rotation
|
||||
};
|
||||
var platform = DetailBuilder.MakeDetail(go, sector, _remoteCameraPlatformPrefab, detailInfo);
|
||||
platform.SetActive(false);
|
||||
|
||||
if (!string.IsNullOrEmpty(info.rename))
|
||||
{
|
||||
platform.name = info.rename;
|
||||
}
|
||||
|
||||
platform.transform.parent = sector?.transform ?? go.transform;
|
||||
|
||||
if (!string.IsNullOrEmpty(info.parentPath))
|
||||
{
|
||||
var newParent = go.transform.Find(info.parentPath);
|
||||
if (newParent != null)
|
||||
{
|
||||
platform.transform.parent = newParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning($"Cannot find parent object at path: {go.name}/{info.parentPath}");
|
||||
}
|
||||
}
|
||||
|
||||
var decalMat = new Material(_decalMaterial);
|
||||
decalMat.SetTexture("_MainTex", decal);
|
||||
decalMat.SetTexture("_EmissionMap", decal);
|
||||
platform.FindChild("PedestalAnchor/Prefab_NOM_SharedPedestal/SharedPedestal_side01_bottom_jnt/SharedPedestal_side01_top_jnt/AstroBodySymbolRenderer").GetComponent<OWRenderer>().sharedMaterial = decalMat;
|
||||
|
||||
var component = platform.GetComponent<NomaiRemoteCameraPlatform>();
|
||||
component._id = id;
|
||||
component._visualSector = sector;
|
||||
component._dataPointID = info.reveals;
|
||||
|
||||
platform.SetActive(true);
|
||||
}
|
||||
|
||||
public static void MakeStone(GameObject go, Sector sector, NomaiRemoteCameraPlatform.ID id, Texture2D decal, PropModule.RemoteInfo.StoneInfo info, IModBehaviour mod)
|
||||
{
|
||||
var shareStone = _shareStonePrefab.InstantiateInactive();
|
||||
|
||||
if (!string.IsNullOrEmpty(info.rename))
|
||||
{
|
||||
shareStone.name = info.rename;
|
||||
}
|
||||
else
|
||||
{
|
||||
shareStone.name = "ShareStone_" + id.ToString();
|
||||
}
|
||||
|
||||
shareStone.transform.parent = sector?.transform ?? go.transform;
|
||||
|
||||
if (!string.IsNullOrEmpty(info.parentPath))
|
||||
{
|
||||
var newParent = go.transform.Find(info.parentPath);
|
||||
if (newParent != null)
|
||||
{
|
||||
shareStone.transform.parent = newParent;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogWarning($"Cannot find parent object at path: {go.name}/{info.parentPath}");
|
||||
}
|
||||
}
|
||||
|
||||
shareStone.transform.position = go.transform.TransformPoint((Vector3)(info.position ?? Vector3.zero));
|
||||
shareStone.transform.rotation = go.transform.TransformRotation(Quaternion.Euler((Vector3)(info.rotation ?? Vector3.zero)));
|
||||
|
||||
shareStone.GetComponent<SharedStone>()._connectedPlatform = id;
|
||||
|
||||
var decalMat = new Material(_decalMaterialGold);
|
||||
decalMat.SetTexture("_MainTex", decal);
|
||||
decalMat.SetTexture("_EmissionMap", decal);
|
||||
shareStone.FindChild("AnimRoot/PlanetDecal").GetComponent<OWRenderer>().sharedMaterial = decalMat;
|
||||
|
||||
shareStone.SetActive(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -92,7 +92,14 @@ namespace NewHorizons.Builder.Props
|
||||
point = Quaternion.Euler(90, 0, 0) * point;
|
||||
}
|
||||
|
||||
var prop = DetailBuilder.MakeDetail(go, sector, prefab, (MVector3)(point.normalized * height), null, propInfo.scale, true);
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = point.normalized * height,
|
||||
scale = propInfo.scale,
|
||||
alignToNormal = true
|
||||
};
|
||||
var prop = DetailBuilder.MakeDetail(go, sector, prefab, detailInfo);
|
||||
|
||||
if (propInfo.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset);
|
||||
if (propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation);
|
||||
|
||||
|
||||
2
NewHorizons/External/Configs/PlanetConfig.cs
vendored
2
NewHorizons/External/Configs/PlanetConfig.cs
vendored
@ -151,7 +151,7 @@ namespace NewHorizons.External.Configs
|
||||
public StarModule Star;
|
||||
|
||||
/// <summary>
|
||||
/// Unique star system containing your planet
|
||||
/// Unique star system containing your planet. If you set this to be a custom solar system remember to add a Spawn module to one of the bodies, or else you can't get to the system.
|
||||
/// </summary>
|
||||
[DefaultValue("SolarSystem")] public string starSystem = "SolarSystem";
|
||||
|
||||
|
||||
188
NewHorizons/External/Modules/PropModule.cs
vendored
188
NewHorizons/External/Modules/PropModule.cs
vendored
@ -62,7 +62,7 @@ namespace NewHorizons.External.Modules
|
||||
/// Add slideshows (from the DLC) to the planet
|
||||
/// </summary>
|
||||
public ProjectionInfo[] slideShows;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A list of quantum groups that props can be added to. An example of a group would be a list of possible locations for a QuantumSocketedObject.
|
||||
/// </summary>
|
||||
@ -93,6 +93,11 @@ namespace NewHorizons.External.Modules
|
||||
/// </summary>
|
||||
public SignalModule.SignalInfo[] signals;
|
||||
|
||||
/// <summary>
|
||||
/// Add projection pools/platforms, whiteboards, and stones to this planet
|
||||
/// </summary>
|
||||
public RemoteInfo[] remotes;
|
||||
|
||||
[JsonObject]
|
||||
public class ScatterInfo
|
||||
{
|
||||
@ -200,6 +205,11 @@ namespace NewHorizons.External.Modules
|
||||
/// 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;
|
||||
|
||||
/// <summary>
|
||||
/// Should this detail stay loaded even if you're outside the sector (good for very large props)
|
||||
/// </summary>
|
||||
public bool keepLoaded;
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
@ -552,7 +562,6 @@ namespace NewHorizons.External.Modules
|
||||
/// An optional rename of this object
|
||||
/// </summary>
|
||||
public string rename;
|
||||
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
@ -601,7 +610,7 @@ namespace NewHorizons.External.Modules
|
||||
public enum SlideShowType
|
||||
{
|
||||
[EnumMember(Value = @"slideReel")] SlideReel = 0,
|
||||
|
||||
|
||||
[EnumMember(Value = @"autoProjector")] AutoProjector = 1,
|
||||
|
||||
[EnumMember(Value = @"visionTorchTarget")] VisionTorchTarget = 2,
|
||||
@ -722,8 +731,8 @@ namespace NewHorizons.External.Modules
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum QuantumGroupType
|
||||
{
|
||||
@ -733,24 +742,24 @@ namespace NewHorizons.External.Modules
|
||||
|
||||
FailedValidation = 10
|
||||
}
|
||||
|
||||
|
||||
[JsonObject]
|
||||
public class QuantumGroupInfo
|
||||
{
|
||||
public class QuantumGroupInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// What type of group this is: does it define a list of states a single quantum object could take or a list of sockets one or more quantum objects could share?
|
||||
/// </summary>
|
||||
public QuantumGroupType type;
|
||||
public QuantumGroupType type;
|
||||
|
||||
/// <summary>
|
||||
/// A unique string used by props (that are marked as quantum) use to refer back to this group
|
||||
/// </summary>
|
||||
public string id;
|
||||
public string id;
|
||||
|
||||
/// <summary>
|
||||
/// Only required if type is `sockets`. This lists all the possible locations for any props assigned to this group.
|
||||
/// </summary>
|
||||
public QuantumSocketInfo[] sockets;
|
||||
public QuantumSocketInfo[] sockets;
|
||||
|
||||
/// <summary>
|
||||
/// Optional. Only used if type is `states`. If this is true, then the first prop made part of this group will be used to construct a visibility box for an empty game object, which will be considered one of the states.
|
||||
@ -767,24 +776,24 @@ namespace NewHorizons.External.Modules
|
||||
/// </summary>
|
||||
[DefaultValue(true)] public bool loop = true;
|
||||
}
|
||||
|
||||
|
||||
[JsonObject]
|
||||
public class QuantumSocketInfo
|
||||
{
|
||||
public class QuantumSocketInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of this socket
|
||||
/// </summary>
|
||||
public MVector3 position;
|
||||
public MVector3 position;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation the quantum object will take if it's occupying this socket
|
||||
/// </summary>
|
||||
public MVector3 rotation;
|
||||
public MVector3 rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The probability any props that are part of this group will occupy this socket
|
||||
/// </summary>
|
||||
[DefaultValue(1f)] public float probability = 1f;
|
||||
[DefaultValue(1f)] public float probability = 1f;
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
@ -810,6 +819,151 @@ namespace NewHorizons.External.Modules
|
||||
/// </summary>
|
||||
[DefaultValue("environment")] public AudioMixerTrackName track = AudioMixerTrackName.Environment;
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class RemoteInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The unique remote id
|
||||
/// </summary>
|
||||
public string id;
|
||||
|
||||
/// <summary>
|
||||
/// Icon that the will show on the stone, pedastal of the whiteboard, and pedastal of the platform.
|
||||
/// </summary>
|
||||
public string decalPath;
|
||||
|
||||
/// <summary>
|
||||
/// Whiteboard that the stones can put text onto
|
||||
/// </summary>
|
||||
public WhiteboardInfo whiteboard;
|
||||
|
||||
/// <summary>
|
||||
/// Camera platform that the stones can project to and from
|
||||
/// </summary>
|
||||
public PlatformInfo platform;
|
||||
|
||||
/// <summary>
|
||||
/// Projection stones
|
||||
/// </summary>
|
||||
public StoneInfo[] stones;
|
||||
|
||||
[JsonObject]
|
||||
public class WhiteboardInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The text for each stone
|
||||
/// </summary>
|
||||
public SharedNomaiTextInfo[] nomaiText;
|
||||
|
||||
/// <summary>
|
||||
/// The location of this platform.
|
||||
/// </summary>
|
||||
public MVector3 position;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of this platform.
|
||||
/// </summary>
|
||||
public MVector3 rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The relative path from the planet to the parent of this object. Optional (will default to the root sector).
|
||||
/// </summary>
|
||||
public string parentPath;
|
||||
|
||||
/// <summary>
|
||||
/// An optional rename of this object
|
||||
/// </summary>
|
||||
public string rename;
|
||||
|
||||
[JsonObject]
|
||||
public class SharedNomaiTextInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The id of the stone this text will appear for
|
||||
/// </summary>
|
||||
public string id;
|
||||
|
||||
/// <summary>
|
||||
/// Additional information about each arc in the text
|
||||
/// </summary>
|
||||
public NomaiTextArcInfo[] arcInfo;
|
||||
|
||||
/// <summary>
|
||||
/// The random seed used to pick what the text arcs will look like.
|
||||
/// </summary>
|
||||
public int seed; // For randomizing arcs
|
||||
|
||||
/// <summary>
|
||||
/// The location of this object.
|
||||
/// </summary>
|
||||
[DefaultValue("unspecified")] public NomaiTextInfo.NomaiTextLocation location = NomaiTextInfo.NomaiTextLocation.UNSPECIFIED;
|
||||
|
||||
/// <summary>
|
||||
/// The relative path to the xml file for this object.
|
||||
/// </summary>
|
||||
public string xmlFile;
|
||||
|
||||
/// <summary>
|
||||
/// An optional rename of this object
|
||||
/// </summary>
|
||||
public string rename;
|
||||
}
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class PlatformInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of this platform.
|
||||
/// </summary>
|
||||
public MVector3 position;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of this platform.
|
||||
/// </summary>
|
||||
public MVector3 rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The relative path from the planet to the parent of this object. Optional (will default to the root sector).
|
||||
/// </summary>
|
||||
public string parentPath;
|
||||
|
||||
/// <summary>
|
||||
/// An optional rename of this object
|
||||
/// </summary>
|
||||
public string rename;
|
||||
|
||||
/// <summary>
|
||||
/// A ship log fact to reveal when the platform is connected to.
|
||||
/// </summary>
|
||||
[DefaultValue("")] public string reveals = "";
|
||||
}
|
||||
|
||||
[JsonObject]
|
||||
public class StoneInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// The location of this stone.
|
||||
/// </summary>
|
||||
public MVector3 position;
|
||||
|
||||
/// <summary>
|
||||
/// The rotation of this stone.
|
||||
/// </summary>
|
||||
public MVector3 rotation;
|
||||
|
||||
/// <summary>
|
||||
/// The relative path from the planet to the parent of this object. Optional (will default to the root sector).
|
||||
/// </summary>
|
||||
public string parentPath;
|
||||
|
||||
/// <summary>
|
||||
/// An optional rename of this object
|
||||
/// </summary>
|
||||
public string rename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
|
||||
@ -30,9 +30,10 @@ namespace NewHorizons.Handlers
|
||||
Logger.LogVerbose($"Adding all custom AudioTypes to the library");
|
||||
|
||||
var library = Locator.GetAudioManager()._libraryAsset;
|
||||
library.audioEntries = library.audioEntries.Concat(_audioEntries).ToArray();
|
||||
|
||||
var audioEntries = library.audioEntries; // store previous array
|
||||
library.audioEntries = library.audioEntries.Concat(_audioEntries).ToArray(); // concat custom entries
|
||||
Locator.GetAudioManager()._audioLibraryDict = library.BuildAudioEntryDictionary();
|
||||
library.audioEntries = audioEntries; // reset it back for next time we build
|
||||
}
|
||||
|
||||
// Will return an existing audio type or create a new one for the given audio string
|
||||
|
||||
71
NewHorizons/Handlers/RemoteHandler.cs
Normal file
71
NewHorizons/Handlers/RemoteHandler.cs
Normal file
@ -0,0 +1,71 @@
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.Handlers
|
||||
{
|
||||
public static class RemoteHandler
|
||||
{
|
||||
private static Dictionary<string, NomaiRemoteCameraPlatform.ID> _customPlatformIDs;
|
||||
private static readonly int _startingInt = 19;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_customPlatformIDs = new Dictionary<string, NomaiRemoteCameraPlatform.ID>();
|
||||
}
|
||||
|
||||
public static string GetPlatformIDName(NomaiRemoteCameraPlatform.ID id)
|
||||
{
|
||||
foreach (var pair in _customPlatformIDs)
|
||||
{
|
||||
if (pair.Value == id) return TranslationHandler.GetTranslation(pair.Key, TranslationHandler.TextType.UI);
|
||||
}
|
||||
return id.ToString();
|
||||
}
|
||||
|
||||
public static string GetPlatformIDKey(NomaiRemoteCameraPlatform.ID id)
|
||||
{
|
||||
foreach (var pair in _customPlatformIDs)
|
||||
{
|
||||
if (pair.Value == id) return pair.Key;
|
||||
}
|
||||
return id.ToString();
|
||||
}
|
||||
|
||||
public static NomaiRemoteCameraPlatform.ID GetPlatformID(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
NomaiRemoteCameraPlatform.ID platformID;
|
||||
if (_customPlatformIDs.TryGetValue(id, out platformID) || Enum.TryParse(id, true, out platformID))
|
||||
{
|
||||
return platformID;
|
||||
}
|
||||
else
|
||||
{
|
||||
return AddCustomPlatformID(id);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Couldn't load platform id:\n{e}");
|
||||
return NomaiRemoteCameraPlatform.ID.None;
|
||||
}
|
||||
}
|
||||
|
||||
public static NomaiRemoteCameraPlatform.ID AddCustomPlatformID(string id)
|
||||
{
|
||||
var platformID = (NomaiRemoteCameraPlatform.ID)_startingInt + _customPlatformIDs.Count();
|
||||
|
||||
Logger.LogVerbose($"Registering custom platform id {id} as {platformID}");
|
||||
|
||||
_customPlatformIDs.Add(id, platformID);
|
||||
|
||||
return platformID;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
@ -11,11 +11,13 @@ namespace NewHorizons.Handlers
|
||||
{
|
||||
private static readonly Dictionary<Material, string> _materialCache = new();
|
||||
private static readonly Dictionary<GameObject, string[]> _objectCache = new();
|
||||
private static readonly Dictionary<string, List<Sector>> _sectorCache = new();
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_materialCache.Clear();
|
||||
_objectCache.Clear();
|
||||
_sectorCache.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -70,18 +72,44 @@ namespace NewHorizons.Handlers
|
||||
foreach (var assetBundle in assetBundles)
|
||||
{
|
||||
StreamingManager.LoadStreamingAssets(assetBundle);
|
||||
|
||||
// Track the sector even if its null. null means stay loaded forever
|
||||
if (!_sectorCache.TryGetValue(assetBundle, out var sectors))
|
||||
{
|
||||
sectors = new List<Sector>();
|
||||
_sectorCache.Add(assetBundle, sectors);
|
||||
}
|
||||
sectors.SafeAdd(sector);
|
||||
}
|
||||
|
||||
if (sector)
|
||||
{
|
||||
sector.OnOccupantEnterSector += _ =>
|
||||
{
|
||||
foreach (var assetBundle in assetBundles)
|
||||
{
|
||||
StreamingManager.LoadStreamingAssets(assetBundle);
|
||||
}
|
||||
if (sector.ContainsAnyOccupants(DynamicOccupant.Player | DynamicOccupant.Probe))
|
||||
foreach (var assetBundle in assetBundles)
|
||||
StreamingManager.LoadStreamingAssets(assetBundle);
|
||||
};
|
||||
/*
|
||||
sector.OnOccupantExitSector += _ =>
|
||||
{
|
||||
// UnloadStreamingAssets is patched to check IsBundleInUse first before unloading
|
||||
if (!sector.ContainsAnyOccupants(DynamicOccupant.Player | DynamicOccupant.Probe))
|
||||
foreach (var assetBundle in assetBundles)
|
||||
StreamingManager.UnloadStreamingAssets(assetBundle);
|
||||
};
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsBundleInUse(string assetBundle)
|
||||
{
|
||||
if (_sectorCache.TryGetValue(assetBundle, out var sectors))
|
||||
foreach (var sector in sectors)
|
||||
// If a sector in the list is null then it is always in use
|
||||
if (sector == null || sector.ContainsAnyOccupants(DynamicOccupant.Player | DynamicOccupant.Probe))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -296,6 +296,7 @@ namespace NewHorizons
|
||||
AstroObjectLocator.Init();
|
||||
StreamingHandler.Init();
|
||||
AudioTypeHandler.Init();
|
||||
RemoteHandler.Init();
|
||||
AtmosphereBuilder.Init();
|
||||
BrambleNodeBuilder.Init(BodyDict[CurrentStarSystem].Select(x => x.Config).Where(x => x.Bramble?.dimension != null).ToArray());
|
||||
|
||||
@ -329,6 +330,46 @@ namespace NewHorizons
|
||||
if (map != null) map._maxPanDistance = FurthestOrbit * 1.5f;
|
||||
// Fix the map satellite
|
||||
SearchUtilities.Find("HearthianMapSatellite_Body", false).AddComponent<MapSatelliteOrbitFix>();
|
||||
|
||||
|
||||
// Sector changes (so that projection pools actually turn off proxies and cull groups on these moons)
|
||||
|
||||
//Fix attlerock vanilla sector components (they were set to timber hearth's sector)
|
||||
var thm = SearchUtilities.Find("Moon_Body/Sector_THM").GetComponent<Sector>();
|
||||
thm._parentSector = SearchUtilities.Find("TimberHearth_Body/Sector_TH").GetComponent<Sector>();
|
||||
foreach (var component in thm.GetComponentsInChildren<Component>(true))
|
||||
{
|
||||
if (component is ISectorGroup sectorGroup)
|
||||
{
|
||||
sectorGroup.SetSector(thm);
|
||||
}
|
||||
|
||||
if (component is SectoredMonoBehaviour behaviour)
|
||||
{
|
||||
behaviour.SetSector(thm);
|
||||
}
|
||||
}
|
||||
|
||||
//Fix hollow's lantern vanilla sector components (they were set to brittle hollow's sector)
|
||||
var vm = SearchUtilities.Find("VolcanicMoon_Body/Sector_VM").GetComponent<Sector>();
|
||||
vm._parentSector = SearchUtilities.Find("BrittleHollow_Body/Sector_BH").GetComponent<Sector>();
|
||||
foreach (var component in vm.GetComponentsInChildren<Component>(true))
|
||||
{
|
||||
if (component is ISectorGroup sectorGroup)
|
||||
{
|
||||
sectorGroup.SetSector(vm);
|
||||
}
|
||||
|
||||
if (component is SectoredMonoBehaviour behaviour)
|
||||
{
|
||||
behaviour.SetSector(vm);
|
||||
}
|
||||
}
|
||||
|
||||
//Fix brittle hollow north pole projection platform
|
||||
var northPoleSurface = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_NorthPoleSurface").GetComponent<Sector>();
|
||||
var remoteViewer = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_NorthPoleSurface/Interactables_NorthPoleSurface/LowBuilding/Prefab_NOM_RemoteViewer").GetComponent<NomaiRemoteCameraPlatform>();
|
||||
remoteViewer._visualSector = northPoleSurface;
|
||||
}
|
||||
|
||||
try
|
||||
|
||||
@ -111,7 +111,14 @@ namespace NewHorizons
|
||||
public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles,
|
||||
float scale, bool alignWithNormal)
|
||||
{
|
||||
return DetailBuilder.MakeDetail(planet, sector, propToCopyPath, position, eulerAngles, scale, alignWithNormal);
|
||||
var prefab = SearchUtilities.Find(propToCopyPath);
|
||||
var detailInfo = new PropModule.DetailInfo() {
|
||||
position = position,
|
||||
rotation = eulerAngles,
|
||||
scale = scale,
|
||||
alignToNormal = alignWithNormal
|
||||
};
|
||||
return DetailBuilder.MakeDetail(planet, sector, prefab, detailInfo);
|
||||
}
|
||||
|
||||
public AudioSignal SpawnSignal(IModBehaviour mod, GameObject root, string audio, string name, string frequency,
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
using HarmonyLib;
|
||||
using NewHorizons.Builder.Props;
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Handlers;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Patches
|
||||
{
|
||||
[HarmonyPatch]
|
||||
|
||||
@ -4,7 +4,7 @@ using UnityEngine;
|
||||
namespace NewHorizons.Patches
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public class RaftPatches : HarmonyPatch
|
||||
public static class RaftPatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(RaftController), nameof(RaftController.FixedUpdate))]
|
||||
|
||||
152
NewHorizons/Patches/RemotePatches.cs
Normal file
152
NewHorizons/Patches/RemotePatches.cs
Normal file
@ -0,0 +1,152 @@
|
||||
using HarmonyLib;
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.Handlers;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Patches
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public class RemotePatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(NomaiRemoteCameraPlatform), nameof(NomaiRemoteCameraPlatform.IDToPlanetString))]
|
||||
public static bool NomaiRemoteCameraPlatform_IDToPlanetString(NomaiRemoteCameraPlatform.ID id, out string __result)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case NomaiRemoteCameraPlatform.ID.None:
|
||||
__result = "None";
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.SunStation:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationSS);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.HGT_TimeLoop:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationTT);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.TH_Mine:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationTH);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.THM_EyeLocator:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationTHMoon);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.BH_Observatory:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_GravityCannon:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_QuantumFragment:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_BlackHoleForge:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_NorthPole:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationBH);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland1:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland2:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_StatueIsland:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationGD);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonSunkenModule:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationOPC_Module3);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonDamagedModule:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationOPC_Module2);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonIntactModule:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationOPC_Module1);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.VM_Interior:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationBHMoon);
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.HGT_TLE:
|
||||
__result = UITextLibrary.GetString(UITextType.LocationCT);
|
||||
break;
|
||||
default:
|
||||
__result = RemoteHandler.GetPlatformIDName(id);
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(NomaiRemoteCameraStreaming), nameof(NomaiRemoteCameraStreaming.NomaiRemoteCameraPlatformIDToSceneName))]
|
||||
public static bool NomaiRemoteCameraStreaming_NomaiRemoteCameraPlatformIDToSceneName(NomaiRemoteCameraPlatform.ID id, out string __result)
|
||||
{
|
||||
switch (id)
|
||||
{
|
||||
case NomaiRemoteCameraPlatform.ID.SunStation:
|
||||
__result = "SolarSystem";
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.HGT_TimeLoop:
|
||||
case NomaiRemoteCameraPlatform.ID.HGT_TLE:
|
||||
__result = "HourglassTwins";
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.TH_Mine:
|
||||
case NomaiRemoteCameraPlatform.ID.THM_EyeLocator:
|
||||
__result = "TimberHearth";
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.BH_Observatory:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_GravityCannon:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_QuantumFragment:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_BlackHoleForge:
|
||||
case NomaiRemoteCameraPlatform.ID.BH_NorthPole:
|
||||
case NomaiRemoteCameraPlatform.ID.VM_Interior:
|
||||
__result = "BrittleHollow";
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland1:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ConstructionYardIsland2:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_StatueIsland:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonSunkenModule:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonDamagedModule:
|
||||
case NomaiRemoteCameraPlatform.ID.GD_ProbeCannonIntactModule:
|
||||
__result = "GiantsDeep";
|
||||
break;
|
||||
case NomaiRemoteCameraPlatform.ID.None:
|
||||
__result = "";
|
||||
break;
|
||||
default:
|
||||
var key = RemoteHandler.GetPlatformIDKey(id);
|
||||
switch (key.Substring(0, key.IndexOf("_")))
|
||||
{
|
||||
case "SS":
|
||||
__result = "SolarSystem";
|
||||
break;
|
||||
case "HGT":
|
||||
case "CT":
|
||||
case "TT":
|
||||
__result = "HourglassTwins";
|
||||
break;
|
||||
case "CO":
|
||||
__result = "Comet";
|
||||
break;
|
||||
case "QM":
|
||||
__result = "QuantumMoon";
|
||||
break;
|
||||
case "GD":
|
||||
__result = "GiantsDeep";
|
||||
break;
|
||||
case "BH":
|
||||
case "VM":
|
||||
__result = "BrittleHollow";
|
||||
break;
|
||||
case "TH":
|
||||
case "THM":
|
||||
__result = "TimberHearth";
|
||||
break;
|
||||
case "DB":
|
||||
__result = "DarkBramble";
|
||||
break;
|
||||
case "WH":
|
||||
__result = "WhiteHole";
|
||||
break;
|
||||
case "RW":
|
||||
__result = "RingWorld";
|
||||
break;
|
||||
case "DW":
|
||||
__result = "DreamWorld";
|
||||
break;
|
||||
default:
|
||||
__result = key;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
NewHorizons/Patches/StreamingManagerPatches.cs
Normal file
17
NewHorizons/Patches/StreamingManagerPatches.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using HarmonyLib;
|
||||
using NewHorizons.Handlers;
|
||||
|
||||
namespace NewHorizons.Patches
|
||||
{
|
||||
[HarmonyPatch]
|
||||
public static class StreamingManagerPatches
|
||||
{
|
||||
[HarmonyPrefix]
|
||||
[HarmonyPatch(typeof(StreamingManager), nameof(StreamingManager.UnloadStreamingAssets))]
|
||||
public static bool StreamingManager_UnloadStreamingAssets(string assetBundleName)
|
||||
{
|
||||
// Only let it unload stuff that isn't being used
|
||||
return !StreamingHandler.IsBundleInUse(assetBundleName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -112,7 +112,7 @@
|
||||
},
|
||||
"starSystem": {
|
||||
"type": "string",
|
||||
"description": "Unique star system containing your planet",
|
||||
"description": "Unique star system containing your planet. If you set this to be a custom solar system remember to add a Spawn module to one of the bodies, or else you can't get to the system.",
|
||||
"default": "SolarSystem"
|
||||
},
|
||||
"version": {
|
||||
@ -970,6 +970,13 @@
|
||||
"items": {
|
||||
"$ref": "#/definitions/SignalInfo"
|
||||
}
|
||||
},
|
||||
"remotes": {
|
||||
"type": "array",
|
||||
"description": "Add projection pools/platforms, whiteboards, and stones to this planet",
|
||||
"items": {
|
||||
"$ref": "#/definitions/RemoteInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1025,6 +1032,10 @@
|
||||
"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)."
|
||||
},
|
||||
"keepLoaded": {
|
||||
"type": "boolean",
|
||||
"description": "Should this detail stay loaded even if you're outside the sector (good for very large props)"
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -1871,6 +1882,148 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"RemoteInfo": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "The unique remote id"
|
||||
},
|
||||
"decalPath": {
|
||||
"type": "string",
|
||||
"description": "Icon that the will show on the stone, pedastal of the whiteboard, and pedastal of the platform."
|
||||
},
|
||||
"whiteboard": {
|
||||
"description": "Whiteboard that the stones can put text onto",
|
||||
"$ref": "#/definitions/WhiteboardInfo"
|
||||
},
|
||||
"platform": {
|
||||
"description": "Camera platform that the stones can project to and from",
|
||||
"$ref": "#/definitions/PlatformInfo"
|
||||
},
|
||||
"stones": {
|
||||
"type": "array",
|
||||
"description": "Projection stones",
|
||||
"items": {
|
||||
"$ref": "#/definitions/StoneInfo"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"WhiteboardInfo": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"nomaiText": {
|
||||
"type": "array",
|
||||
"description": "The text for each stone",
|
||||
"items": {
|
||||
"$ref": "#/definitions/SharedNomaiTextInfo"
|
||||
}
|
||||
},
|
||||
"position": {
|
||||
"description": "The location of this platform.",
|
||||
"$ref": "#/definitions/MVector3"
|
||||
},
|
||||
"rotation": {
|
||||
"description": "The rotation of this platform.",
|
||||
"$ref": "#/definitions/MVector3"
|
||||
},
|
||||
"parentPath": {
|
||||
"type": "string",
|
||||
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||
},
|
||||
"rename": {
|
||||
"type": "string",
|
||||
"description": "An optional rename of this object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"SharedNomaiTextInfo": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string",
|
||||
"description": "The id of the stone this text will appear for"
|
||||
},
|
||||
"arcInfo": {
|
||||
"type": "array",
|
||||
"description": "Additional information about each arc in the text",
|
||||
"items": {
|
||||
"$ref": "#/definitions/NomaiTextArcInfo"
|
||||
}
|
||||
},
|
||||
"seed": {
|
||||
"type": "integer",
|
||||
"description": "The random seed used to pick what the text arcs will look like.",
|
||||
"format": "int32"
|
||||
},
|
||||
"location": {
|
||||
"description": "The location of this object. ",
|
||||
"default": "unspecified",
|
||||
"$ref": "#/definitions/NomaiTextLocation"
|
||||
},
|
||||
"xmlFile": {
|
||||
"type": "string",
|
||||
"description": "The relative path to the xml file for this object."
|
||||
},
|
||||
"rename": {
|
||||
"type": "string",
|
||||
"description": "An optional rename of this object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"PlatformInfo": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"position": {
|
||||
"description": "The location of this platform.",
|
||||
"$ref": "#/definitions/MVector3"
|
||||
},
|
||||
"rotation": {
|
||||
"description": "The rotation of this platform.",
|
||||
"$ref": "#/definitions/MVector3"
|
||||
},
|
||||
"parentPath": {
|
||||
"type": "string",
|
||||
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||
},
|
||||
"rename": {
|
||||
"type": "string",
|
||||
"description": "An optional rename of this object"
|
||||
},
|
||||
"reveals": {
|
||||
"type": "string",
|
||||
"description": "A ship log fact to reveal when the platform is connected to.",
|
||||
"default": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"StoneInfo": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"position": {
|
||||
"description": "The location of this stone.",
|
||||
"$ref": "#/definitions/MVector3"
|
||||
},
|
||||
"rotation": {
|
||||
"description": "The rotation of this stone.",
|
||||
"$ref": "#/definitions/MVector3"
|
||||
},
|
||||
"parentPath": {
|
||||
"type": "string",
|
||||
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||
},
|
||||
"rename": {
|
||||
"type": "string",
|
||||
"description": "An optional rename of this object"
|
||||
}
|
||||
}
|
||||
},
|
||||
"ReferenceFrameModule": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
@ -13,6 +13,8 @@ namespace NewHorizons.Utility
|
||||
|
||||
public static void SetAudioClip(OWAudioSource source, string audio, IModBehaviour mod)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(audio)) return;
|
||||
|
||||
if (audio.Contains(".wav") || audio.Contains(".ogg") || audio.Contains(".mp3"))
|
||||
{
|
||||
try
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
using NewHorizons.Builder.Props;
|
||||
using NewHorizons.External.Configs;
|
||||
using System;
|
||||
using NewHorizons.External.Modules;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
using static NewHorizons.External.Modules.PropModule;
|
||||
|
||||
namespace NewHorizons.Utility.DebugUtilities
|
||||
{
|
||||
@ -24,7 +21,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
public AstroObject body;
|
||||
public string system;
|
||||
public GameObject gameObject;
|
||||
public DetailInfo detailInfo;
|
||||
public PropModule.DetailInfo detailInfo;
|
||||
}
|
||||
|
||||
// VASE
|
||||
@ -108,8 +105,16 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
SetCurrentObject(DEFAULT_OBJECT);
|
||||
}
|
||||
|
||||
GameObject prop = DetailBuilder.MakeDetail(data.hitBodyGameObject, data.hitBodyGameObject.GetComponentInChildren<Sector>(), currentObject, data.pos, data.norm, 1, false);
|
||||
PropPlacementData propData = RegisterProp_WithReturn(data.hitBodyGameObject.GetComponent<AstroObject>(), prop);
|
||||
var planetGO = data.hitBodyGameObject;
|
||||
var sector = planetGO.GetComponentInChildren<Sector>();
|
||||
var prefab = SearchUtilities.Find(currentObject);
|
||||
var detailInfo = new PropModule.DetailInfo()
|
||||
{
|
||||
position = data.pos,
|
||||
rotation = data.norm,
|
||||
};
|
||||
var prop = DetailBuilder.MakeDetail(planetGO, sector, prefab, detailInfo);
|
||||
var propData = RegisterProp_WithReturn(data.hitBodyGameObject.GetComponent<AstroObject>(), prop);
|
||||
|
||||
SetGameObjectRotation(prop, data, playerAbsolutePosition);
|
||||
}
|
||||
@ -156,7 +161,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
{
|
||||
if (config.starSystem != Main.Instance.CurrentStarSystem) return;
|
||||
|
||||
AstroObject planet = AstroObjectLocator.GetAstroObject(config.name);
|
||||
var planet = AstroObjectLocator.GetAstroObject(config.name);
|
||||
|
||||
if (planet == null) return;
|
||||
if (config.Props == null || config.Props.details == null) return;
|
||||
@ -165,7 +170,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
|
||||
foreach (var detail in config.Props.details)
|
||||
{
|
||||
GameObject spawnedProp = DetailBuilder.GetSpawnedGameObjectByDetailInfo(detail);
|
||||
var spawnedProp = DetailBuilder.GetSpawnedGameObjectByDetailInfo(detail);
|
||||
|
||||
if (spawnedProp == null)
|
||||
{
|
||||
@ -173,7 +178,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
continue;
|
||||
}
|
||||
|
||||
PropPlacementData data = RegisterProp_WithReturn(astroObject, spawnedProp, detail.path, detail);
|
||||
var data = RegisterProp_WithReturn(astroObject, spawnedProp, detail.path, detail);
|
||||
|
||||
// note: we do not support placing props from assetbundles, so they will not be added to the
|
||||
// selectable list of placed props
|
||||
@ -189,7 +194,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
RegisterProp_WithReturn(body, prop);
|
||||
}
|
||||
|
||||
private PropPlacementData RegisterProp_WithReturn(AstroObject body, GameObject prop, string propPath = null, DetailInfo detailInfo = null)
|
||||
private PropPlacementData RegisterProp_WithReturn(AstroObject body, GameObject prop, string propPath = null, PropModule.DetailInfo detailInfo = null)
|
||||
{
|
||||
if (Main.Debug)
|
||||
{
|
||||
@ -201,7 +206,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
Logger.LogVerbose($"Adding prop to {Main.Instance.CurrentStarSystem}::{body.name}");
|
||||
|
||||
|
||||
detailInfo = detailInfo == null ? new DetailInfo() : detailInfo;
|
||||
detailInfo = detailInfo == null ? new PropModule.DetailInfo() : detailInfo;
|
||||
detailInfo.path = propPath == null ? currentObject : propPath;
|
||||
|
||||
PropPlacementData data = new PropPlacementData
|
||||
@ -216,14 +221,14 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
return data;
|
||||
}
|
||||
|
||||
public Dictionary<AstroObject, DetailInfo[]> GetPropsConfigByBody()
|
||||
public Dictionary<AstroObject, PropModule.DetailInfo[]> GetPropsConfigByBody()
|
||||
{
|
||||
var groupedProps = props
|
||||
.GroupBy(p => p.system + "." + p.body)
|
||||
.Select(grp => grp.ToList())
|
||||
.ToList();
|
||||
|
||||
Dictionary<AstroObject, DetailInfo[]> propConfigs = new Dictionary<AstroObject, DetailInfo[]>();
|
||||
Dictionary<AstroObject, PropModule.DetailInfo[]> propConfigs = new Dictionary<AstroObject, PropModule.DetailInfo[]>();
|
||||
|
||||
foreach (List<PropPlacementData> bodyProps in groupedProps)
|
||||
{
|
||||
@ -233,7 +238,7 @@ namespace NewHorizons.Utility.DebugUtilities
|
||||
Logger.LogVerbose("getting prop group for body " + body.name);
|
||||
//string bodyName = GetAstroObjectName(bodyProps[0].body);
|
||||
|
||||
DetailInfo[] infoArray = new DetailInfo[bodyProps.Count];
|
||||
PropModule.DetailInfo[] infoArray = new PropModule.DetailInfo[bodyProps.Count];
|
||||
propConfigs[body] = infoArray;
|
||||
|
||||
for (int i = 0; i < bodyProps.Count; i++)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user