Slide reel conditions + some wyrm things (#984)

## Minor features

- Added `persistentConditionsToSet` and `conditionsToSet` to slide
reels. Now instead of just revealing ship logs at the end of a slide
reel/vision, you can set persistent and dialogue conditions.

## Improvements

- Static body shiplogs are now automatically arranged by their distance
to the primary (previously only considered semi-major axis)
- Will register a planet config as invalid if the planet is listed as
its own primary orbital body (nonsense) (fixes #983)
This commit is contained in:
xen-42 2024-10-27 12:59:55 -04:00 committed by GitHub
commit 7c3a8096cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 116 additions and 35 deletions

View File

@ -1,4 +1,5 @@
using HarmonyLib;
using NewHorizons.Components.EOTE;
using NewHorizons.External.Modules.Props;
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
using NewHorizons.Handlers;
@ -137,7 +138,10 @@ namespace NewHorizons.Builder.Props
slideReel.SetSector(sector);
slideReel.SetVisible(true);
var slideCollectionContainer = slideReelObj.GetRequiredComponent<SlideCollectionContainer>();
var toDestroy = slideReelObj.GetComponent<SlideCollectionContainer>();
var slideCollectionContainer = slideReelObj.AddComponent<NHSlideCollectionContainer>();
slideReel._slideCollectionContainer = slideCollectionContainer;
Component.DestroyImmediate(toDestroy);
foreach (var renderer in slideReelObj.GetComponentsInChildren<Renderer>())
{
@ -342,7 +346,10 @@ namespace NewHorizons.Builder.Props
var autoProjector = projectorObj.GetComponent<AutoSlideProjector>();
autoProjector._sector = sector;
var slideCollectionContainer = autoProjector.GetRequiredComponent<SlideCollectionContainer>();
var toDestroy = autoProjector.GetComponent<SlideCollectionContainer>();
var slideCollectionContainer = autoProjector.gameObject.AddComponent<NHSlideCollectionContainer>();
autoProjector._slideCollectionItem = slideCollectionContainer;
Component.DestroyImmediate(toDestroy);
// Now we replace the slides
int slidesCount = info.slides.Length;
@ -419,7 +426,7 @@ namespace NewHorizons.Builder.Props
// attach a component to store all the data for the slides that play when a vision torch scans this target
var target = g.AddComponent<VisionTorchTarget>();
var slideCollectionContainer = g.AddComponent<SlideCollectionContainer>();
var slideCollectionContainer = g.AddComponent<NHSlideCollectionContainer>();
slideCollectionContainer.slideCollection = slideCollection;
target.slideCollection = g.AddComponent<MindSlideCollection>();
target.slideCollection._slideCollectionContainer = slideCollectionContainer;
@ -486,7 +493,7 @@ namespace NewHorizons.Builder.Props
);
// Set up the containers for the slides
var slideCollectionContainer = standingTorch.AddComponent<SlideCollectionContainer>();
var slideCollectionContainer = standingTorch.AddComponent<NHSlideCollectionContainer>();
slideCollectionContainer.slideCollection = slideCollection;
var mindSlideCollection = standingTorch.AddComponent<MindSlideCollection>();
@ -658,12 +665,15 @@ namespace NewHorizons.Builder.Props
Slide.WriteModules(modules, ref slide._modulesList, ref slide._modulesData, ref slide.lengths);
}
private static void LinkShipLogFacts(ProjectionInfo info, SlideCollectionContainer slideCollectionContainer)
private static void LinkShipLogFacts(ProjectionInfo info, NHSlideCollectionContainer slideCollectionContainer)
{
// Idk why but it wants reveals to be comma delimited not a list
if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals);
// Don't use null value, NRE in SlideCollectionContainer.Initialize
slideCollectionContainer._playWithShipLogFacts = info.playWithShipLogFacts ?? Array.Empty<string>();
slideCollectionContainer.conditionsToSet = info.conditionsToSet;
slideCollectionContainer.persistentConditionsToSet = info.persistentConditionsToSet;
}
}

View File

