Dream arrival point and dream campfire builders

This commit is contained in:
Joshua Thome 2024-10-05 00:54:25 -05:00
parent 2b3b7e277e
commit 1be3bf209f
10 changed files with 321 additions and 0 deletions

View File

@ -0,0 +1,63 @@
using NewHorizons.Components.Props;
using NewHorizons.External.Modules.Props;
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using NewHorizons.Utility.OWML;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Builder.Props.EchoesOfTheEye
{
public static class DreamArrivalPointBuilder
{
private static GameObject _prefab;
internal static void InitPrefab()
{
if (_prefab == null)
{
_prefab = SearchUtilities.Find("DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/DreamFireHouse_1/Interactibles_DreamFireHouse_1/Prefab_IP_DreamArrivalPoint_Zone1").InstantiateInactive().Rename("Prefab_DreamArrivalPoint").DontDestroyOnLoad();
if (_prefab == null)
{
NHLogger.LogWarning($"Tried to make a dream arrival point but couldn't. Do you have the DLC installed?");
return;
}
else
{
_prefab.AddComponent<DestroyOnDLC>()._destroyOnDLCNotOwned = true;
var dreamArrivalPoint = _prefab.GetComponent<DreamArrivalPoint>();
dreamArrivalPoint._location = DreamArrivalPoint.Location.Undefined;
dreamArrivalPoint._sector = null;
dreamArrivalPoint._entrywayVolumes = [];
dreamArrivalPoint._raftSpawn = null;
dreamArrivalPoint._connectedDreamCampfire = null;
dreamArrivalPoint._campfire._sector = null;
}
}
}
public static GameObject Make(GameObject planetGO, Sector sector, DreamArrivalPointInfo info, IModBehaviour mod)
{
InitPrefab();
if (_prefab == null || sector == null) return null;
var arrivalPointObj = DetailBuilder.Make(planetGO, sector, mod, _prefab, new DetailInfo(info));
StreamingHandler.SetUpStreaming(arrivalPointObj, sector);
DreamArrivalPoint arrivalPoint = arrivalPointObj.GetComponent<DreamArrivalPoint>();
arrivalPoint._sector = arrivalPoint.GetComponentInParent<Sector>();
arrivalPoint._location = DreamHandler.GetDreamArrivalLocation(info.id);
Locator.RegisterDreamArrivalPoint(arrivalPoint, arrivalPoint._location);
return arrivalPointObj;
}
}
}

View File

@ -0,0 +1,73 @@
using NewHorizons.External.Modules.Props;
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using NewHorizons.Utility.OWML;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Builder.Props.EchoesOfTheEye
{
public static class DreamCampfireBuilder
{
private static GameObject _prefab;
internal static void InitPrefab()
{
if (_prefab == null)
{
_prefab = SearchUtilities.Find("RingWorld_Body/Sector_RingInterior/Sector_Zone4/Sector_PrisonDocks/Sector_PrisonInterior/Interactibles_PrisonInterior/Prefab_IP_DreamCampfire").InstantiateInactive().Rename("Prefab_DreamCampfire").DontDestroyOnLoad();
if (_prefab == null)
{
NHLogger.LogWarning($"Tried to make a dream campfire but couldn't. Do you have the DLC installed?");
return;
}
else
{
_prefab.AddComponent<DestroyOnDLC>()._destroyOnDLCNotOwned = true;
var campfire = _prefab.GetComponentInChildren<DreamCampfire>();
campfire._dreamArrivalLocation = DreamArrivalPoint.Location.Undefined;
campfire._sector = null;
campfire._entrywayVolumes = [];
}
}
}
public static GameObject Make(GameObject planetGO, Sector sector, DreamCampfireInfo info, IModBehaviour mod)
{
InitPrefab();
if (_prefab == null || sector == null) return null;
var campfireObj = DetailBuilder.Make(planetGO, sector, mod, _prefab, new DetailInfo(info));
var campfire = campfireObj.GetComponentInChildren<DreamCampfire>();
campfire._dreamArrivalLocation = DreamHandler.GetDreamArrivalLocation(info.id);
Delay.FireInNUpdates(() => {
var streaming = campfireObj.GetComponentInChildren<DreamCampfireStreaming>();
if (streaming != null)
{
var targetArrivalPoint = Locator.GetDreamArrivalPoint(campfire._dreamArrivalLocation);
if (targetArrivalPoint != null)
{
var streamingGroup = targetArrivalPoint.transform.root.GetComponentInChildren<StreamingGroup>();
if (streamingGroup)
{
streaming._streamingGroup = streamingGroup;
}
}
}
}, 2);
Locator.RegisterDreamCampfire(campfire, campfire._dreamArrivalLocation);
return campfireObj;
}
}
}

