mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Code refactor after PR
This commit is contained in:
parent
70abed2ae3
commit
c3a7588b22
@ -1,648 +0,0 @@
|
||||
using NewHorizons.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
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";
|
||||
|
||||
private static Dictionary<string, NewHorizonsBody> astroIdToBody = new Dictionary<string, NewHorizonsBody>();
|
||||
|
||||
private static NewHorizonsBody GetConfigFromEntry(ShipLogEntry entry)
|
||||
{
|
||||
return astroIdToBody[entry._astroObjectID];
|
||||
}
|
||||
|
||||
#region Map Mode
|
||||
|
||||
public class MapModeBuilder
|
||||
{
|
||||
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<MapModeObject> children;
|
||||
public MapModeObject parent;
|
||||
public MapModeObject lastSibling;
|
||||
public void increment_width()
|
||||
{
|
||||
branch_width++;
|
||||
parent?.increment_width();
|
||||
}
|
||||
public void increment_height()
|
||||
{
|
||||
branch_height++;
|
||||
parent?.increment_height();
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAstroBodyShipLogName(string id)
|
||||
{
|
||||
if (astroIdToBody.ContainsKey(id))
|
||||
{
|
||||
return astroIdToBody[id].Config.Name;
|
||||
}
|
||||
else
|
||||
{
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer)
|
||||
{
|
||||
MapModeObject rootObject = ConstructPrimaryNode(systemName);
|
||||
if (rootObject.mainBody != null)
|
||||
{
|
||||
MakeAllNodes(ref rootObject, transformParent, layer);
|
||||
}
|
||||
|
||||
int maxAmount = Main.BodyDict[Main.Instance.CurrentStarSystem].Count;
|
||||
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 MakeAllNodes(ref MapModeObject parentNode, GameObject parent, int layer)
|
||||
{
|
||||
MakeNode(ref parentNode, parent, layer);
|
||||
for (var i = 0; i < parentNode.children.Count; i++)
|
||||
{
|
||||
MapModeObject child = parentNode.children[i];
|
||||
MakeAllNodes(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<RectTransform>();
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localRotation = Quaternion.identity;
|
||||
transform.localScale = Vector3.one;
|
||||
|
||||
Image newImage = newImageGO.AddComponent<Image>();
|
||||
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<T, W>(Dictionary<T, W> dict, W val)
|
||||
{
|
||||
T key = default;
|
||||
foreach (KeyValuePair<T, W> pair in dict)
|
||||
{
|
||||
if (EqualityComparer<W>.Default.Equals(pair.Value, val))
|
||||
{
|
||||
key = pair.Key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
private static string GetAstroObjectId(NewHorizonsBody body)
|
||||
{
|
||||
if (astroIdToBody.ContainsValue(body))
|
||||
{
|
||||
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<ShipLogAstroObject>();
|
||||
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)
|
||||
{
|
||||
astroObject._imageObj.GetComponent<Image>().enabled = false;
|
||||
astroObject._outlineObj.GetComponent<Image>().enabled = false;
|
||||
astroObject._unviewedObj.GetComponent<Image>().enabled = false;
|
||||
astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale;
|
||||
}
|
||||
astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false;
|
||||
|
||||
Rect imageRect = astroObject._imageObj.GetComponent<RectTransform>().rect;
|
||||
astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0);
|
||||
node.astroObject = astroObject;
|
||||
}
|
||||
|
||||
private static void ConnectNodeToLastSibling(MapModeObject node)
|
||||
{
|
||||
Vector2 fromPosition = node.astroObject.transform.localPosition;
|
||||
Vector2 toPosition = node.lastSibling.astroObject.transform.localPosition;
|
||||
|
||||
GameObject newLink = new GameObject("Line_ShipLog");
|
||||
newLink.layer = node.astroObject.gameObject.layer;
|
||||
newLink.SetActive(false);
|
||||
|
||||
RectTransform transform = newLink.AddComponent<RectTransform>();
|
||||
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);
|
||||
Image linkImage = newLink.AddComponent<Image>();
|
||||
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<ShipLogDetail>();
|
||||
linkDetail.Init(linkDetailInfo, linkImage, linkImage);
|
||||
|
||||
transform.SetParent(node.astroObject.transform);
|
||||
transform.SetAsFirstSibling();
|
||||
newLink.SetActive(true);
|
||||
}
|
||||
|
||||
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<RectTransform>();
|
||||
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>();
|
||||
Image outlineImage = CreateImage(detailGameObject, assets, outlinePath, "Detail Outline", parent.gameObject.layer).GetComponent<Image>();
|
||||
|
||||
ShipLogDetail detail = detailGameObject.AddComponent<ShipLogDetail>();
|
||||
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<RectTransform>();
|
||||
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;
|
||||
|
||||
GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog");
|
||||
newNodeGO.layer = layer;
|
||||
newNodeGO.transform.SetParent(parent.transform);
|
||||
|
||||
RectTransform transform = newNodeGO.AddComponent<RectTransform>();
|
||||
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);
|
||||
if (node.lastSibling != null) ConnectNodeToLastSibling(node);
|
||||
MakeDetails(node);
|
||||
transform.SetAsFirstSibling();
|
||||
}
|
||||
|
||||
private static MapModeObject ConstructPrimaryNode(string systemName)
|
||||
{
|
||||
foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.Base.CenterOfSolarSystem))
|
||||
{
|
||||
List<NewHorizonsBody> 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,
|
||||
level = 0,
|
||||
x = 0,
|
||||
y = 0
|
||||
};
|
||||
newNode.children = ConstructChildrenNodes(systemName, newNode, searchList);
|
||||
return newNode;
|
||||
}
|
||||
Logger.LogError("Couldn't find center of system!");
|
||||
return new MapModeObject();
|
||||
}
|
||||
|
||||
private static List<MapModeObject> ConstructChildrenNodes(string systemName, MapModeObject parent, List<NewHorizonsBody> searchList)
|
||||
{
|
||||
List<MapModeObject> children = new List<MapModeObject>();
|
||||
int newX = parent.x;
|
||||
int newY = parent.y;
|
||||
int newLevel = parent.level + 1;
|
||||
MapModeObject lastSibling = parent;
|
||||
foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name))
|
||||
{
|
||||
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 = 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);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Rumor Mode
|
||||
public static class RumorModeBuilder
|
||||
{
|
||||
private static Dictionary<CuriosityName, Color> curiosityColors = new Dictionary<CuriosityName, Color>();
|
||||
private static Dictionary<CuriosityName, Color> curiosityHighlightColors = new Dictionary<CuriosityName, Color>();
|
||||
private static Dictionary<string, CuriosityName> rawNameToCuriosityName = new Dictionary<string, CuriosityName>();
|
||||
private static Dictionary<string, string> entryIdToRawName = new Dictionary<string, string>();
|
||||
|
||||
public static void AddCuriosityColors(ShipLogModule.CuriosityColorInfo[] newColors)
|
||||
{
|
||||
foreach (ShipLogModule.CuriosityColorInfo 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 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)
|
||||
{
|
||||
Logger.LogError("Failed to load ship logs 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<TextAsset> newBodies = new List<TextAsset>(manager._shipLogXmlAssets) {newAsset};
|
||||
manager._shipLogXmlAssets = newBodies.ToArray();
|
||||
if (astroIdToBody.ContainsKey(astroBodyId.Value) == false)
|
||||
{
|
||||
astroIdToBody.Add(astroBodyId.Value, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 = 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<string, string> 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.EntryPositionInfo 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<SphereShape>();
|
||||
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<OWTriggerVolume>();
|
||||
newVolume._shape = newShape;
|
||||
ShipLogFactListTriggerVolume volume = go.AddComponent<ShipLogFactListTriggerVolume>();
|
||||
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<SphereCollider>();
|
||||
newSphere.radius = info.radius;
|
||||
OWCollider newCollider = go.AddComponent<OWCollider>();
|
||||
ShipLogFactObserveTrigger newObserveTrigger = go.AddComponent<ShipLogFactObserveTrigger>();
|
||||
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<ShapeVisibilityTracker>();
|
||||
newTracker._shapes = new Shape[] {newShape};
|
||||
ShipLogFactSnapshotTrigger newSnapshotTrigger = go.AddComponent<ShipLogFactSnapshotTrigger>();
|
||||
newSnapshotTrigger._maxDistance = info.maxDistance == -1f ? 200f : info.maxDistance;
|
||||
newSnapshotTrigger._factIDs = info.reveals;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Entry Locations
|
||||
public static class EntryLocationBuilder
|
||||
{
|
||||
private static List<ShipLogEntryLocation> locationsToInitialize = new List<ShipLogEntryLocation>();
|
||||
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<ShipLogEntryLocation>();
|
||||
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
|
||||
}
|
||||
}
|
||||
@ -11,6 +11,7 @@ using System.Reflection;
|
||||
using NewHorizons.Builder.General;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using NewHorizons.Builder.ShipLog;
|
||||
|
||||
namespace NewHorizons.Builder.Props
|
||||
{
|
||||
@ -58,14 +59,14 @@ namespace NewHorizons.Builder.Props
|
||||
{
|
||||
foreach (var revealInfo in config.Props.Reveal)
|
||||
{
|
||||
ShipLogBuilder.RevealBuilder.Make(go, sector, revealInfo, mod);
|
||||
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);
|
||||
EntryLocationBuilder.Make(go, sector, entryLocationInfo, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs
Normal file
37
NewHorizons/Builder/ShipLog/EntryLocationBuilder.cs
Normal file
@ -0,0 +1,37 @@
|
||||
using NewHorizons.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.Builder.ShipLog
|
||||
{
|
||||
public static class EntryLocationBuilder
|
||||
{
|
||||
private static readonly List<ShipLogEntryLocation> _locationsToInitialize = new List<ShipLogEntryLocation>();
|
||||
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<ShipLogEntryLocation>();
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
319
NewHorizons/Builder/ShipLog/MapModeBuilder.cs
Normal file
319
NewHorizons/Builder/ShipLog/MapModeBuilder.cs
Normal file
@ -0,0 +1,319 @@
|
||||
using NewHorizons.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
using NewHorizons.Builder.Handlers;
|
||||
|
||||
namespace NewHorizons.Builder.ShipLog
|
||||
{
|
||||
public static class MapModeBuilder
|
||||
{
|
||||
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<MapModeObject> children;
|
||||
public MapModeObject parent;
|
||||
public MapModeObject lastSibling;
|
||||
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 ShipLogHandler.GetConfigFromID(id)?.Config?.Name ?? id;
|
||||
}
|
||||
|
||||
public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, int layer)
|
||||
{
|
||||
MapModeObject rootObject = ConstructPrimaryNode(systemName);
|
||||
if (rootObject.mainBody != null)
|
||||
{
|
||||
MakeAllNodes(ref rootObject, transformParent, layer);
|
||||
}
|
||||
|
||||
int maxAmount = Main.BodyDict[Main.Instance.CurrentStarSystem].Count;
|
||||
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 MakeAllNodes(ref MapModeObject parentNode, GameObject parent, int layer)
|
||||
{
|
||||
MakeNode(ref parentNode, parent, layer);
|
||||
for (var i = 0; i < parentNode.children.Count; i++)
|
||||
{
|
||||
MapModeObject child = parentNode.children[i];
|
||||
MakeAllNodes(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<RectTransform>();
|
||||
transform.localPosition = Vector3.zero;
|
||||
transform.localRotation = Quaternion.identity;
|
||||
transform.localScale = Vector3.one;
|
||||
|
||||
Image newImage = newImageGO.AddComponent<Image>();
|
||||
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;
|
||||
}
|
||||
|
||||
private static void CreateShipLogAstroObject(GameObject nodeGO, ref MapModeObject node, GameObject referenceUnviewedSprite, int layer)
|
||||
{
|
||||
const float unviewedIconOffset = 15;
|
||||
ShipLogAstroObject astroObject = nodeGO.AddComponent<ShipLogAstroObject>();
|
||||
astroObject._id = ShipLogHandler.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)
|
||||
{
|
||||
astroObject._imageObj.GetComponent<Image>().enabled = false;
|
||||
astroObject._outlineObj.GetComponent<Image>().enabled = false;
|
||||
astroObject._unviewedObj.GetComponent<Image>().enabled = false;
|
||||
astroObject.transform.localScale = node.lastSibling.astroObject.transform.localScale;
|
||||
}
|
||||
astroObject._invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false;
|
||||
|
||||
Rect imageRect = astroObject._imageObj.GetComponent<RectTransform>().rect;
|
||||
astroObject._unviewedObj.transform.localPosition = new Vector3(imageRect.width / 2 + unviewedIconOffset, imageRect.height / 2 + unviewedIconOffset, 0);
|
||||
node.astroObject = astroObject;
|
||||
}
|
||||
|
||||
private static void ConnectNodeToLastSibling(MapModeObject node)
|
||||
{
|
||||
Vector2 fromPosition = node.astroObject.transform.localPosition;
|
||||
Vector2 toPosition = node.lastSibling.astroObject.transform.localPosition;
|
||||
|
||||
GameObject newLink = new GameObject("Line_ShipLog");
|
||||
newLink.layer = node.astroObject.gameObject.layer;
|
||||
newLink.SetActive(false);
|
||||
|
||||
RectTransform transform = newLink.AddComponent<RectTransform>();
|
||||
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);
|
||||
Image linkImage = newLink.AddComponent<Image>();
|
||||
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<ShipLogDetail>();
|
||||
linkDetail.Init(linkDetailInfo, linkImage, linkImage);
|
||||
|
||||
transform.SetParent(node.astroObject.transform);
|
||||
transform.SetAsFirstSibling();
|
||||
newLink.SetActive(true);
|
||||
}
|
||||
|
||||
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<RectTransform>();
|
||||
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>();
|
||||
Image outlineImage = CreateImage(detailGameObject, assets, outlinePath, "Detail Outline", parent.gameObject.layer).GetComponent<Image>();
|
||||
|
||||
ShipLogDetail detail = detailGameObject.AddComponent<ShipLogDetail>();
|
||||
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<RectTransform>();
|
||||
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;
|
||||
|
||||
GameObject newNodeGO = new GameObject(node.mainBody.Config.Name + "_ShipLog");
|
||||
newNodeGO.layer = layer;
|
||||
newNodeGO.transform.SetParent(parent.transform);
|
||||
|
||||
RectTransform transform = newNodeGO.AddComponent<RectTransform>();
|
||||
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("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot/TimberHearth/UnviewedIcon"), layer);
|
||||
if (node.lastSibling != null) ConnectNodeToLastSibling(node);
|
||||
MakeDetails(node);
|
||||
transform.SetAsFirstSibling();
|
||||
}
|
||||
|
||||
private static MapModeObject ConstructPrimaryNode(string systemName)
|
||||
{
|
||||
foreach (NewHorizonsBody body in Main.BodyDict[systemName].Where(b => b.Config.Base.CenterOfSolarSystem))
|
||||
{
|
||||
List<NewHorizonsBody> 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,
|
||||
level = 0,
|
||||
x = 0,
|
||||
y = 0
|
||||
};
|
||||
newNode.children = ConstructChildrenNodes(systemName, newNode, searchList);
|
||||
return newNode;
|
||||
}
|
||||
Logger.LogError("Couldn't find center of system!");
|
||||
return new MapModeObject();
|
||||
}
|
||||
|
||||
private static List<MapModeObject> ConstructChildrenNodes(string systemName, MapModeObject parent, List<NewHorizonsBody> searchList)
|
||||
{
|
||||
List<MapModeObject> children = new List<MapModeObject>();
|
||||
int newX = parent.x;
|
||||
int newY = parent.y;
|
||||
int newLevel = parent.level + 1;
|
||||
MapModeObject lastSibling = parent;
|
||||
foreach (NewHorizonsBody body in searchList.Where(b => b.Config.Orbit.PrimaryBody == parent.mainBody.Config.Name))
|
||||
{
|
||||
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 = 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);
|
||||
}
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
89
NewHorizons/Builder/ShipLog/RevealBuilder.cs
Normal file
89
NewHorizons/Builder/ShipLog/RevealBuilder.cs
Normal file
@ -0,0 +1,89 @@
|
||||
using NewHorizons.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.Builder.ShipLog
|
||||
{
|
||||
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<SphereShape>();
|
||||
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<OWTriggerVolume>();
|
||||
newVolume._shape = newShape;
|
||||
ShipLogFactListTriggerVolume volume = go.AddComponent<ShipLogFactListTriggerVolume>();
|
||||
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<SphereCollider>();
|
||||
newSphere.radius = info.radius;
|
||||
OWCollider newCollider = go.AddComponent<OWCollider>();
|
||||
ShipLogFactObserveTrigger newObserveTrigger = go.AddComponent<ShipLogFactObserveTrigger>();
|
||||
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<ShapeVisibilityTracker>();
|
||||
newTracker._shapes = new Shape[] { newShape };
|
||||
ShipLogFactSnapshotTrigger newSnapshotTrigger = go.AddComponent<ShipLogFactSnapshotTrigger>();
|
||||
newSnapshotTrigger._maxDistance = info.maxDistance == -1f ? 200f : info.maxDistance;
|
||||
newSnapshotTrigger._factIDs = info.reveals;
|
||||
}
|
||||
}
|
||||
}
|
||||
191
NewHorizons/Builder/ShipLog/RumorModeBuilder.cs
Normal file
191
NewHorizons/Builder/ShipLog/RumorModeBuilder.cs
Normal file
@ -0,0 +1,191 @@
|
||||
using NewHorizons.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
using NewHorizons.Builder.Handlers;
|
||||
|
||||
namespace NewHorizons.Builder.ShipLog
|
||||
{
|
||||
public static class RumorModeBuilder
|
||||
{
|
||||
private static readonly Dictionary<CuriosityName, Color> _curiosityColors = new Dictionary<CuriosityName, Color>();
|
||||
private static readonly Dictionary<CuriosityName, Color> _curiosityHighlightColors = new Dictionary<CuriosityName, Color>();
|
||||
private static readonly Dictionary<string, CuriosityName> _rawNameToCuriosityName = new Dictionary<string, CuriosityName>();
|
||||
private static readonly Dictionary<string, string> _entryIdToRawName = new Dictionary<string, string>();
|
||||
|
||||
public static void AddCuriosityColors(ShipLogModule.CuriosityColorInfo[] newColors)
|
||||
{
|
||||
foreach (ShipLogModule.CuriosityColorInfo 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 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)
|
||||
{
|
||||
Logger.LogError("Failed to load ship logs 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<TextAsset> newBodies = new List<TextAsset>(manager._shipLogXmlAssets) { newAsset };
|
||||
manager._shipLogXmlAssets = newBodies.ToArray();
|
||||
ShipLogHandler.AddConfig(astroBodyId.Value, body);
|
||||
}
|
||||
}
|
||||
|
||||
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 = ShipLogHandler.GetConfigFromID(entry._astroObjectID);
|
||||
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<string, string> 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.EntryPositionInfo position in config.positions)
|
||||
{
|
||||
if (position.id == entryId)
|
||||
{
|
||||
return position.position;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
46
NewHorizons/Handlers/ShipLogHandler.cs
Normal file
46
NewHorizons/Handlers/ShipLogHandler.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using NewHorizons.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.Builder.Handlers
|
||||
{
|
||||
public static class ShipLogHandler
|
||||
{
|
||||
public static readonly string PAN_ROOT_PATH = "Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/ScaleRoot/PanRoot";
|
||||
|
||||
private static Dictionary<string, NewHorizonsBody> _astroIdToBody = new Dictionary<string, NewHorizonsBody>();
|
||||
|
||||
public static NewHorizonsBody GetConfigFromID(string id)
|
||||
{
|
||||
return _astroIdToBody.ContainsKey(id) ? _astroIdToBody[id] : null;
|
||||
}
|
||||
|
||||
public static void AddConfig(string id, NewHorizonsBody body)
|
||||
{
|
||||
if (!_astroIdToBody.ContainsKey(id))
|
||||
{
|
||||
_astroIdToBody.Add(id, body);
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAstroObjectId(NewHorizonsBody body)
|
||||
{
|
||||
if (_astroIdToBody.ContainsValue(body))
|
||||
{
|
||||
return CollectionUtilities.KeyByValue(_astroIdToBody, body);
|
||||
}
|
||||
else
|
||||
{
|
||||
return body.Config.Name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,8 @@ using UnityEngine;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
using Object = UnityEngine.Object;
|
||||
using NewHorizons.Handlers;
|
||||
using NewHorizons.Builder.ShipLog;
|
||||
using NewHorizons.Builder.Handlers;
|
||||
|
||||
namespace NewHorizons.Tools
|
||||
{
|
||||
@ -409,25 +411,25 @@ namespace NewHorizons.Tools
|
||||
{
|
||||
if (body.Config.ShipLog?.curiosities != null)
|
||||
{
|
||||
ShipLogBuilder.RumorModeBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities);
|
||||
RumorModeBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities);
|
||||
}
|
||||
}
|
||||
foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem])
|
||||
{
|
||||
if (body.Config.ShipLog?.xmlFile != null)
|
||||
{
|
||||
ShipLogBuilder.RumorModeBuilder.AddBodyToShipLog(__instance, body);
|
||||
RumorModeBuilder.AddBodyToShipLog(__instance, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnShipLogManagerAwakeComplete(ShipLogManager __instance)
|
||||
{
|
||||
ShipLogBuilder.RumorModeBuilder.GenerateEntryData(__instance);
|
||||
RumorModeBuilder.GenerateEntryData(__instance);
|
||||
for (var i = 0; i < __instance._entryList.Count; i++)
|
||||
{
|
||||
ShipLogEntry logEntry = __instance._entryList[i];
|
||||
ShipLogBuilder.RumorModeBuilder.UpdateEntryCuriosity(ref logEntry);
|
||||
RumorModeBuilder.UpdateEntryCuriosity(ref logEntry);
|
||||
}
|
||||
Logger.Log("Ship Log Generation Complete For: " + Main.Instance.CurrentStarSystem, Logger.LogType.Log);
|
||||
}
|
||||
@ -472,7 +474,7 @@ namespace NewHorizons.Tools
|
||||
__instance.RevealFact(fact, false, false);
|
||||
}
|
||||
}
|
||||
ShipLogBuilder.EntryLocationBuilder.InitializeLocations();
|
||||
EntryLocationBuilder.InitializeLocations();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -485,23 +487,23 @@ namespace NewHorizons.Tools
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = ShipLogBuilder.RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight);
|
||||
__result = RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static void DeleteDetail(string name)
|
||||
{
|
||||
Object.Destroy(GameObject.Find(ShipLogBuilder.PAN_ROOT_PATH + "/" + name));
|
||||
Object.Destroy(GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + name));
|
||||
}
|
||||
|
||||
public static void OnShipLogMapModeInitialize(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.MapModeBuilder.ConstructMapMode(Main.Instance.CurrentStarSystem, panRoot, sunObject.layer);
|
||||
GameObject panRoot = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH);
|
||||
GameObject sunObject = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/Sun");
|
||||
ShipLogAstroObject[][] navMatrix = 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!).");
|
||||
@ -530,7 +532,7 @@ namespace NewHorizons.Tools
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = ShipLogBuilder.MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID());
|
||||
__result = MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
25
NewHorizons/Utility/CollectionUtilities.cs
Normal file
25
NewHorizons/Utility/CollectionUtilities.cs
Normal file
@ -0,0 +1,25 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NewHorizons.Utility
|
||||
{
|
||||
public static class CollectionUtilities
|
||||
{
|
||||
public static T KeyByValue<T, W>(Dictionary<T, W> dict, W val)
|
||||
{
|
||||
T key = default;
|
||||
foreach (KeyValuePair<T, W> pair in dict)
|
||||
{
|
||||
if (EqualityComparer<W>.Default.Equals(pair.Value, val))
|
||||
{
|
||||
key = pair.Key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user