@ -440,6 +440,11 @@ namespace NewHorizons.Builder.ShipLog
private static MapModeObject ConstructPrimaryNode(List<NewHorizonsBody> bodies)
{
float DistanceFromPrimary(NewHorizonsBody body)
{
return Mathf.Max(body.Config.Orbit.semiMajorAxis, body.Config.Orbit.staticPosition?.Length() ?? 0f);
}
foreach (NewHorizonsBody body in bodies.Where(b => b.Config.Base.centerOfSolarSystem))
{
bodies.Sort((b, o) => b.Config.Orbit.semiMajorAxis.CompareTo(o.Config.Orbit.semiMajorAxis));

View File

@ -0,0 +1,62 @@
using HarmonyLib;
namespace NewHorizons.Components.EOTE;
[HarmonyPatch(typeof(SlideCollectionContainer))]
public class NHSlideCollectionContainer : SlideCollectionContainer
{
public string[] conditionsToSet;
public string[] persistentConditionsToSet;
[HarmonyPrefix]
[HarmonyPatch(typeof(SlideCollectionContainer), nameof(SlideCollectionContainer.Initialize))]
public static bool SlideCollectionContainer_Initialize(SlideCollectionContainer __instance)
{
if (__instance is NHSlideCollectionContainer)
{
if (__instance._initialized)
return false;
__instance.SetupReadFlags();
__instance.RegisterPerSlideCompletion();
if (__instance.streamingTexturesAvailable)
__instance.SetupStreaming();
__instance.BuildMusicRangesIndex();
__instance._changeSlidesAllowed = true;
__instance._initialized = true;
__instance._slideCollection.isVision = __instance._owningItem == null;
foreach (var factID in __instance._playWithShipLogFacts)
{
var fact = Locator.GetShipLogManager().GetFact(factID);
fact?.RegisterSlideCollection(__instance._slideCollection);
}
return false;
}
return true;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(SlideCollectionContainer), nameof(SlideCollectionContainer.SetReadFlag))]
public static void SlideCollectionContainer_SetReadFlag(SlideCollectionContainer __instance)
{
if (__instance is NHSlideCollectionContainer container)
{
if (container._unreadSlideIndices.Count == 0)
{
if (container.conditionsToSet != null)
{
foreach (var condition in container.conditionsToSet)
{
DialogueConditionManager.SharedInstance.SetConditionState(condition, true);
}
}
if (container.persistentConditionsToSet != null)
{
foreach (var condition in container.persistentConditionsToSet)
{
PlayerData.SetPersistentCondition(condition, true);
}
}
}
}
}
}

View File

@ -287,6 +287,14 @@ namespace NewHorizons.External.Configs
// Disable map marker for dream dimensions
if (Dream != null && Dream.inDreamWorld) MapMarker.enabled = false;
// User error #983
// This will not catch if they wrote the two names slightly differently but oh well don't be stupid
// Ideally we should just check for loops in PlanetGraph
if (Orbit.primaryBody == name)
{
throw new Exception($"You set {name} to orbit itself, that is invalid. The planet will not load.");
}
}
public void Migrate()

View File

@ -48,6 +48,16 @@ namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
/// </summary>
public string[] reveals;
/// <summary>
/// The dialogue conditions to set after finishing this slide reel.
/// </summary>
public string[] conditionsToSet;
/// <summary>
/// The persistent conditions to set after finishing this slide reel.
/// </summary>
public string[] persistentConditionsToSet;
/// <summary>
/// The ship log facts that make the reel play when they are displayed in the computer (by selecting entries or arrows).
/// You should probably include facts from `reveals` here.

View File

@ -27,6 +27,8 @@ namespace NewHorizons.External.SerializableData
return new Vector3(vec.x, vec.y, vec.z);
}
public float Length() => Mathf.Sqrt(x * x + y * y + z * z);
public override string ToString() => $"{x}, {y}, {z}";
}
}

View File

@ -1,30 +0,0 @@
using HarmonyLib;
namespace NewHorizons.Patches.ShipLogPatches
{
[HarmonyPatch(typeof(SlideCollectionContainer))]
public static class SlideCollectionContainerPatches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(SlideCollectionContainer), nameof(SlideCollectionContainer.Initialize))]
public static bool SlideCollectionContainer_Initialize(SlideCollectionContainer __instance)
{
if (__instance._initialized)
return false;
__instance.SetupReadFlags();
__instance.RegisterPerSlideCompletion();
if (__instance.streamingTexturesAvailable)
__instance.SetupStreaming();
__instance.BuildMusicRangesIndex();
__instance._changeSlidesAllowed = true;
__instance._initialized = true;
__instance._slideCollection.isVision = __instance._owningItem == null;
foreach (var factID in __instance._playWithShipLogFacts)
{
var fact = Locator.GetShipLogManager().GetFact(factID);
fact?.RegisterSlideCollection(__instance._slideCollection);
}
return false;
}
}
}

View File

@ -2263,6 +2263,20 @@
"type": "string"
}
},
"conditionsToSet": {
"type": "array",
"description": "The dialogue conditions to set after finishing this slide reel.",
"items": {
"type": "string"
}
},
"persistentConditionsToSet": {
"type": "array",
"description": "The persistent conditions to set after finishing this slide reel.",
"items": {
"type": "string"
}
},
"playWithShipLogFacts": {
"type": "array",
"description": "The ship log facts that make the reel play when they are displayed in the computer (by selecting entries or arrows).\nYou should probably include facts from `reveals` here.\nIf you only specify a rumor fact, then it would only play in its ship log entry if this has revealed only\nrumor facts because an entry with revealed explore facts doesn't display rumor facts.",