View File

@ -1,5 +1,6 @@
using NewHorizons.Builder.Body; using NewHorizons.Builder.Body;
using NewHorizons.Builder.Props.Audio; using NewHorizons.Builder.Props.Audio;
using NewHorizons.Builder.Props.EchoesOfTheEye;
using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.Builder.Props.TranslatorText;
using NewHorizons.Builder.ShipLog; using NewHorizons.Builder.ShipLog;
using NewHorizons.External; using NewHorizons.External;
@ -101,6 +102,8 @@ namespace NewHorizons.Builder.Props
// If a prop has set its parentPath and the parent cannot be found, add it to the next pass and try again later // If a prop has set its parentPath and the parent cannot be found, add it to the next pass and try again later
nextPass = new List<Action>(); nextPass = new List<Action>();
if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamCampfires, (campfire) => DreamCampfireBuilder.Make(go, sector, campfire, mod), (campfire) => campfire.id);
if (Main.HasDLC) MakeGeneralProps(go, config.Props.dreamArrivalPoints, (point) => DreamArrivalPointBuilder.Make(go, sector, point, mod), (point) => point.id);
MakeGeneralProps(go, config.Props.gravityCannons, (cannon) => GravityCannonBuilder.Make(go, sector, cannon, mod), (cannon) => cannon.shuttleID); MakeGeneralProps(go, config.Props.gravityCannons, (cannon) => GravityCannonBuilder.Make(go, sector, cannon, mod), (cannon) => cannon.shuttleID);
MakeGeneralProps(go, config.Props.shuttles, (shuttle) => ShuttleBuilder.Make(go, sector, mod, shuttle), (shuttle) => shuttle.id); MakeGeneralProps(go, config.Props.shuttles, (shuttle) => ShuttleBuilder.Make(go, sector, mod, shuttle), (shuttle) => shuttle.id);
MakeGeneralProps(go, config.Props.details, (detail) => DetailBuilder.Make(go, sector, mod, detail), (detail) => detail.path); MakeGeneralProps(go, config.Props.details, (detail) => DetailBuilder.Make(go, sector, mod, detail), (detail) => detail.path);

View File

