From 8b0d38aa019565de855faf274967cfa29df5c401 Mon Sep 17 00:00:00 2001 From: Ben C Date: Fri, 4 Feb 2022 18:21:19 -0500 Subject: [PATCH 1/6] Basic Version --- .gitignore | 3 +- NewHorizons/Builder/General/ShipLogBuilder.cs | 419 ++++++++++++++++++ NewHorizons/External/IPlanetConfig.cs | 1 + NewHorizons/External/PlanetConfig.cs | 1 + NewHorizons/External/ShipLogModule.cs | 34 ++ NewHorizons/Main.cs | 32 +- NewHorizons/NewHorizons.csproj.user | 6 +- NewHorizons/Tools/Patches.cs | 177 +++++++- NewHorizons/Utility/MVector2.cs | 26 ++ NewHorizons/Utility/SearchUtilities.cs | 10 + 10 files changed, 703 insertions(+), 6 deletions(-) create mode 100644 NewHorizons/External/ShipLogModule.cs create mode 100644 NewHorizons/Utility/MVector2.cs diff --git a/.gitignore b/.gitignore index 204daa57..70f0ab13 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ obj zip *.zip -*/Build/* \ No newline at end of file +*/Build/* +.idea/ diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs index 8d38d135..2fceed15 100644 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ b/NewHorizons/Builder/General/ShipLogBuilder.cs @@ -1,17 +1,436 @@ using NewHorizons.Components; using System; +using System.Collections; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Xml.Linq; using System.Text; using System.Threading.Tasks; +using NewHorizons.External; +using NewHorizons.Utility; +using OWML.Common; using UnityEngine; +using UnityEngine.UI; using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Builder.General { public static class ShipLogBuilder { + public static readonly string PAN_ROOT_PATH = "Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot"; + public static ShipLogStarChartMode ShipLogStarChartMode; + private static Dictionary curiosityColors = new Dictionary(); + private static Dictionary curiosityHighlightColors = new Dictionary(); + private static Dictionary rawNameToCuriosityName = new Dictionary(); + private static Dictionary entryIdToRawName = new Dictionary(); + private static Dictionary astroIdToBody = new Dictionary(); + + private class MapModeObject + { + public int x; + public int y; + public int branch_width; + public int branch_height; + public int level; + public NewHorizonsBody mainBody; + public ShipLogAstroObject astroObject; + public List children; + public MapModeObject parent; + public void increment_width() + { + branch_width++; + parent?.increment_width(); + } + public void increment_height() + { + branch_height++; + parent?.increment_height(); + } + } + + public static string GetAstroBodyShipLogName(string id) + { + return astroIdToBody[id].Config.Name; + } + + public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer) + { + MapModeObject rootObject = MakePrimaryNode(systemName); + if (rootObject.mainBody != null) + { + CreateAllNodes(ref rootObject, transformParent, layer); + } + + const int maxAmount = 20; + ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; + for (int i = 0; i < maxAmount; i++) + { + navMatrix[i] = new ShipLogAstroObject[maxAmount]; + } + CreateNavigationMatrix(rootObject, ref navMatrix); + navMatrix = navMatrix.Where(a => a.Count(c => c != null) > 0).Prepend(new ShipLogAstroObject[1]).ToArray(); + for (var index = 0; index < navMatrix.Length; index++) + { + navMatrix[index] = navMatrix[index].Where(a => a != null).ToArray(); + } + return navMatrix; + } + + private static void CreateNavigationMatrix(MapModeObject root, ref ShipLogAstroObject[][] navMatrix) + { + if (root.astroObject != null) + { + navMatrix[root.y][root.x] = root.astroObject; + } + foreach (MapModeObject child in root.children) + { + CreateNavigationMatrix(child, ref navMatrix); + } + } + + private static void CreateAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) + { + CreateNode(ref parentNode, parent, layer); + for (var i = 0; i < parentNode.children.Count; i++) + { + MapModeObject child = parentNode.children[i]; + CreateAllNodes(ref child, parent, layer); + parentNode.children[i] = child; + } + } + + private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, string imagePath, string name, int layer) + { + GameObject newImageGO = new GameObject(name); + newImageGO.layer = layer; + newImageGO.transform.SetParent(nodeGO.transform); + + RectTransform transform = newImageGO.AddComponent(); + transform.localPosition = Vector3.zero; + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one; + + Image newImage = newImageGO.AddComponent(); + if (imagePath == "DEFAULT") + { + newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; + } + else + { + Texture2D newTexture = assets.GetTexture(imagePath); + Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); + Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); + newImage.sprite = Sprite.Create(newTexture, rect, pivot); + } + return newImageGO; + } + + public static T KeyByValue(this Dictionary dict, W val) + { + T key = default; + foreach (KeyValuePair pair in dict) + { + if (EqualityComparer.Default.Equals(pair.Value, val)) + { + key = pair.Key; + break; + } + } + return key; + } + + private static string GetAstroObjectId(NewHorizonsBody body) + { + return KeyByValue(astroIdToBody, body); + } + + private static void CreateAstroObject(GameObject nodeGO, ref MapModeObject node, GameObject referenceUnviewedSprite, int layer) + { + const float unviewedIconOffset = 15; + ShipLogAstroObject astroObject = nodeGO.AddComponent(); + astroObject._id = GetAstroObjectId(node.mainBody); + string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; + string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; + astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, "Image", layer); + astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, "Outline", layer); + astroObject._unviewedObj = GameObject.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); + astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; + Rect imageRect = astroObject._imageObj.GetComponent().rect; + astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); + node.astroObject = astroObject; + } + + private static void CreateNode(ref MapModeObject node, GameObject parent, int layer) + { + const float padding = 250f; + + GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog"); + newNodeGO.layer = layer; + newNodeGO.transform.SetParent(parent.transform); + + RectTransform transform = newNodeGO.AddComponent(); + float scale = node.mainBody.Config.ShipLog?.mapMode?.scale?? 1f; + scale = scale <= 0 ? 1f : scale; + transform.localPosition = new Vector3(node.x * padding, node.y * padding, 0); + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one * scale; + + if (node.mainBody.Config.ShipLog?.xmlFile == null) + { + Image newImage = newNodeGO.AddComponent(); + string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; + if (imagePath == "DEFAULT") + { + newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; + } + else + { + Texture2D newTexture = node.mainBody.Mod.Assets.GetTexture(imagePath); + Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); + Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); + newImage.sprite = Sprite.Create(newTexture, rect, pivot); + } + } + else + { + CreateAstroObject(newNodeGO, ref node, GameObject.Find(PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"), layer); + } + } + + private static MapModeObject MakePrimaryNode(string systemName) + { + foreach (NewHorizonsBody body in Main.BodyDict[systemName]) + { + if (!body.Config.Base.CenterOfSolarSystem) continue; + MapModeObject newNode = new MapModeObject + { + mainBody = body, + level = 0, + x = 0, + y = 0 + }; + newNode.children = MakeChildrenNodes(systemName, newNode); + return newNode; + } + Logger.LogError("Couldn't find center of system!"); + return new MapModeObject(); + } + + private static List MakeChildrenNodes(string systemName, MapModeObject parent) + { + List children = new List(); + int newX = parent.x; + int newY = parent.y; + foreach (NewHorizonsBody body in Main.BodyDict[systemName]) + { + if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) + { + int newLevel = parent.level + 1; + bool even = newLevel % 2 == 0; + newX = even ? newX : newX + 1; + newY = even ? newY + 1 : newY; + MapModeObject newNode = new MapModeObject() + { + mainBody = body, + level = newLevel, + x = newX, + y = newY, + parent=parent + }; + newNode.children = MakeChildrenNodes(systemName, newNode); + if (even) + { + newY += newNode.branch_height; + parent.increment_height(); + } + else + { + newX += newNode.branch_width; + parent.increment_width(); + } + children.Add(newNode); + } + } + return children; + } + + public static void AddCuriosityColors(ShipLogModule.CuriosityColor[] newColors) + { + foreach (ShipLogModule.CuriosityColor newColor in newColors) + { + if (rawNameToCuriosityName.ContainsKey(newColor.id) == false) + { + CuriosityName newName = (CuriosityName) 8 + rawNameToCuriosityName.Count; + rawNameToCuriosityName.Add(newColor.id, newName); + curiosityColors.Add(newName, newColor.color.ToColor()); + curiosityHighlightColors.Add(newName, newColor.highlightColor.ToColor()); + } + } + } + + public static Color GetCuriosityColor(CuriosityName curiosityName, bool highlighted, Color defaultColor, Color defaultHighlight) + { + if (curiosityColors.ContainsKey(curiosityName) && curiosityHighlightColors.ContainsKey(curiosityName)) + { + return (highlighted ? curiosityHighlightColors : curiosityColors)[curiosityName]; + } + else + { + return highlighted? defaultHighlight : defaultColor; + } + } + + public static void AddAstroBodyToShipLog(ShipLogManager manager, NewHorizonsBody body) + { + string systemName = body.Config.StarSystem; + XElement astroBodyFile = XElement.Load(Main.Instance.ModHelper.Manifest.ModFolderPath + body.Config.ShipLog.xmlFile); + XElement astroBodyId = astroBodyFile.Element("ID"); + if (astroBodyId == null) + { + Logger.LogError("Failed to load ship log for " + systemName + "!"); + } + else + { + astroBodyId.SetValue(systemName + "/" + astroBodyId.Value); + foreach (XElement entryElement in astroBodyFile.DescendantsAndSelf("Entry")) + { + XElement curiosityName = entryElement.Element("Curiosity"); + XElement id = entryElement.Element("ID"); + if (curiosityName != null && id != null && entryIdToRawName.ContainsKey(id.Value) == false) + { + entryIdToRawName.Add(id.Value, curiosityName.Value); + } + AddTranslation(entryElement); + } + TextAsset newAsset = new TextAsset(astroBodyFile.ToString()); + List newBodies = new List(manager._shipLogXmlAssets) {newAsset}; + manager._shipLogXmlAssets = newBodies.ToArray(); + if (astroIdToBody.ContainsKey(astroBodyId.Value) == false) + { + astroIdToBody.Add(astroBodyId.Value, body); + } + } + } + + private static void AddTranslation(XElement entry) + { + Dictionary table = TextTranslation.Get().m_table.theShipLogTable; + XElement nameElement = entry.Element("Name"); + if (nameElement != null) + { + string name = nameElement.Value; + table[name] = name; + foreach (XElement rumorFact in entry.Elements("RumorFact")) + { + XElement rumorName = rumorFact.Element("RumorName"); + if (rumorName != null) + { + table[rumorName.Value] = rumorName.Value; + } + + XElement rumorText = rumorFact.Element("Text"); + if (rumorText != null) + { + table[name + rumorText.Value] = rumorText.Value; + } + } + foreach (XElement exploreFact in entry.Elements("ExploreFact")) + { + XElement exploreText = exploreFact.Element("Text"); + if (exploreText != null) + { + table[name + exploreText.Value] = exploreText.Value; + } + } + } + } + + public static void UpdateEntryCuriosity(ref ShipLogEntry entry) + { + if (entryIdToRawName.ContainsKey(entry._id)) + { + entry._curiosity = rawNameToCuriosityName[entryIdToRawName[entry._id]]; + } + } + + private static Sprite GetSprite(string entryId, NewHorizonsBody body) + { + IModAssets assets = body.Mod.Assets; + string path = body.Config.ShipLog.spriteFolder + "/" + entryId + ".png"; + if (File.Exists(Main.Instance.ModHelper.Manifest.ModFolderPath + path)) + { + Texture2D newTexture = assets.GetTexture(path); + Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); + Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); + return Sprite.Create(newTexture, rect, pivot); + } + else + { + return Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; + } + } + + private static NewHorizonsBody GetConfigFromEntry(ShipLogEntry entry) + { + return astroIdToBody[entry._astroObjectID]; + } + + private static Vector2? FindPosition(string entryId, ShipLogModule config) + { + if (config.positions == null) return null; + foreach (ShipLogModule.EntryPosition position in config.positions) + { + if (position.id == entryId) + { + return position.position; + } + } + return null; + } + + public static void GenerateEntryData(ShipLogManager manager) + { + const int step = 400; + int colAccumulator = 0; + int rowAccumulator = 0; + foreach(ShipLogEntry entry in manager._entryList) + { + if (manager._entryDataDict.ContainsKey(entry._id) == false) + { + NewHorizonsBody body = GetConfigFromEntry(entry); + Vector2? manualEntryPosition = FindPosition(entry._id, body.Config.ShipLog); + Vector2 entryPosition; + if (manualEntryPosition == null) + { + entryPosition = new Vector2(colAccumulator, rowAccumulator); + } + else + { + entryPosition = (Vector2) manualEntryPosition; + } + EntryData newData = new EntryData + { + id = entry._id, + cardPosition = entryPosition, + sprite = body.Config.ShipLog.spriteFolder == null? null : GetSprite(entry._id, body) + }; + entry.SetSprite(newData.sprite == null? manager._shipLogLibrary.defaultEntrySprite : newData.sprite); + manager._entryDataDict.Add(entry._id, newData); + int index = manager._entryList.IndexOf(entry); + if (index < manager._entryList.Count - 2 && manager._entryList[index + 1]._astroObjectID != entry._astroObjectID) + { + rowAccumulator += step; + colAccumulator = 0; + } + else + { + colAccumulator += step; + } + } + } + } public static void Init() { diff --git a/NewHorizons/External/IPlanetConfig.cs b/NewHorizons/External/IPlanetConfig.cs index 56d12c12..0922c4fa 100644 --- a/NewHorizons/External/IPlanetConfig.cs +++ b/NewHorizons/External/IPlanetConfig.cs @@ -20,6 +20,7 @@ namespace NewHorizons.External StarModule Star { get; } FocalPointModule FocalPoint { get; } PropModule Props { get; } + ShipLogModule ShipLog { get; } SpawnModule Spawn { get; } SignalModule Signal { get; } SingularityModule Singularity { get; } diff --git a/NewHorizons/External/PlanetConfig.cs b/NewHorizons/External/PlanetConfig.cs index 4724d3a2..7539d0cf 100644 --- a/NewHorizons/External/PlanetConfig.cs +++ b/NewHorizons/External/PlanetConfig.cs @@ -23,6 +23,7 @@ namespace NewHorizons.External public StarModule Star { get; set; } public FocalPointModule FocalPoint { get; set; } public PropModule Props { get; set; } + public ShipLogModule ShipLog { get; set; } public SpawnModule Spawn { get; set; } public SignalModule Signal { get; set; } public SingularityModule Singularity { get; set; } diff --git a/NewHorizons/External/ShipLogModule.cs b/NewHorizons/External/ShipLogModule.cs new file mode 100644 index 00000000..a805e303 --- /dev/null +++ b/NewHorizons/External/ShipLogModule.cs @@ -0,0 +1,34 @@ +using NewHorizons.Utility; + +namespace NewHorizons.External +{ + public class ShipLogModule : Module + { + public string xmlFile; + public string spriteFolder; + public MapMode mapMode; + public CuriosityColor[] curiosities; + public EntryPosition[] positions; + + public class MapMode + { + public string revealedSprite; + public string outlineSprite; + public float scale; + public bool invisibleWhenHidden; + } + + public class CuriosityColor + { + public string id; + public MColor color; + public MColor highlightColor; + } + + public class EntryPosition + { + public string id; + public MVector2 position; + } + } +} \ No newline at end of file diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index e2c01d43..769aeaff 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -12,12 +12,13 @@ using NewHorizons.Utility; using OWML.Common; using OWML.ModHelper; using OWML.Utils; -using PacificEngine.OW_CommonResources.Game.Player; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; +using Epic.OnlineServices; +using PacificEngine.OW_CommonResources.Game.Player; using UnityEngine; using UnityEngine.SceneManagement; using UnityEngine.UI; @@ -50,6 +51,35 @@ namespace NewHorizons return new NewHorizonsApi(); } + private void OnGUI() + { + GUILayout.BeginArea(new Rect(0, 0, 100, 100)); + bool learnPress = GUILayout.Button("Learn Thing"); + if (learnPress) + { + Locator.GetShipLogManager().RevealFact("COOL_ROCK_R1", false, true); + Locator.GetShipLogManager().RevealFact("COOL_ROCK_R2", false, true); + Locator.GetShipLogManager().RevealFact("UNCOOL_ROCK_R1", false, true); + Locator.GetShipLogManager().RevealFact("UNCOOL_ROCK_R2", false, true); + Locator.GetShipLogManager().RevealFact("UNCOOL_ROCK_R3", false, true); + + } + + bool iRemem = GUILayout.Button("I Remem"); + if (iRemem) + { + Data.knowAllFacts = true; + Data.knowAllRumors = true; + } + bool forgorPress = GUILayout.Button("I Forgor"); + if (forgorPress) + { + Data.knowAllFacts = false; + Data.knowAllRumors = false; + } + GUILayout.EndArea(); + } + public void Start() { SceneManager.sceneLoaded += OnSceneLoaded; diff --git a/NewHorizons/NewHorizons.csproj.user b/NewHorizons/NewHorizons.csproj.user index 4a7efd53..9aeb566d 100644 --- a/NewHorizons/NewHorizons.csproj.user +++ b/NewHorizons/NewHorizons.csproj.user @@ -2,7 +2,7 @@ ProjectFiles - $(AppData)\OuterWildsModManager\OWML\Mods\xen.NewHorizons - $(AppData)\OuterWildsModManager\OWML\Mods + $(AppData)\OuterWildsModManager\OWML\Mods\xen.NewHorizons + $(AppData)\OuterWildsModManager\OWML\Mods - + \ No newline at end of file diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index 4ee1062b..ee9522a4 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -5,11 +5,17 @@ using NewHorizons.External; using OWML.Common; using System; using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; +using System.Xml.Linq; +using Harmony; +using NewHorizons.Utility; +using OWML.Utils; using UnityEngine; using Logger = NewHorizons.Utility.Logger; +using Object = UnityEngine.Object; namespace NewHorizons.Tools { @@ -41,9 +47,11 @@ namespace NewHorizons.Tools var playerDataLearnFrequency = typeof(PlayerData).GetMethod("LearnFrequency"); Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataLearnFrequency, typeof(Patches), nameof(Patches.OnPlayerDataLearnFrequency)); var playerDataKnowsMultipleFrequencies = typeof(PlayerData).GetMethod("KnowsMultipleFrequencies"); - Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataKnowsMultipleFrequencies, typeof(Patches), nameof(Patches.OnPlayerDataKnowsMultipleFrequencies)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataKnowsMultipleFrequencies, typeof(Patches), nameof(Patches.OnPlayerDataKnowsMultipleFrequencies)); var playerDataResetGame = typeof(PlayerData).GetMethod("ResetGame"); Main.Instance.ModHelper.HarmonyHelper.AddPostfix(playerDataResetGame, typeof(Patches), nameof(Patches.OnPlayerDataResetGame)); + var playerDataGetNewlyRevealedFactIDs = typeof(PlayerData).GetMethod("GetNewlyRevealedFactIDs"); + Main.Instance.ModHelper.HarmonyHelper.AddPostfix(playerDataGetNewlyRevealedFactIDs, typeof(Patches), nameof(Patches.OnPlayerDataGetNewlyRevealedFactIDsComplete)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Start", typeof(Patches), nameof(Patches.OnBlackHoleVolumeStart)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.OnWhiteHoleVolumeAwake)); @@ -51,12 +59,30 @@ namespace NewHorizons.Tools Main.Instance.ModHelper.HarmonyHelper.AddPrefix("IsLaunched", typeof(Patches), nameof(Patches.OnSurveyorProbeIsLaunched)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Update", typeof(Patches), nameof(Patches.OnShipLogControllerUpdate)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.OnShipLogManagerAwake)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("IsFactRevealed", typeof(Patches), nameof(Patches.OnShipLogManagerIsFactRevealed)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("CheckForCompletionAchievement", typeof(Patches), nameof(Patches.OnShipLogManagerCheckForCompletionAchievement)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("RevealFact", typeof(Patches), nameof(Patches.OnShipLogManagerRevealFact)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("GetCuriosityColor", typeof(Patches), nameof(Patches.OnUIStyleManagerGetCuriosityColor)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Initialize", typeof(Patches), nameof(Patches.OnShipLogMapModeInitialize)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.DisableShipLogSandFunnel)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("UpdateState", typeof(Patches), nameof(Patches.DisableShipLogSandFunnel)); + + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("GetName", typeof(Patches), nameof(Patches.OnShipLogAstroObjectGetName)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Update", typeof(Patches), nameof(Patches.OnShipCockpitControllerUpdate)); // Postfixes Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnMapControllerAwake)); Main.Instance.ModHelper.HarmonyHelper.AddPostfix("EnterMode", typeof(Patches), nameof(Patches.OnShipLogMapModeEnterMode)); + + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnShipLogManagerAwakeComplete)); + + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Initialize", typeof(Patches), nameof(Patches.OnShipLogMapModeInitializeComplete)); } public static bool GetHUDDisplayName(ReferenceFrame __instance, ref string __result) @@ -398,6 +424,155 @@ namespace NewHorizons.Tools } return true; } + + #region ShipLog + public static void OnShipLogManagerAwake(ShipLogManager __instance) + { + Logger.Log("Beginning Ship Log Generation For: " + Main.Instance.CurrentStarSystem, Logger.LogType.Log); + if (Main.Instance.CurrentStarSystem != "SolarSystem") + { + __instance._shipLogXmlAssets = new TextAsset[] {}; + foreach (ShipLogEntryLocation logEntryLocation in GameObject.FindObjectsOfType()) + { + logEntryLocation._initialized = true; + } + } + foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem]) + { + if (body.Config.ShipLog?.curiosities != null) + { + ShipLogBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities); + } + } + foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem]) + { + if (body.Config.ShipLog?.xmlFile != null) + { + ShipLogBuilder.AddAstroBodyToShipLog(__instance, body); + } + } + } + + public static void OnShipLogManagerAwakeComplete(ShipLogManager __instance) + { + ShipLogBuilder.GenerateEntryData(__instance); + for (var i = 0; i < __instance._entryList.Count; i++) + { + ShipLogEntry logEntry = __instance._entryList[i]; + ShipLogBuilder.UpdateEntryCuriosity(ref logEntry); + } + Logger.Log("Ship Log Generation Complete For: " + Main.Instance.CurrentStarSystem, Logger.LogType.Log); + } + + public static bool OnShipLogManagerIsFactRevealed(ShipLogManager __instance, ref bool __result, string __0) + { + if (Main.Instance.CurrentStarSystem == "SolarSystem") + { + return true; + } + else + { + if (__instance._factDict.ContainsKey(__0) == false) + { + __result = false; + return false; + } + else + { + return true; + } + } + } + + public static bool OnShipLogManagerCheckForCompletionAchievement() + { + return Main.Instance.CurrentStarSystem == "SolarSystem"; + } + + public static bool OnShipLogManagerRevealFact(string __0) + { + if (Main.Instance.CurrentStarSystem != "SolarSystem" && __0 == "TH_VILLAGE_X1") + { + return false; + } + + return true; + } + + public static bool OnUIStyleManagerGetCuriosityColor(UIStyleManager __instance, CuriosityName __0, bool __1, ref Color __result) + { + if (Main.Instance.CurrentStarSystem == "SolarSystem") + { + return true; + } + else + { + __result = ShipLogBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight); + return false; + } + } + + private static void DeleteDetail(string name) + { + Object.Destroy(GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH + "/" + name)); + } + + public static void OnShipLogMapModeInitialize(ShipLogMapMode __instance) + { + + } + + public static void OnShipLogMapModeInitializeComplete(ShipLogMapMode __instance) + { + if (Main.Instance.CurrentStarSystem != "SolarSystem") + { + GameObject panRoot = GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH); + GameObject sunObject = GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH + "/Sun"); + ShipLogAstroObject[][] navMatrix = ShipLogBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, sunObject.layer); + if (navMatrix.Length <= 1) + { + Logger.LogWarning("No planets suitable for map mode found! Defaulting to vanilla menu (expect weirdness!)."); + } + else + { + __instance._astroObjects = navMatrix; + __instance._startingAstroObjectID = navMatrix[1][0].GetID(); + List delete = SearchUtilities.GetAllChildren(panRoot).Where(g => g.name.Contains("_ShipLog") == false).ToList(); + foreach (GameObject gameObject in delete) + { + DeleteDetail(gameObject.name); + } + + __instance._sandFunnel = __instance.gameObject.AddComponent(); + } + } + Logger.Log("Map Mode Construction Complete", Logger.LogType.Log); + } + + public static bool OnShipLogAstroObjectGetName(ShipLogAstroObject __instance, ref string __result) + { + if (Main.Instance.CurrentStarSystem == "SolarSystem") + { + return true; + } + else + { + __result = ShipLogBuilder.GetAstroBodyShipLogName(__instance.GetID()); + return false; + } + } + + public static bool DisableShipLogSandFunnel() + { + return Main.Instance.CurrentStarSystem == "SolarSystem"; + } + + public static void OnPlayerDataGetNewlyRevealedFactIDsComplete(ref List __result) + { + ShipLogManager manager = Locator.GetShipLogManager(); + __result = __result.Where(e => manager.GetFact(e) != null).ToList(); + } + # endregion public static void OnShipLogMapModeEnterMode(ShipLogMapMode __instance) { diff --git a/NewHorizons/Utility/MVector2.cs b/NewHorizons/Utility/MVector2.cs new file mode 100644 index 00000000..4d6ccf84 --- /dev/null +++ b/NewHorizons/Utility/MVector2.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace NewHorizons.Utility +{ + public class MVector2 + { + public MVector2(float x, float y) + { + X = x; + Y = y; + } + + public float X { get; } + public float Y { get; } + + public static implicit operator MVector2(Vector2 vec) + { + return new MVector2(vec.x, vec.y); + } + + public static implicit operator Vector2(MVector2 vec) + { + return new Vector2(vec.X, vec.Y); + } + } +} \ No newline at end of file diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs index 7eee7333..901851b2 100644 --- a/NewHorizons/Utility/SearchUtilities.cs +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -72,5 +72,15 @@ namespace NewHorizons.Utility return null; } + + public static List GetAllChildren(GameObject parent) + { + List children = new List(); + foreach (Transform child in parent.transform) + { + children.Add(child.gameObject); + } + return children; + } } } From 1673de69acb7c8efd090aad4bae3bff739113a58 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 5 Feb 2022 19:32:32 -0500 Subject: [PATCH 2/6] Added XML Schemas - Improved Map mode - Added XML Schemas for Dialogue and Ship Log - Added New Properties to JSON Schema - Added Reveal Props --- NewHorizons/Builder/General/ShipLogBuilder.cs | 828 ++++++++++-------- NewHorizons/Builder/Props/PropBuildManager.cs | 15 + NewHorizons/Builder/Props/SignalBuilder.cs | 1 + NewHorizons/External/PropModule.cs | 19 + NewHorizons/External/ShipLogModule.cs | 5 +- NewHorizons/External/SignalModule.cs | 1 + NewHorizons/Tools/Patches.cs | 51 +- NewHorizons/dialogue_schema.xsd | 39 + NewHorizons/schema.json | 246 +++++- NewHorizons/shiplog_schema.xsd | 38 + 10 files changed, 869 insertions(+), 374 deletions(-) create mode 100644 NewHorizons/dialogue_schema.xsd create mode 100644 NewHorizons/shiplog_schema.xsd diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs index 2fceed15..ac764a21 100644 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ b/NewHorizons/Builder/General/ShipLogBuilder.cs @@ -21,417 +21,549 @@ namespace NewHorizons.Builder.General public static readonly string PAN_ROOT_PATH = "Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot"; public static ShipLogStarChartMode ShipLogStarChartMode; - private static Dictionary curiosityColors = new Dictionary(); - private static Dictionary curiosityHighlightColors = new Dictionary(); - private static Dictionary rawNameToCuriosityName = new Dictionary(); - private static Dictionary entryIdToRawName = new Dictionary(); private static Dictionary astroIdToBody = new Dictionary(); - - private class MapModeObject - { - public int x; - public int y; - public int branch_width; - public int branch_height; - public int level; - public NewHorizonsBody mainBody; - public ShipLogAstroObject astroObject; - public List children; - public MapModeObject parent; - public void increment_width() - { - branch_width++; - parent?.increment_width(); - } - public void increment_height() - { - branch_height++; - parent?.increment_height(); - } - } - - public static string GetAstroBodyShipLogName(string id) - { - return astroIdToBody[id].Config.Name; - } - - public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer) - { - MapModeObject rootObject = MakePrimaryNode(systemName); - if (rootObject.mainBody != null) - { - CreateAllNodes(ref rootObject, transformParent, layer); - } - - const int maxAmount = 20; - ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; - for (int i = 0; i < maxAmount; i++) - { - navMatrix[i] = new ShipLogAstroObject[maxAmount]; - } - CreateNavigationMatrix(rootObject, ref navMatrix); - navMatrix = navMatrix.Where(a => a.Count(c => c != null) > 0).Prepend(new ShipLogAstroObject[1]).ToArray(); - for (var index = 0; index < navMatrix.Length; index++) - { - navMatrix[index] = navMatrix[index].Where(a => a != null).ToArray(); - } - return navMatrix; - } - - private static void CreateNavigationMatrix(MapModeObject root, ref ShipLogAstroObject[][] navMatrix) - { - if (root.astroObject != null) - { - navMatrix[root.y][root.x] = root.astroObject; - } - foreach (MapModeObject child in root.children) - { - CreateNavigationMatrix(child, ref navMatrix); - } - } - - private static void CreateAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) - { - CreateNode(ref parentNode, parent, layer); - for (var i = 0; i < parentNode.children.Count; i++) - { - MapModeObject child = parentNode.children[i]; - CreateAllNodes(ref child, parent, layer); - parentNode.children[i] = child; - } - } - - private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, string imagePath, string name, int layer) - { - GameObject newImageGO = new GameObject(name); - newImageGO.layer = layer; - newImageGO.transform.SetParent(nodeGO.transform); - - RectTransform transform = newImageGO.AddComponent(); - transform.localPosition = Vector3.zero; - transform.localRotation = Quaternion.identity; - transform.localScale = Vector3.one; - - Image newImage = newImageGO.AddComponent(); - if (imagePath == "DEFAULT") - { - newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; - } - else - { - Texture2D newTexture = assets.GetTexture(imagePath); - Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); - Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); - newImage.sprite = Sprite.Create(newTexture, rect, pivot); - } - return newImageGO; - } - public static T KeyByValue(this Dictionary dict, W val) + private static NewHorizonsBody GetConfigFromEntry(ShipLogEntry entry) { - T key = default; - foreach (KeyValuePair pair in dict) + return astroIdToBody[entry._astroObjectID]; + } + + #region Map Mode + + public class MapModeBuilder + { + private class MapModeObject { - if (EqualityComparer.Default.Equals(pair.Value, val)) + public int x; + public int y; + public int branch_width; + public int branch_height; + public int level; + public NewHorizonsBody mainBody; + public ShipLogAstroObject astroObject; + public List children; + public MapModeObject parent; + public MapModeObject lastSibling; + public void increment_width() { - key = pair.Key; - break; + branch_width++; + parent?.increment_width(); + } + public void increment_height() + { + branch_height++; + parent?.increment_height(); } } - return key; - } - private static string GetAstroObjectId(NewHorizonsBody body) - { - return KeyByValue(astroIdToBody, body); - } - - private static void CreateAstroObject(GameObject nodeGO, ref MapModeObject node, GameObject referenceUnviewedSprite, int layer) - { - const float unviewedIconOffset = 15; - ShipLogAstroObject astroObject = nodeGO.AddComponent(); - astroObject._id = GetAstroObjectId(node.mainBody); - string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; - string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; - astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, "Image", layer); - astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, "Outline", layer); - astroObject._unviewedObj = GameObject.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); - astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; - Rect imageRect = astroObject._imageObj.GetComponent().rect; - astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); - node.astroObject = astroObject; - } - - private static void CreateNode(ref MapModeObject node, GameObject parent, int layer) - { - const float padding = 250f; - - GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog"); - newNodeGO.layer = layer; - newNodeGO.transform.SetParent(parent.transform); - - RectTransform transform = newNodeGO.AddComponent(); - float scale = node.mainBody.Config.ShipLog?.mapMode?.scale?? 1f; - scale = scale <= 0 ? 1f : scale; - transform.localPosition = new Vector3(node.x * padding, node.y * padding, 0); - transform.localRotation = Quaternion.identity; - transform.localScale = Vector3.one * scale; - - if (node.mainBody.Config.ShipLog?.xmlFile == null) + public static string GetAstroBodyShipLogName(string id) { - Image newImage = newNodeGO.AddComponent(); - string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; + if (astroIdToBody.ContainsKey(id)) + { + return astroIdToBody[id].Config.Name; + } + else + { + return id; + } + } + + public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer) + { + MapModeObject rootObject = MakePrimaryNode(systemName); + if (rootObject.mainBody != null) + { + CreateAllNodes(ref rootObject, transformParent, layer); + } + + const int maxAmount = 20; + ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; + for (int i = 0; i < maxAmount; i++) + { + navMatrix[i] = new ShipLogAstroObject[maxAmount]; + } + + CreateNavigationMatrix(rootObject, ref navMatrix); + navMatrix = navMatrix.Where(a => a.Count(c => c != null) > 0).Prepend(new ShipLogAstroObject[1]).ToArray(); + for (var index = 0; index < navMatrix.Length; index++) + { + navMatrix[index] = navMatrix[index].Where(a => a != null).ToArray(); + } + return navMatrix; + } + + private static void CreateNavigationMatrix(MapModeObject root, ref ShipLogAstroObject[][] navMatrix) + { + if (root.astroObject != null) + { + navMatrix[root.y][root.x] = root.astroObject; + } + foreach (MapModeObject child in root.children) + { + CreateNavigationMatrix(child, ref navMatrix); + } + } + + private static void CreateAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) + { + CreateNode(ref parentNode, parent, layer); + for (var i = 0; i < parentNode.children.Count; i++) + { + MapModeObject child = parentNode.children[i]; + CreateAllNodes(ref child, parent, layer); + parentNode.children[i] = child; + } + } + + private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, string imagePath, string name, int layer) + { + GameObject newImageGO = new GameObject(name); + newImageGO.layer = layer; + newImageGO.transform.SetParent(nodeGO.transform); + + RectTransform transform = newImageGO.AddComponent(); + transform.localPosition = Vector3.zero; + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one; + + Image newImage = newImageGO.AddComponent(); if (imagePath == "DEFAULT") { newImage.sprite = Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; } else { - Texture2D newTexture = node.mainBody.Mod.Assets.GetTexture(imagePath); + Texture2D newTexture = assets.GetTexture(imagePath); Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); newImage.sprite = Sprite.Create(newTexture, rect, pivot); } + return newImageGO; } - else + + public static T KeyByValue(Dictionary dict, W val) { - CreateAstroObject(newNodeGO, ref node, GameObject.Find(PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"), layer); - } - } - - private static MapModeObject MakePrimaryNode(string systemName) - { - foreach (NewHorizonsBody body in Main.BodyDict[systemName]) - { - if (!body.Config.Base.CenterOfSolarSystem) continue; - MapModeObject newNode = new MapModeObject + T key = default; + foreach (KeyValuePair pair in dict) { - mainBody = body, - level = 0, - x = 0, - y = 0 - }; - newNode.children = MakeChildrenNodes(systemName, newNode); - return newNode; + if (EqualityComparer.Default.Equals(pair.Value, val)) + { + key = pair.Key; + break; + } + } + return key; } - Logger.LogError("Couldn't find center of system!"); - return new MapModeObject(); - } - private static List MakeChildrenNodes(string systemName, MapModeObject parent) - { - List children = new List(); - int newX = parent.x; - int newY = parent.y; - foreach (NewHorizonsBody body in Main.BodyDict[systemName]) + private static string GetAstroObjectId(NewHorizonsBody body) { - if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) + if (astroIdToBody.ContainsValue(body)) { - int newLevel = parent.level + 1; - bool even = newLevel % 2 == 0; - newX = even ? newX : newX + 1; - newY = even ? newY + 1 : newY; - MapModeObject newNode = new MapModeObject() + return KeyByValue(astroIdToBody, body); + } + else + { + return body.Config.Name; + } + } + + private static void CreateShipLogAstroObject(GameObject nodeGO, ref MapModeObject node, GameObject referenceUnviewedSprite, int layer) + { + const float unviewedIconOffset = 15; + ShipLogAstroObject astroObject = nodeGO.AddComponent(); + astroObject._id = GetAstroObjectId(node.mainBody); + string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; + string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; + astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, "Image", layer); + astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, "Outline", layer); + astroObject._unviewedObj = GameObject.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); + astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; + Rect imageRect = astroObject._imageObj.GetComponent().rect; + astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); + node.astroObject = astroObject; + } + + private static void ConnectNodes(MapModeObject from, MapModeObject to) + { + + } + + private static void CreateNode(ref MapModeObject node, GameObject parent, int layer) + { + const float padding = 250f; + + GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog"); + newNodeGO.layer = layer; + newNodeGO.transform.SetParent(parent.transform); + + RectTransform transform = newNodeGO.AddComponent(); + float scale = node.mainBody.Config.ShipLog?.mapMode?.scale?? 1f; + Vector2 position = Vector2.zero; + if (node.lastSibling != null) + { + ShipLogAstroObject lastAstroObject = node.lastSibling.astroObject; + Vector3 lastPosition = lastAstroObject.transform.localPosition; + position = lastPosition; + float extraDistance = (node.mainBody.Config.ShipLog?.mapMode?.offset ?? 0f) * 100; + if (node.level % 2 == 0) + { + position.y += padding * (node.y - node.lastSibling.y) + extraDistance; + } + else + { + position.x += padding * (node.x - node.lastSibling.x) + extraDistance; + } + } + transform.localPosition = new Vector3(position.x, position.y, 0); + transform.localRotation = Quaternion.identity; + transform.localScale = Vector3.one * scale; + CreateShipLogAstroObject(newNodeGO, ref node, GameObject.Find(PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"), layer); + } + + private static MapModeObject MakePrimaryNode(string systemName) + { + foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.Base.CenterOfSolarSystem)) + { + MapModeObject newNode = new MapModeObject { mainBody = body, - level = newLevel, - x = newX, - y = newY, - parent=parent + level = 0, + x = 0, + y = 0 }; newNode.children = MakeChildrenNodes(systemName, newNode); - if (even) - { - newY += newNode.branch_height; - parent.increment_height(); - } - else - { - newX += newNode.branch_width; - parent.increment_width(); - } - children.Add(newNode); + return newNode; } + Logger.LogError("Couldn't find center of system!"); + return new MapModeObject(); } - return children; - } - public static void AddCuriosityColors(ShipLogModule.CuriosityColor[] newColors) - { - foreach (ShipLogModule.CuriosityColor newColor in newColors) + private static List MakeChildrenNodes(string systemName, MapModeObject parent) { - if (rawNameToCuriosityName.ContainsKey(newColor.id) == false) + List children = new List(); + int newX = parent.x; + int newY = parent.y; + int newLevel = parent.level + 1; + MapModeObject lastSibling = parent; + foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.ShipLog?.mapMode?.remove == false && b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name)) { - CuriosityName newName = (CuriosityName) 8 + rawNameToCuriosityName.Count; - rawNameToCuriosityName.Add(newColor.id, newName); - curiosityColors.Add(newName, newColor.color.ToColor()); - curiosityHighlightColors.Add(newName, newColor.highlightColor.ToColor()); + if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) + { + bool even = newLevel % 2 == 0; + newX = even ? newX : newX + 1; + newY = even ? newY + 1 : newY; + MapModeObject newNode = new MapModeObject() + { + mainBody = body, + level = newLevel, + x = newX, + y = newY, + parent = parent, + lastSibling = lastSibling + }; + newNode.children = MakeChildrenNodes(systemName, newNode); + if (even) + { + newY += newNode.branch_height; + parent.increment_height(); + } + else + { + newX += newNode.branch_width; + parent.increment_width(); + } + lastSibling = newNode; + children.Add(newNode); + } } + return children; } } + #endregion - public static Color GetCuriosityColor(CuriosityName curiosityName, bool highlighted, Color defaultColor, Color defaultHighlight) + #region Rumor Mode + public static class RumorModeBuilder { - if (curiosityColors.ContainsKey(curiosityName) && curiosityHighlightColors.ContainsKey(curiosityName)) - { - return (highlighted ? curiosityHighlightColors : curiosityColors)[curiosityName]; - } - else - { - return highlighted? defaultHighlight : defaultColor; - } - } + private static Dictionary curiosityColors = new Dictionary(); + private static Dictionary curiosityHighlightColors = new Dictionary(); + private static Dictionary rawNameToCuriosityName = new Dictionary(); + private static Dictionary entryIdToRawName = new Dictionary(); - public static void AddAstroBodyToShipLog(ShipLogManager manager, NewHorizonsBody body) - { - string systemName = body.Config.StarSystem; - XElement astroBodyFile = XElement.Load(Main.Instance.ModHelper.Manifest.ModFolderPath + body.Config.ShipLog.xmlFile); - XElement astroBodyId = astroBodyFile.Element("ID"); - if (astroBodyId == null) + public static void AddCuriosityColors(ShipLogModule.CuriosityColor[] newColors) { - Logger.LogError("Failed to load ship log for " + systemName + "!"); - } - else - { - astroBodyId.SetValue(systemName + "/" + astroBodyId.Value); - foreach (XElement entryElement in astroBodyFile.DescendantsAndSelf("Entry")) + foreach (ShipLogModule.CuriosityColor newColor in newColors) { - XElement curiosityName = entryElement.Element("Curiosity"); - XElement id = entryElement.Element("ID"); - if (curiosityName != null && id != null && entryIdToRawName.ContainsKey(id.Value) == false) + if (rawNameToCuriosityName.ContainsKey(newColor.id) == false) { - entryIdToRawName.Add(id.Value, curiosityName.Value); + CuriosityName newName = (CuriosityName) 8 + rawNameToCuriosityName.Count; + rawNameToCuriosityName.Add(newColor.id, newName); + curiosityColors.Add(newName, newColor.color.ToColor()); + curiosityHighlightColors.Add(newName, newColor.highlightColor.ToColor()); } - AddTranslation(entryElement); } - TextAsset newAsset = new TextAsset(astroBodyFile.ToString()); - List newBodies = new List(manager._shipLogXmlAssets) {newAsset}; - manager._shipLogXmlAssets = newBodies.ToArray(); - if (astroIdToBody.ContainsKey(astroBodyId.Value) == false) + } + + public static Color GetCuriosityColor(CuriosityName curiosityName, bool highlighted, Color defaultColor, Color defaultHighlight) + { + if (curiosityColors.ContainsKey(curiosityName) && curiosityHighlightColors.ContainsKey(curiosityName)) { - astroIdToBody.Add(astroBodyId.Value, body); + return (highlighted ? curiosityHighlightColors : curiosityColors)[curiosityName]; } - } - } - - private static void AddTranslation(XElement entry) - { - Dictionary table = TextTranslation.Get().m_table.theShipLogTable; - XElement nameElement = entry.Element("Name"); - if (nameElement != null) - { - string name = nameElement.Value; - table[name] = name; - foreach (XElement rumorFact in entry.Elements("RumorFact")) + else { - XElement rumorName = rumorFact.Element("RumorName"); - if (rumorName != null) - { - table[rumorName.Value] = rumorName.Value; - } - - XElement rumorText = rumorFact.Element("Text"); - if (rumorText != null) - { - table[name + rumorText.Value] = rumorText.Value; - } + return highlighted? defaultHighlight : defaultColor; } - foreach (XElement exploreFact in entry.Elements("ExploreFact")) + } + + public static void AddBodyToShipLog(ShipLogManager manager, NewHorizonsBody body) + { + string systemName = body.Config.StarSystem; + XElement astroBodyFile = XElement.Load(Main.Instance.ModHelper.Manifest.ModFolderPath + body.Config.ShipLog.xmlFile); + XElement astroBodyId = astroBodyFile.Element("ID"); + if (astroBodyId == null) { - XElement exploreText = exploreFact.Element("Text"); - if (exploreText != null) - { - table[name + exploreText.Value] = exploreText.Value; - } + Logger.LogError("Failed to load ship logs for " + systemName + "!"); } - } - } - - public static void UpdateEntryCuriosity(ref ShipLogEntry entry) - { - if (entryIdToRawName.ContainsKey(entry._id)) - { - entry._curiosity = rawNameToCuriosityName[entryIdToRawName[entry._id]]; - } - } - - private static Sprite GetSprite(string entryId, NewHorizonsBody body) - { - IModAssets assets = body.Mod.Assets; - string path = body.Config.ShipLog.spriteFolder + "/" + entryId + ".png"; - if (File.Exists(Main.Instance.ModHelper.Manifest.ModFolderPath + path)) - { - Texture2D newTexture = assets.GetTexture(path); - Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); - Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); - return Sprite.Create(newTexture, rect, pivot); - } - else - { - return Locator.GetShipLogManager()._shipLogLibrary.defaultEntrySprite; - } - } - - private static NewHorizonsBody GetConfigFromEntry(ShipLogEntry entry) - { - return astroIdToBody[entry._astroObjectID]; - } - - private static Vector2? FindPosition(string entryId, ShipLogModule config) - { - if (config.positions == null) return null; - foreach (ShipLogModule.EntryPosition position in config.positions) - { - if (position.id == entryId) + else { - return position.position; + astroBodyId.SetValue(systemName + "/" + astroBodyId.Value); + foreach (XElement entryElement in astroBodyFile.DescendantsAndSelf("Entry")) + { + XElement curiosityName = entryElement.Element("Curiosity"); + XElement id = entryElement.Element("ID"); + if (curiosityName != null && id != null && entryIdToRawName.ContainsKey(id.Value) == false) + { + entryIdToRawName.Add(id.Value, curiosityName.Value); + } + AddTranslation(entryElement); + } + TextAsset newAsset = new TextAsset(astroBodyFile.ToString()); + List newBodies = new List(manager._shipLogXmlAssets) {newAsset}; + manager._shipLogXmlAssets = newBodies.ToArray(); + if (astroIdToBody.ContainsKey(astroBodyId.Value) == false) + { + astroIdToBody.Add(astroBodyId.Value, body); + } } } - return null; - } - public static void GenerateEntryData(ShipLogManager manager) - { - const int step = 400; - int colAccumulator = 0; - int rowAccumulator = 0; - foreach(ShipLogEntry entry in manager._entryList) + public static void GenerateEntryData(ShipLogManager manager) { - if (manager._entryDataDict.ContainsKey(entry._id) == false) + const int step = 400; + int colAccumulator = 0; + int rowAccumulator = 0; + foreach(ShipLogEntry entry in manager._entryList) { - NewHorizonsBody body = GetConfigFromEntry(entry); - Vector2? manualEntryPosition = FindPosition(entry._id, body.Config.ShipLog); - Vector2 entryPosition; - if (manualEntryPosition == null) + if (manager._entryDataDict.ContainsKey(entry._id) == false) { - entryPosition = new Vector2(colAccumulator, rowAccumulator); - } - else - { - entryPosition = (Vector2) manualEntryPosition; - } - EntryData newData = new EntryData - { - id = entry._id, - cardPosition = entryPosition, - sprite = body.Config.ShipLog.spriteFolder == null? null : GetSprite(entry._id, body) - }; - entry.SetSprite(newData.sprite == null? manager._shipLogLibrary.defaultEntrySprite : newData.sprite); - manager._entryDataDict.Add(entry._id, newData); - int index = manager._entryList.IndexOf(entry); - if (index < manager._entryList.Count - 2 && manager._entryList[index + 1]._astroObjectID != entry._astroObjectID) - { - rowAccumulator += step; - colAccumulator = 0; - } - else - { - colAccumulator += step; + NewHorizonsBody body = GetConfigFromEntry(entry); + Vector2? manualEntryPosition = GetManualEntryPosition(entry._id, body.Config.ShipLog); + Vector2 entryPosition; + if (manualEntryPosition == null) + { + entryPosition = new Vector2(colAccumulator, rowAccumulator); + } + else + { + entryPosition = (Vector2) manualEntryPosition; + } + EntryData newData = new EntryData + { + id = entry._id, + cardPosition = entryPosition, + sprite = body.Config.ShipLog.spriteFolder == null? null : GetEntrySprite(entry._id, body) + }; + entry.SetSprite(newData.sprite == null? manager._shipLogLibrary.defaultEntrySprite : newData.sprite); + manager._entryDataDict.Add(entry._id, newData); + int index = manager._entryList.IndexOf(entry); + if (index < manager._entryList.Count - 2 && manager._entryList[index + 1]._astroObjectID != entry._astroObjectID) + { + rowAccumulator += step; + colAccumulator = 0; + } + else + { + colAccumulator += step; + } } } } - } + private static void AddTranslation(XElement entry) + { + Dictionary table = TextTranslation.Get().m_table.theShipLogTable; + XElement nameElement = entry.Element("Name"); + if (nameElement != null) + { + string name = nameElement.Value; + table[name] = name; + foreach (XElement rumorFact in entry.Elements("RumorFact")) + { + XElement rumorName = rumorFact.Element("RumorName"); + if (rumorName != null) + { + table[rumorName.Value] = rumorName.Value; + } + + XElement rumorText = rumorFact.Element("Text"); + if (rumorText != null) + { + table[name + rumorText.Value] = rumorText.Value; + } + } + foreach (XElement exploreFact in entry.Elements("ExploreFact")) + { + XElement exploreText = exploreFact.Element("Text"); + if (exploreText != null) + { + table[name + exploreText.Value] = exploreText.Value; + } + } + } + } + + public static void UpdateEntryCuriosity(ref ShipLogEntry entry) + { + if (entryIdToRawName.ContainsKey(entry._id)) + { + entry._curiosity = rawNameToCuriosityName[entryIdToRawName[entry._id]]; + } + } + + private static Sprite GetEntrySprite(string entryId, NewHorizonsBody body) + { + IModAssets assets = body.Mod.Assets; + string path = body.Config.ShipLog.spriteFolder + "/" + entryId + ".png"; + if (File.Exists(Main.Instance.ModHelper.Manifest.ModFolderPath + path)) + { + Texture2D newTexture = assets.GetTexture(path); + Rect rect = new Rect(0, 0, newTexture.width, newTexture.height); + Vector2 pivot = new Vector2(newTexture.width / 2, newTexture.height / 2); + return Sprite.Create(newTexture, rect, pivot); + } + else + { + return null; + } + } + + private static Vector2? GetManualEntryPosition(string entryId, ShipLogModule config) + { + if (config.positions == null) return null; + foreach (ShipLogModule.EntryPosition position in config.positions) + { + if (position.id == entryId) + { + return position.position; + } + } + return null; + } + } + #endregion + + #region Fact Reveals + public static class RevealBuilder + { + public static void Make(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + GameObject newRevealGO = MakeGameObject(go, sector, info, mod); + switch (info.revealOn.ToLower()) + { + case "enter": + MakeTrigger(newRevealGO, sector, info, mod); + break; + case "observe": + MakeObservable(newRevealGO, sector, info, mod); + break; + case "snapshot": + MakeSnapshot(newRevealGO, sector, info, mod); + break; + default: + Logger.LogError("Invalid revealOn: " + info.revealOn); + break; + } + + newRevealGO.SetActive(true); + } + + private static SphereShape MakeShape(GameObject go, PropModule.RevealInfo info, Shape.CollisionMode collisionMode) + { + SphereShape newShape = go.AddComponent(); + newShape.radius = info.radius; + newShape.SetCollisionMode(collisionMode); + return newShape; + } + + private static GameObject MakeGameObject(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + GameObject revealTriggerVolume = new GameObject("Reveal Volume (" + info.revealOn + ")"); + revealTriggerVolume.SetActive(false); + revealTriggerVolume.transform.parent = sector?.transform ?? go.transform; + revealTriggerVolume.transform.localPosition = info.position; + return revealTriggerVolume; + } + + private static void MakeTrigger(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + SphereShape newShape = MakeShape(go, info, Shape.CollisionMode.Volume); + OWTriggerVolume newVolume = go.AddComponent(); + newVolume._shape = newShape; + ShipLogFactListTriggerVolume volume = go.AddComponent(); + volume._factIDs = info.reveals; + } + + private static void MakeObservable(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + go.layer = LayerMask.NameToLayer("Interactible"); + SphereCollider newSphere = go.AddComponent(); + newSphere.radius = info.radius; + OWCollider newCollider = go.AddComponent(); + ShipLogFactObserveTrigger newObserveTrigger = go.AddComponent(); + newObserveTrigger._factIDs = info.reveals; + newObserveTrigger._maxViewDistance = info.maxDistance == -1f ? 2f : info.maxDistance; + newObserveTrigger._maxViewAngle = info.maxAngle; + newObserveTrigger._owCollider = newCollider; + newObserveTrigger._disableColliderOnRevealFact = true; + } + + private static void MakeSnapshot(GameObject go, Sector sector, PropModule.RevealInfo info, IModHelper mod) + { + SphereShape newShape = MakeShape(go, info, Shape.CollisionMode.Manual); + ShapeVisibilityTracker newTracker = go.AddComponent(); + newTracker._shapes = new Shape[] {newShape}; + ShipLogFactSnapshotTrigger newSnapshotTrigger = go.AddComponent(); + newSnapshotTrigger._maxDistance = info.maxDistance == -1f ? 200f : info.maxDistance; + newSnapshotTrigger._factIDs = info.reveals; + } + } + #endregion + + #region Entry Locations + public static class EntryLocationBuilder + { + private static List locationsToInitialize = new List(); + public static void Make(GameObject go, Sector sector, PropModule.EntryLocationInfo info, IModHelper mod) + { + GameObject entryLocationGameObject = new GameObject("Entry Location (" + info.id + ")"); + entryLocationGameObject.SetActive(false); + entryLocationGameObject.transform.parent = sector?.transform ?? go.transform; + entryLocationGameObject.transform.localPosition = info.position; + ShipLogEntryLocation newLocation = entryLocationGameObject.AddComponent(); + newLocation._entryID = info.id; + newLocation._isWithinCloakField = info.cloaked; + locationsToInitialize.Add(newLocation); + entryLocationGameObject.SetActive(true); + } + + public static void InitializeLocations() + { + locationsToInitialize.ForEach(l => l.InitEntry()); + locationsToInitialize.Clear(); + } + } + #endregion + public static void Init() { var shipLogRoot = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas"); diff --git a/NewHorizons/Builder/Props/PropBuildManager.cs b/NewHorizons/Builder/Props/PropBuildManager.cs index 281a2dd0..eadbfe7c 100644 --- a/NewHorizons/Builder/Props/PropBuildManager.cs +++ b/NewHorizons/Builder/Props/PropBuildManager.cs @@ -8,6 +8,7 @@ using UnityEngine; using Random = UnityEngine.Random; using Logger = NewHorizons.Utility.Logger; using System.Reflection; +using NewHorizons.Builder.General; using NewHorizons.Utility; using OWML.Common; @@ -53,6 +54,20 @@ namespace NewHorizons.Builder.Props DialogueBuilder.Make(go, sector, dialogueInfo, mod); } } + if (config.Props.Reveal != null) + { + foreach (var revealInfo in config.Props.Reveal) + { + ShipLogBuilder.RevealBuilder.Make(go, sector, revealInfo, mod); + } + } + if (config.Props.EntryLocation != null) + { + foreach (var entryLocationInfo in config.Props.EntryLocation) + { + ShipLogBuilder.EntryLocationBuilder.Make(go, sector, entryLocationInfo, mod); + } + } } public static GameObject LoadPrefab(string assetBundle, string path, string uniqueModName, IModAssets assets) diff --git a/NewHorizons/Builder/Props/SignalBuilder.cs b/NewHorizons/Builder/Props/SignalBuilder.cs index 96d7c3af..cc1a66e8 100644 --- a/NewHorizons/Builder/Props/SignalBuilder.cs +++ b/NewHorizons/Builder/Props/SignalBuilder.cs @@ -145,6 +145,7 @@ namespace NewHorizons.Builder.Props } audioSignal._name = name; audioSignal._sourceRadius = info.SourceRadius; + audioSignal._revealFactID = info.Reveals; audioSignal._onlyAudibleToScope = info.OnlyAudibleToScope; audioSignal._identificationDistance = info.IdentificationRadius; audioSignal._canBePickedUpByScope = true; diff --git a/NewHorizons/External/PropModule.cs b/NewHorizons/External/PropModule.cs index 02f66142..7364985b 100644 --- a/NewHorizons/External/PropModule.cs +++ b/NewHorizons/External/PropModule.cs @@ -15,6 +15,8 @@ namespace NewHorizons.External public GeyserInfo[] Geysers; public TornadoInfo[] Tornados; public DialogueInfo[] Dialogue; + public RevealInfo[] Reveal; + public EntryLocationInfo[] EntryLocation; public class ScatterInfo { @@ -68,5 +70,22 @@ namespace NewHorizons.External public MVector3 remoteTriggerPosition; public string persistentCondition; } + + public class RevealInfo + { + public string revealOn; + public string[] reveals; + public MVector3 position; + public float radius = 1f; + public float maxDistance = -1f; // Snapshot & Observe Only + public float maxAngle = 180f; // Observe Only + } + + public class EntryLocationInfo + { + public string id; + public bool cloaked; + public MVector3 position; + } } } diff --git a/NewHorizons/External/ShipLogModule.cs b/NewHorizons/External/ShipLogModule.cs index a805e303..b0d2ad53 100644 --- a/NewHorizons/External/ShipLogModule.cs +++ b/NewHorizons/External/ShipLogModule.cs @@ -9,13 +9,16 @@ namespace NewHorizons.External public MapMode mapMode; public CuriosityColor[] curiosities; public EntryPosition[] positions; + public string[] initialReveal; public class MapMode { public string revealedSprite; public string outlineSprite; - public float scale; + public float scale = 1f; public bool invisibleWhenHidden; + public float offset = 0f; + public bool remove = false; } public class CuriosityColor diff --git a/NewHorizons/External/SignalModule.cs b/NewHorizons/External/SignalModule.cs index 07a72252..906e3411 100644 --- a/NewHorizons/External/SignalModule.cs +++ b/NewHorizons/External/SignalModule.cs @@ -18,6 +18,7 @@ namespace NewHorizons.External public string Name; public string AudioClip = null; public string AudioFilePath = null; + public string Reveals = ""; public float SourceRadius = 1f; public float DetectionRadius = 0f; public float IdentificationRadius = 10f; diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index fdf97dae..f10c14ab 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -60,14 +60,12 @@ namespace NewHorizons.Tools Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.OnShipLogManagerAwake)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Start", typeof(Patches), nameof(Patches.OnShipLogManagerStart)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("IsFactRevealed", typeof(Patches), nameof(Patches.OnShipLogManagerIsFactRevealed)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("CheckForCompletionAchievement", typeof(Patches), nameof(Patches.OnShipLogManagerCheckForCompletionAchievement)); - Main.Instance.ModHelper.HarmonyHelper.AddPrefix("RevealFact", typeof(Patches), nameof(Patches.OnShipLogManagerRevealFact)); - + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("GetCuriosityColor", typeof(Patches), nameof(Patches.OnUIStyleManagerGetCuriosityColor)); - - Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Initialize", typeof(Patches), nameof(Patches.OnShipLogMapModeInitialize)); - + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Awake", typeof(Patches), nameof(Patches.DisableShipLogSandFunnel)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("UpdateState", typeof(Patches), nameof(Patches.DisableShipLogSandFunnel)); @@ -81,7 +79,7 @@ namespace NewHorizons.Tools Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnShipLogManagerAwakeComplete)); - Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Initialize", typeof(Patches), nameof(Patches.OnShipLogMapModeInitializeComplete)); + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Initialize", typeof(Patches), nameof(Patches.OnShipLogMapModeInitialize)); } public static bool GetHUDDisplayName(ReferenceFrame __instance, ref string __result) @@ -333,7 +331,7 @@ namespace NewHorizons.Tools } return true; } - + public static void OnPlayerDataResetGame() { NewHorizonsData.Reset(); @@ -408,25 +406,25 @@ namespace NewHorizons.Tools { if (body.Config.ShipLog?.curiosities != null) { - ShipLogBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities); + ShipLogBuilder.RumorModeBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities); } } foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem]) { if (body.Config.ShipLog?.xmlFile != null) { - ShipLogBuilder.AddAstroBodyToShipLog(__instance, body); + ShipLogBuilder.RumorModeBuilder.AddBodyToShipLog(__instance, body); } } } public static void OnShipLogManagerAwakeComplete(ShipLogManager __instance) { - ShipLogBuilder.GenerateEntryData(__instance); + ShipLogBuilder.RumorModeBuilder.GenerateEntryData(__instance); for (var i = 0; i < __instance._entryList.Count; i++) { ShipLogEntry logEntry = __instance._entryList[i]; - ShipLogBuilder.UpdateEntryCuriosity(ref logEntry); + ShipLogBuilder.RumorModeBuilder.UpdateEntryCuriosity(ref logEntry); } Logger.Log("Ship Log Generation Complete For: " + Main.Instance.CurrentStarSystem, Logger.LogType.Log); } @@ -456,14 +454,24 @@ namespace NewHorizons.Tools return Main.Instance.CurrentStarSystem == "SolarSystem"; } - public static bool OnShipLogManagerRevealFact(string __0) + public static bool OnShipLogManagerStart(ShipLogManager __instance) { - if (Main.Instance.CurrentStarSystem != "SolarSystem" && __0 == "TH_VILLAGE_X1") + if (Main.Instance.CurrentStarSystem == "SolarSystem") { + return true; + } + else + { + foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem]) + { + foreach (string fact in body.Config.ShipLog?.initialReveal ?? Array.Empty()) + { + __instance.RevealFact(fact, false, false); + } + } + ShipLogBuilder.EntryLocationBuilder.InitializeLocations(); return false; } - - return true; } public static bool OnUIStyleManagerGetCuriosityColor(UIStyleManager __instance, CuriosityName __0, bool __1, ref Color __result) @@ -474,7 +482,7 @@ namespace NewHorizons.Tools } else { - __result = ShipLogBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight); + __result = ShipLogBuilder.RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight); return false; } } @@ -485,17 +493,12 @@ namespace NewHorizons.Tools } public static void OnShipLogMapModeInitialize(ShipLogMapMode __instance) - { - - } - - public static void OnShipLogMapModeInitializeComplete(ShipLogMapMode __instance) { if (Main.Instance.CurrentStarSystem != "SolarSystem") { GameObject panRoot = GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH); GameObject sunObject = GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH + "/Sun"); - ShipLogAstroObject[][] navMatrix = ShipLogBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, sunObject.layer); + ShipLogAstroObject[][] navMatrix = ShipLogBuilder.MapModeBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, sunObject.layer); if (navMatrix.Length <= 1) { Logger.LogWarning("No planets suitable for map mode found! Defaulting to vanilla menu (expect weirdness!)."); @@ -509,7 +512,7 @@ namespace NewHorizons.Tools { DeleteDetail(gameObject.name); } - + // Just Lie About Having A Sand Funnel __instance._sandFunnel = __instance.gameObject.AddComponent(); } } @@ -524,7 +527,7 @@ namespace NewHorizons.Tools } else { - __result = ShipLogBuilder.GetAstroBodyShipLogName(__instance.GetID()); + __result = ShipLogBuilder.MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID()); return false; } } diff --git a/NewHorizons/dialogue_schema.xsd b/NewHorizons/dialogue_schema.xsd new file mode 100644 index 00000000..e8c70424 --- /dev/null +++ b/NewHorizons/dialogue_schema.xsd @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/NewHorizons/schema.json b/NewHorizons/schema.json index 2b005b04..85a03c54 100644 --- a/NewHorizons/schema.json +++ b/NewHorizons/schema.json @@ -669,7 +669,7 @@ "generateColliders": { "type": "bool", "default": false, - "description": "For each mesh filter found here should we make a mesh collider?" + "description": "For each mesh filter found here should we make a mesh collider?" } } } @@ -791,6 +791,94 @@ } } } + }, + "reveal": { + "type": "array", + "description": "A set of volumes that reveal ship log fact", + "items": { + "type": "object", + "properties": { + "revealOn": { + "type": "string", + "description": "'enter', 'observe', or 'snapshot' what needs to be done to the volume to unlock the facts" + }, + "reveals": { + "type": "array", + "description": "A list of facts to reveal", + "items": { + "type": "string" + } + }, + "position": { + "type": "object", + "description": "The position to place the volume at", + "properties": { + "x": { + "type": "number", + "default": 0 + }, + "y": { + "type": "number", + "default": 0 + }, + "z": { + "type": "number", + "default": 0 + } + } + }, + "radius": { + "type": "number", + "description": "The radius of the volume", + "default": 1.0 + }, + "maxDistance": { + "type": "number", + "description": "The max distance the user can be away from the volume to reveal the fact (snapshot and observe only)" + }, + "maxAngle": { + "type": "number", + "description": "The max view angle the player can see the volume with to unlock the fact", + "default": 180.0 + } + } + } + }, + "entryLocation": { + "type": "array", + "description": "A set of locations for ship log entries", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the entry this location is for" + }, + "cloaked": { + "type": "bool", + "description": "Whether this entry location is in a cloaking field", + "default": false + }, + "position": { + "type": "object", + "description": "The position of this entry location", + "properties": { + "x": { + "type": "number", + "default": 0 + }, + "y": { + "type": "number", + "default": 0 + }, + "z": { + "type": "number", + "default": 0 + } + } + } + } + } } } }, @@ -886,6 +974,10 @@ "type": "string", "description": "Relative filepath to the .wav file to use as the audio. Mutually exclusive with audioClip" }, + "reveals": { + "type": "string", + "description": "A ship log fact to reveal when the signal is identified" + }, "sourceRadius": { "type": "number", "default": 1, @@ -1154,6 +1246,158 @@ } } } + }, + "ShipLog": { + "type": "object", + "properties": { + "xmlFile": { + "type": "string", + "description": "The xml file to load ship log entries from" + }, + "spriteFolder": { + "type": "string", + "description": "A path to the folder where entry sprites are stored" + }, + "initialReveal": { + "type": "array", + "description": "A list of fact IDs to reveal when the game starts", + "items": { + "type": "string" + } + }, + "positions": { + "type": "array", + "description": "A set of positions to use instead of automatic layout in rumor mode", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The name of the entry to apply the position" + }, + "position": { + "type": "object", + "properties": { + "x": { + "type": "number", + "default": 0 + }, + "y": { + "type": "number", + "default": 0 + } + } + } + } + } + }, + "MapMode": { + "type": "object", + "properties": { + "revealedSprite": { + "type": "string", + "description": "The path to the sprite to show when the planet is revealed in map mode" + }, + "outlineSprite": { + "type": "string", + "description": "The path to the sprite to show when the planet is unexplored in map mode" + }, + "scale": { + "type": "number", + "description": "Scale to apply to the planet in map mode", + "default": 1 + }, + "invisibleWhenHidden": { + "type": "bool", + "description": "Hide the planet completely if unexplored instead of showing an outline", + "default": false + }, + "offset": { + "type": "number", + "description": "Extra distance to apply to this object in map mode", + "default": 0 + }, + "remove": { + "type": "boolean", + "description": "Completely remove this planet from map mode", + "default": false + } + } + }, + "Curiosities": { + "type": "array", + "description": "A set of colors to apply to curiosities", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The ID of the curiosity to apply the color to" + }, + "color": { + "type": "object", + "description": "The color to apply to entries with this curiosity", + "properties": { + "R": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + }, + "G": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + }, + "B": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + }, + "A": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + } + } + }, + "highlightColor": { + "type": "object", + "description": "The color to apply to highlighted entries with this curiosity", + "properties": { + "R": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + }, + "G": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + }, + "B": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + }, + "A": { + "type": "integer", + "default": 0, + "minimum": 0, + "maximum": 255 + } + } + } + } + } + } + } } } } \ No newline at end of file diff --git a/NewHorizons/shiplog_schema.xsd b/NewHorizons/shiplog_schema.xsd new file mode 100644 index 00000000..fe3ade33 --- /dev/null +++ b/NewHorizons/shiplog_schema.xsd @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 5e680fb89e395974623698d9da1c584581c1ba98 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sat, 5 Feb 2022 19:44:21 -0500 Subject: [PATCH 3/6] Added RevealFacts to dialogue_schema.xsd --- NewHorizons/dialogue_schema.xsd | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NewHorizons/dialogue_schema.xsd b/NewHorizons/dialogue_schema.xsd index e8c70424..bd3e38ca 100644 --- a/NewHorizons/dialogue_schema.xsd +++ b/NewHorizons/dialogue_schema.xsd @@ -16,6 +16,13 @@ + + + + + + + From 71fb83891d64bd06fe773903476038f64bbd5cd1 Mon Sep 17 00:00:00 2001 From: Ben C Date: Sun, 6 Feb 2022 10:58:55 -0500 Subject: [PATCH 4/6] Added Ship Log Details - Removed Debugging GUI - Added lines to map mode so orbits are more obvious - Added details to ship log - Updated schema.json - Added missing elements to dialogue_schema.xsd --- NewHorizons/Builder/General/ShipLogBuilder.cs | 113 ++++++++++++++---- NewHorizons/Components/ShipLogDetail.cs | 37 ++++++ NewHorizons/External/ShipLogModule.cs | 23 +++- NewHorizons/Main.cs | 29 ----- NewHorizons/Tools/Patches.cs | 24 +++- NewHorizons/dialogue_schema.xsd | 2 + NewHorizons/schema.json | 57 ++++++++- 7 files changed, 223 insertions(+), 62 deletions(-) create mode 100644 NewHorizons/Components/ShipLogDetail.cs diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs index ac764a21..52d9e4ee 100644 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ b/NewHorizons/Builder/General/ShipLogBuilder.cs @@ -1,12 +1,8 @@ using NewHorizons.Components; -using System; -using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml.Linq; -using System.Text; -using System.Threading.Tasks; using NewHorizons.External; using NewHorizons.Utility; using OWML.Common; @@ -70,10 +66,10 @@ namespace NewHorizons.Builder.General public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer) { - MapModeObject rootObject = MakePrimaryNode(systemName); + MapModeObject rootObject = ConstructPrimaryNode(systemName); if (rootObject.mainBody != null) { - CreateAllNodes(ref rootObject, transformParent, layer); + MakeAllNodes(ref rootObject, transformParent, layer); } const int maxAmount = 20; @@ -104,13 +100,13 @@ namespace NewHorizons.Builder.General } } - private static void CreateAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) + private static void MakeAllNodes(ref MapModeObject parentNode, GameObject parent, int layer) { - CreateNode(ref parentNode, parent, layer); + MakeNode(ref parentNode, parent, layer); for (var i = 0; i < parentNode.children.Count; i++) { MapModeObject child = parentNode.children[i]; - CreateAllNodes(ref child, parent, layer); + MakeAllNodes(ref child, parent, layer); parentNode.children[i] = child; } } @@ -174,21 +170,85 @@ namespace NewHorizons.Builder.General astroObject._id = GetAstroObjectId(node.mainBody); string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; - astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, "Image", layer); - astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, "Outline", layer); - astroObject._unviewedObj = GameObject.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); + astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, node.mainBody.Config.Name + " Revealed", layer); + astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, node.mainBody.Config.Name + " Outline", layer); + astroObject._unviewedObj = Object.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); + if (node.mainBody.Config.FocalPoint != null) + { + astroObject._imageObj.GetComponent().enabled = false; + astroObject._outlineObj.GetComponent().enabled = false; + astroObject._unviewedObj.GetComponent().enabled = false; + astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale; + } astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; Rect imageRect = astroObject._imageObj.GetComponent().rect; astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); node.astroObject = astroObject; } - private static void ConnectNodes(MapModeObject from, MapModeObject to) + private static void ConnectNodeToLastSibling(MapModeObject node) { - + Vector2 fromPosition = node.astroObject.transform.localPosition; + Vector2 toPosition = node.lastSibling.astroObject.transform.localPosition; + GameObject newLink = new GameObject(node.mainBody.Config.Name + " To " + node.lastSibling.mainBody.Config.Name + " Link_ShipLog"); + newLink.layer = node.astroObject.gameObject.layer; + newLink.SetActive(false); + RectTransform transform = newLink.AddComponent(); + transform.SetParent(node.astroObject.transform.parent); + Vector2 center = toPosition + (fromPosition - toPosition) / 2; + transform.localPosition = new Vector3(center.x, center.y, -1); + transform.localRotation = Quaternion.identity; + transform.localScale = node.level % 2 == 0 ? new Vector3(node.astroObject.transform.localScale.x / 5f, Mathf.Abs(fromPosition.y - toPosition.y) / 100f, 1) : new Vector3(Mathf.Abs(fromPosition.x - toPosition.x) / 100f, node.astroObject.transform.localScale.y / 5f , 1); + newLink.AddComponent(); + transform.SetParent(node.astroObject.transform); + transform.SetAsFirstSibling(); + newLink.SetActive(true); } - private static void CreateNode(ref MapModeObject node, GameObject parent, int layer) + private static void MakeDetail(ShipLogModule.ShipLogDetailInfo info, Transform parent, IModAssets assets) + { + GameObject detailGameObject = new GameObject("Detail"); + detailGameObject.transform.SetParent(parent); + detailGameObject.SetActive(false); + + RectTransform detailTransform = detailGameObject.AddComponent(); + detailTransform.localPosition = (Vector2)(info.position ?? new MVector2(0, 0)); + detailTransform.localRotation = Quaternion.Euler(0f, 0f, info.rotation); + detailTransform.localScale = (Vector2)(info.scale ?? new MVector2(0, 0)); + + string revealedPath = info.revealedSprite ?? "DEFAULT"; + string outlinePath = info.outlineSprite ?? revealedPath; + + Image revealedImage = CreateImage(detailGameObject, assets, revealedPath, "Detail Revealed", parent.gameObject.layer).GetComponent(); + Image outlineImage = CreateImage(detailGameObject, assets, outlinePath, "Detail Outline", parent.gameObject.layer).GetComponent(); + + ShipLogDetail detail = detailGameObject.AddComponent(); + detail.Init(info, revealedImage, outlineImage); + detailGameObject.SetActive(true); + } + + private static void MakeDetails(MapModeObject node) + { + if (node.mainBody.Config.ShipLog?.mapMode?.details?.Length > 0) + { + GameObject detailsParent = new GameObject("Details"); + detailsParent.transform.SetParent(node.astroObject.transform); + detailsParent.SetActive(false); + + RectTransform detailsTransform = detailsParent.AddComponent(); + detailsTransform.localPosition = Vector3.zero; + detailsTransform.localRotation = Quaternion.identity; + detailsTransform.localScale = Vector3.one; + + foreach (ShipLogModule.ShipLogDetailInfo detailInfo in node.mainBody.Config.ShipLog.mapMode.details) + { + MakeDetail(detailInfo, detailsTransform, node.mainBody.Mod.Assets); + } + detailsParent.SetActive(true); + } + } + + private static void MakeNode(ref MapModeObject node, GameObject parent, int layer) { const float padding = 250f; @@ -218,12 +278,17 @@ namespace NewHorizons.Builder.General transform.localRotation = Quaternion.identity; transform.localScale = Vector3.one * scale; CreateShipLogAstroObject(newNodeGO, ref node, GameObject.Find(PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon"), layer); + if (node.lastSibling != null) ConnectNodeToLastSibling(node); + MakeDetails(node); + transform.SetAsFirstSibling(); } - private static MapModeObject MakePrimaryNode(string systemName) + private static MapModeObject ConstructPrimaryNode(string systemName) { foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.Base.CenterOfSolarSystem)) { + List searchList = Main.BodyDict[systemName].Where(b => (b.Config.ShipLog?.mapMode?.remove ?? false) == false).ToList(); + searchList.Sort((b, o) => b.Config.Orbit.SemiMajorAxis.CompareTo(o.Config.Orbit.SemiMajorAxis)); MapModeObject newNode = new MapModeObject { mainBody = body, @@ -231,21 +296,21 @@ namespace NewHorizons.Builder.General x = 0, y = 0 }; - newNode.children = MakeChildrenNodes(systemName, newNode); + newNode.children = ConstructChildrenNodes(systemName, newNode, searchList); return newNode; } Logger.LogError("Couldn't find center of system!"); return new MapModeObject(); } - private static List MakeChildrenNodes(string systemName, MapModeObject parent) + private static List ConstructChildrenNodes(string systemName, MapModeObject parent, List searchList) { List children = new List(); int newX = parent.x; int newY = parent.y; int newLevel = parent.level + 1; MapModeObject lastSibling = parent; - foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.ShipLog?.mapMode?.remove == false && b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name)) + foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name)) { if (body.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name) { @@ -261,16 +326,18 @@ namespace NewHorizons.Builder.General parent = parent, lastSibling = lastSibling }; - newNode.children = MakeChildrenNodes(systemName, newNode); + newNode.children = ConstructChildrenNodes(systemName, newNode, searchList); if (even) { newY += newNode.branch_height; parent.increment_height(); + newY += 1; } else { newX += newNode.branch_width; parent.increment_width(); + newX += 1; } lastSibling = newNode; children.Add(newNode); @@ -289,9 +356,9 @@ namespace NewHorizons.Builder.General private static Dictionary rawNameToCuriosityName = new Dictionary(); private static Dictionary entryIdToRawName = new Dictionary(); - public static void AddCuriosityColors(ShipLogModule.CuriosityColor[] newColors) + public static void AddCuriosityColors(ShipLogModule.CuriosityColorInfo[] newColors) { - foreach (ShipLogModule.CuriosityColor newColor in newColors) + foreach (ShipLogModule.CuriosityColorInfo newColor in newColors) { if (rawNameToCuriosityName.ContainsKey(newColor.id) == false) { @@ -450,7 +517,7 @@ namespace NewHorizons.Builder.General private static Vector2? GetManualEntryPosition(string entryId, ShipLogModule config) { if (config.positions == null) return null; - foreach (ShipLogModule.EntryPosition position in config.positions) + foreach (ShipLogModule.EntryPositionInfo position in config.positions) { if (position.id == entryId) { diff --git a/NewHorizons/Components/ShipLogDetail.cs b/NewHorizons/Components/ShipLogDetail.cs new file mode 100644 index 00000000..21059059 --- /dev/null +++ b/NewHorizons/Components/ShipLogDetail.cs @@ -0,0 +1,37 @@ +using NewHorizons.External; +using OWML.Common; +using UnityEngine; +using UnityEngine.UI; + +namespace NewHorizons.Components +{ + public class ShipLogDetail : MonoBehaviour + { + private Image revealedImage; + private Image outlineImage; + private ShipLogModule.ShipLogDetailInfo detailInfo; + + public void Init(ShipLogModule.ShipLogDetailInfo info, Image revealed, Image outline) + { + detailInfo = info; + revealedImage = revealed; + outlineImage = outline; + revealedImage.enabled = false; + outlineImage.enabled = false; + } + + public void UpdateState(bool parentRevealed) + { + if (parentRevealed) + { + revealedImage.enabled = true; + outlineImage.enabled = false; + } + else + { + revealedImage.enabled = false; + outlineImage.enabled = !detailInfo.invisibleWhenHidden; + } + } + } +} \ No newline at end of file diff --git a/NewHorizons/External/ShipLogModule.cs b/NewHorizons/External/ShipLogModule.cs index b0d2ad53..8883d8f5 100644 --- a/NewHorizons/External/ShipLogModule.cs +++ b/NewHorizons/External/ShipLogModule.cs @@ -6,12 +6,12 @@ namespace NewHorizons.External { public string xmlFile; public string spriteFolder; - public MapMode mapMode; - public CuriosityColor[] curiosities; - public EntryPosition[] positions; public string[] initialReveal; + public MapModeInfo mapMode; + public CuriosityColorInfo[] curiosities; + public EntryPositionInfo[] positions; - public class MapMode + public class MapModeInfo { public string revealedSprite; public string outlineSprite; @@ -19,19 +19,30 @@ namespace NewHorizons.External public bool invisibleWhenHidden; public float offset = 0f; public bool remove = false; + public ShipLogDetailInfo[] details; } - public class CuriosityColor + public class CuriosityColorInfo { public string id; public MColor color; public MColor highlightColor; } - public class EntryPosition + public class EntryPositionInfo { public string id; public MVector2 position; } + + public class ShipLogDetailInfo + { + public string revealedSprite; + public string outlineSprite; + public float rotation = 0f; + public bool invisibleWhenHidden; + public MVector2 position; + public MVector2 scale; + } } } \ No newline at end of file diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index c3367a5e..bb9dbb3f 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -53,35 +53,6 @@ namespace NewHorizons return new NewHorizonsApi(); } - private void OnGUI() - { - GUILayout.BeginArea(new Rect(0, 0, 100, 100)); - bool learnPress = GUILayout.Button("Learn Thing"); - if (learnPress) - { - Locator.GetShipLogManager().RevealFact("COOL_ROCK_R1", false, true); - Locator.GetShipLogManager().RevealFact("COOL_ROCK_R2", false, true); - Locator.GetShipLogManager().RevealFact("UNCOOL_ROCK_R1", false, true); - Locator.GetShipLogManager().RevealFact("UNCOOL_ROCK_R2", false, true); - Locator.GetShipLogManager().RevealFact("UNCOOL_ROCK_R3", false, true); - - } - - bool iRemem = GUILayout.Button("I Remem"); - if (iRemem) - { - Data.knowAllFacts = true; - Data.knowAllRumors = true; - } - bool forgorPress = GUILayout.Button("I Forgor"); - if (forgorPress) - { - Data.knowAllFacts = false; - Data.knowAllRumors = false; - } - GUILayout.EndArea(); - } - public void Start() { SceneManager.sceneLoaded += OnSceneLoaded; diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index f10c14ab..43316198 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -75,10 +75,12 @@ namespace NewHorizons.Tools // Postfixes Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnMapControllerAwake)); - Main.Instance.ModHelper.HarmonyHelper.AddPostfix("EnterMode", typeof(Patches), nameof(Patches.OnShipLogMapModeEnterMode)); - - Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnShipLogManagerAwakeComplete)); + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Awake", typeof(Patches), nameof(Patches.OnShipLogManagerAwakeComplete)); + + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("UpdateState", typeof(Patches), nameof(Patches.OnShipLogAstroObjectUpdateState)); + + Main.Instance.ModHelper.HarmonyHelper.AddPostfix("EnterMode", typeof(Patches), nameof(Patches.OnShipLogMapModeEnterMode)); Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Initialize", typeof(Patches), nameof(Patches.OnShipLogMapModeInitialize)); } @@ -532,6 +534,22 @@ namespace NewHorizons.Tools } } + public static void OnShipLogAstroObjectUpdateState(ShipLogAstroObject __instance) + { + Transform detailsParent = __instance.transform.Find("Details"); + if (detailsParent != null) + { + foreach (GameObject child in SearchUtilities.GetAllChildren(detailsParent.gameObject)) + { + Component detail; + if (child.TryGetComponent(typeof(ShipLogDetail), out detail)) + { + (detail as ShipLogDetail)?.UpdateState(__instance._state == ShipLogEntry.State.Explored); + } + } + } + } + public static bool DisableShipLogSandFunnel() { return Main.Instance.CurrentStarSystem == "SolarSystem"; diff --git a/NewHorizons/dialogue_schema.xsd b/NewHorizons/dialogue_schema.xsd index bd3e38ca..f956f814 100644 --- a/NewHorizons/dialogue_schema.xsd +++ b/NewHorizons/dialogue_schema.xsd @@ -29,6 +29,8 @@ + + diff --git a/NewHorizons/schema.json b/NewHorizons/schema.json index 85a03c54..32e42d7b 100644 --- a/NewHorizons/schema.json +++ b/NewHorizons/schema.json @@ -1319,8 +1319,63 @@ }, "remove": { "type": "boolean", - "description": "Completely remove this planet from map mode", + "description": "Completely remove this planet (and it's children) from map mode", "default": false + }, + "details": { + "type": "array", + "description": "Place non-selectable object in map mode (like sand funnels)", + "items": { + "type": "object", + "properties": { + "revealedSprite": { + "type": "string", + "description": "The sprite to show when the parent AstroBody is revealed" + }, + "outlineSprite": { + "type": "string", + "description": "The sprite to show when the parent AstroBody is rumored/unexplored" + }, + "rotation": { + "type": "number", + "description": "The angle in degrees to rotate the detail", + "default": 0 + }, + "invisibleWhenHidden": { + "type": "boolean", + "description": "Whether to completely hide this detail when the parent AstroBody is unexplored", + "default": false + }, + "position": { + "type": "object", + "description": "The position (relative to the parent) to place the detail", + "properties": { + "x": { + "type": "number", + "default": 0 + }, + "y": { + "type": "number", + "default": 0 + } + } + }, + "scale": { + "type": "object", + "description": "The amount to scale the x and y axis of the detail by", + "properties": { + "x": { + "type": "number", + "default": 0 + }, + "y": { + "type": "number", + "default": 0 + } + } + } + } + } } } }, From 1b320f6fc11a4ec3e45ec419ec0bb38f2fd9af6b Mon Sep 17 00:00:00 2001 From: Ben C Date: Sun, 6 Feb 2022 12:11:04 -0500 Subject: [PATCH 5/6] Changed Map Mode Lines - Lines are now hidden if their parent is hidden - Better Line Color --- NewHorizons/Builder/General/ShipLogBuilder.cs | 19 +++++++++++-- NewHorizons/Components/ShipLogDetail.cs | 28 +++++++++++++------ NewHorizons/Tools/Patches.cs | 9 +++++- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs index 52d9e4ee..6997b38f 100644 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ b/NewHorizons/Builder/General/ShipLogBuilder.cs @@ -168,10 +168,12 @@ namespace NewHorizons.Builder.General const float unviewedIconOffset = 15; ShipLogAstroObject astroObject = nodeGO.AddComponent(); astroObject._id = GetAstroObjectId(node.mainBody); + string imagePath = node.mainBody.Config.ShipLog?.mapMode?.revealedSprite ?? "DEFAULT"; string outlinePath = node.mainBody.Config.ShipLog?.mapMode?.outlineSprite ?? imagePath; astroObject._imageObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, imagePath, node.mainBody.Config.Name + " Revealed", layer); astroObject._outlineObj = CreateImage(nodeGO, node.mainBody.Mod.Assets, outlinePath, node.mainBody.Config.Name + " Outline", layer); + astroObject._unviewedObj = Object.Instantiate(referenceUnviewedSprite, nodeGO.transform, false); if (node.mainBody.Config.FocalPoint != null) { @@ -181,6 +183,7 @@ namespace NewHorizons.Builder.General astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale; } astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false; + Rect imageRect = astroObject._imageObj.GetComponent().rect; astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0); node.astroObject = astroObject; @@ -190,16 +193,28 @@ namespace NewHorizons.Builder.General { Vector2 fromPosition = node.astroObject.transform.localPosition; Vector2 toPosition = node.lastSibling.astroObject.transform.localPosition; - GameObject newLink = new GameObject(node.mainBody.Config.Name + " To " + node.lastSibling.mainBody.Config.Name + " Link_ShipLog"); + + GameObject newLink = new GameObject("Line_ShipLog"); newLink.layer = node.astroObject.gameObject.layer; newLink.SetActive(false); + RectTransform transform = newLink.AddComponent(); transform.SetParent(node.astroObject.transform.parent); Vector2 center = toPosition + (fromPosition - toPosition) / 2; transform.localPosition = new Vector3(center.x, center.y, -1); transform.localRotation = Quaternion.identity; transform.localScale = node.level % 2 == 0 ? new Vector3(node.astroObject.transform.localScale.x / 5f, Mathf.Abs(fromPosition.y - toPosition.y) / 100f, 1) : new Vector3(Mathf.Abs(fromPosition.x - toPosition.x) / 100f, node.astroObject.transform.localScale.y / 5f , 1); - newLink.AddComponent(); + Image linkImage = newLink.AddComponent(); + linkImage.color = new Color(0.28f, 0.28f, 0.5f, 0.28f); + + ShipLogModule.ShipLogDetailInfo linkDetailInfo = new ShipLogModule.ShipLogDetailInfo() + { + invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false + }; + + ShipLogDetail linkDetail = newLink.AddComponent(); + linkDetail.Init(linkDetailInfo, linkImage, linkImage); + transform.SetParent(node.astroObject.transform); transform.SetAsFirstSibling(); newLink.SetActive(true); diff --git a/NewHorizons/Components/ShipLogDetail.cs b/NewHorizons/Components/ShipLogDetail.cs index 21059059..c6f77304 100644 --- a/NewHorizons/Components/ShipLogDetail.cs +++ b/NewHorizons/Components/ShipLogDetail.cs @@ -2,6 +2,7 @@ using OWML.Common; using UnityEngine; using UnityEngine.UI; +using Logger = NewHorizons.Utility.Logger; namespace NewHorizons.Components { @@ -20,17 +21,26 @@ namespace NewHorizons.Components outlineImage.enabled = false; } - public void UpdateState(bool parentRevealed) + public void UpdateState(ShipLogEntry.State parentState) { - if (parentRevealed) + switch (parentState) { - revealedImage.enabled = true; - outlineImage.enabled = false; - } - else - { - revealedImage.enabled = false; - outlineImage.enabled = !detailInfo.invisibleWhenHidden; + case ShipLogEntry.State.Explored: + outlineImage.enabled = false; + revealedImage.enabled = true; + break; + case ShipLogEntry.State.Rumored: + revealedImage.enabled = false; + outlineImage.enabled = true; + break; + case ShipLogEntry.State.Hidden: + revealedImage.enabled = false; + outlineImage.enabled = !detailInfo.invisibleWhenHidden; + break; + case ShipLogEntry.State.None: + revealedImage.enabled = false; + outlineImage.enabled = false; + break; } } } diff --git a/NewHorizons/Tools/Patches.cs b/NewHorizons/Tools/Patches.cs index 43316198..4c885417 100644 --- a/NewHorizons/Tools/Patches.cs +++ b/NewHorizons/Tools/Patches.cs @@ -544,10 +544,17 @@ namespace NewHorizons.Tools Component detail; if (child.TryGetComponent(typeof(ShipLogDetail), out detail)) { - (detail as ShipLogDetail)?.UpdateState(__instance._state == ShipLogEntry.State.Explored); + (detail as ShipLogDetail)?.UpdateState(__instance._state); } } } + + Transform lineObject = __instance.transform.Find("Line_ShipLog"); + if (lineObject != null) + { + ShipLogDetail lineDetail = lineObject.gameObject.GetComponent(); + lineDetail.UpdateState(__instance._state); + } } public static bool DisableShipLogSandFunnel() From 28970e4138c26b3da8b06eb22ad5b3c6a0daafaa Mon Sep 17 00:00:00 2001 From: Ben C Date: Sun, 6 Feb 2022 22:52:26 -0500 Subject: [PATCH 6/6] Fixed error if there are too many planets Found by `Jammer` --- NewHorizons/Builder/General/ShipLogBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Builder/General/ShipLogBuilder.cs b/NewHorizons/Builder/General/ShipLogBuilder.cs index 6997b38f..6c89fbf9 100644 --- a/NewHorizons/Builder/General/ShipLogBuilder.cs +++ b/NewHorizons/Builder/General/ShipLogBuilder.cs @@ -72,7 +72,7 @@ namespace NewHorizons.Builder.General MakeAllNodes(ref rootObject, transformParent, layer); } - const int maxAmount = 20; + int maxAmount = Main.BodyDict[Main.Instance.CurrentStarSystem].Count; ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][]; for (int i = 0; i < maxAmount; i++) {