@ -123,6 +123,16 @@ namespace NewHorizons.External.Modules
/// </summary> /// </summary>
public ShuttleInfo[] shuttles; public ShuttleInfo[] shuttles;
/// <summary>
/// Add campfires that allow you to enter the dream world/simulation. Must be paired with a dream arrival point, which can be placed on this planet or elsewhere.
/// </summary>
public DreamCampfireInfo[] dreamCampfires;
/// <summary>
/// Add the points you will arrive at when entering the dream world/simulation from a paired dream campfire, which can be placed on this planet or elsewhere.
/// </summary>
public DreamArrivalPointInfo[] dreamArrivalPoints;
[Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public RevealVolumeInfo[] reveal; [Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public RevealVolumeInfo[] reveal;
[Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public AudioVolumeInfo[] audioVolumes; [Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public AudioVolumeInfo[] audioVolumes;

View File

@ -0,0 +1,22 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
{
[JsonObject]
public class DreamArrivalPointInfo : GeneralPropInfo
{
/// <summary>
/// Unique ID for this dream-world arrival point
/// </summary>
public string id;
/// <summary>
/// Whether to generate simulation meshes (the models used in the "tronworld" or "matrix" view) for most objects on the current planet by cloning the existing meshes and applying the simulation materials. Leave this off if you are building your own simulation meshes or using existing objects which have them.
/// </summary>
public bool generateSimulationMeshes;
}
}

View File

@ -0,0 +1,18 @@
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
{
[JsonObject]
public class DreamCampfireInfo : GeneralPropInfo
{
/// <summary>
/// Unique ID for this dream-world campfire
/// </summary>
public string id;
}
}

View File

@ -0,0 +1,85 @@
using NewHorizons.Utility;
using NewHorizons.Utility.OWML;
using OWML.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Handlers
{
public static class DreamHandler
{
public static DreamArrivalPoint.Location GetDreamArrivalLocation(string id)
{
try
{
if (EnumUtils.TryParse(id, out DreamArrivalPoint.Location location))
{
return location;
}
else
{
NHLogger.LogVerbose($"Registering new dream arrival location [{id}]");
return EnumUtilities.Create<DreamArrivalPoint.Location>(id);
}
}
catch (Exception e)
{
NHLogger.LogError($"Couldn't load dream arrival location [{id}]:\n{e}");
return DreamArrivalPoint.Location.Undefined;
}
}
public static void MigrateDreamWorldController()
{
// Create new DreamWorldController instance since the existing one is disabled
var managerObj = new GameObject("DreamWorldManager");
managerObj.SetActive(false);
var oldDWC = Locator.GetDreamWorldController();
var dwc = managerObj.AddComponent<DreamWorldController>();
var simRootObj = MigrateCopy(oldDWC._primarySimulationRoot.gameObject, managerObj);
dwc._primarySimulationRoot = simRootObj.transform;
dwc._simulationRoots = [simRootObj.transform];
dwc._simulationCamera = simRootObj.FindChild("Camera_Simulation").GetComponent<SimulationCamera>();
dwc._simulationSphere = simRootObj.FindChild("SimulationSphere").GetComponent<OWRenderer>();
dwc._tempSkyboxColor = oldDWC._tempSkyboxColor;
dwc._sarcophagusController = oldDWC._sarcophagusController;
dwc._prisonerDirector = oldDWC._prisonerDirector;
// These should correspond to the arrival point's attached body
dwc._dreamBody = null;
dwc._dreamWorldSector = null;
dwc._dreamWorldVolume = null;
// These should correspond to the campfire's attached body
dwc._planetBody = null;
dwc._ringWorldController = null;
managerObj.SetActive(true);
// Run after Start() completes
Delay.FireOnNextUpdate(() =>
{
dwc._dreamBody = null;
dwc._dreamWorldSector = null;
dwc._dreamWorldVolume = null;
dwc._planetBody = null;
dwc._ringWorldController = null;
});
}
private static GameObject MigrateCopy(GameObject go, GameObject newParent)
{
var clone = GameObject.Instantiate(go);
clone.transform.SetParent(newParent.transform, false);
return clone;
}
}
}

View File

@ -70,6 +70,7 @@ namespace NewHorizons.Handlers
if (Main.HasDLC) if (Main.HasDLC)
{ {
StrangerRemoved(); StrangerRemoved();
DreamWorldRemoved();
} }
// Put it back at the center of the universe after banishing it else there are weird graphical bugs // Put it back at the center of the universe after banishing it else there are weird graphical bugs
@ -90,6 +91,11 @@ namespace NewHorizons.Handlers
} }
} }
private static void DreamWorldRemoved()
{
DreamHandler.MigrateDreamWorldController();
}
private static void SunRemoved() private static void SunRemoved()
{ {
var sun = SearchUtilities.Find("Sun_Body").GetComponent<AstroObject>(); var sun = SearchUtilities.Find("Sun_Body").GetComponent<AstroObject>();
@ -207,6 +213,9 @@ namespace NewHorizons.Handlers
case AstroObject.Name.RingWorld: case AstroObject.Name.RingWorld:
StrangerRemoved(); StrangerRemoved();
break; break;
case AstroObject.Name.DreamWorld:
DreamWorldRemoved();
break;
} }
// Always delete the children // Always delete the children

View File

@ -4,6 +4,7 @@ using NewHorizons.Builder.Body;
using NewHorizons.Builder.General; using NewHorizons.Builder.General;
using NewHorizons.Builder.Props; using NewHorizons.Builder.Props;
using NewHorizons.Builder.Props.Audio; using NewHorizons.Builder.Props.Audio;
using NewHorizons.Builder.Props.EchoesOfTheEye;
using NewHorizons.Builder.Props.TranslatorText; using NewHorizons.Builder.Props.TranslatorText;
using NewHorizons.Components.Fixers; using NewHorizons.Components.Fixers;
using NewHorizons.Components.Ship; using NewHorizons.Components.Ship;
@ -381,6 +382,8 @@ namespace NewHorizons
ProjectionBuilder.InitPrefabs(); ProjectionBuilder.InitPrefabs();
CloakBuilder.InitPrefab(); CloakBuilder.InitPrefab();
RaftBuilder.InitPrefab(); RaftBuilder.InitPrefab();
DreamCampfireBuilder.InitPrefab();
DreamArrivalPointBuilder.InitPrefab();
} }
WarpPadBuilder.InitPrefabs(); WarpPadBuilder.InitPrefabs();

View File

@ -26,5 +26,40 @@ namespace NewHorizons.Patches.EchoesOfTheEyePatches
.Repeat(matcher => matcher.RemoveInstructions(5)) .Repeat(matcher => matcher.RemoveInstructions(5))
.InstructionEnumeration(); .InstructionEnumeration();
} }
[HarmonyPrefix]
[HarmonyPatch(nameof(DreamWorldController.EnterDreamWorld))]
public static void DreamWorldController_EnterDreamWorld(DreamWorldController __instance, DreamCampfire dreamCampfire, DreamArrivalPoint arrivalPoint)
{
var dreamWorldAO = Locator.GetAstroObject(AstroObject.Name.DreamWorld);
if (arrivalPoint.GetAttachedOWRigidbody() == dreamWorldAO.GetOWRigidbody())
{
__instance._dreamBody = dreamWorldAO.GetAttachedOWRigidbody();
__instance._dreamWorldSector = dreamWorldAO.GetRootSector();
__instance._dreamWorldVolume = __instance._dreamWorldSector.transform.Find("Volumes_DreamWorld").Find("DreamWorldVolume").GetComponent<OWTriggerVolume>();
}
else
{
var arrivalAO = arrivalPoint.GetComponentInParent<AstroObject>();
__instance._dreamBody = arrivalAO.GetAttachedOWRigidbody();
__instance._dreamWorldSector = arrivalAO.GetRootSector();
__instance._dreamWorldVolume = arrivalAO._gravityVolume.GetOWTriggerVolume();
}
__instance._primarySimulationRoot.GetComponent<SectorCullGroup>().SetSector(__instance._dreamWorldSector);
var ringWorldAO = Locator.GetAstroObject(AstroObject.Name.RingWorld);
if (dreamCampfire.GetAttachedOWRigidbody() == ringWorldAO.GetOWRigidbody())
{
__instance._planetBody = ringWorldAO.GetAttachedOWRigidbody();
__instance._ringWorldController = ringWorldAO.GetComponent<RingWorldController>();
}
else
{
var departureAO = dreamCampfire.GetComponentInParent<AstroObject>();
__instance._planetBody = departureAO.GetAttachedOWRigidbody();
__instance._ringWorldController = null;
}
}
} }
} }