mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
commit
616c577b7a
1
.gitignore
vendored
1
.gitignore
vendored
@ -7,3 +7,4 @@ zip
|
||||
*.zip
|
||||
|
||||
*/Build/*
|
||||
.idea/
|
||||
|
||||
BIN
NewHorizons/AssetBundle/DefaultMapModNoAtmo.png
Normal file
BIN
NewHorizons/AssetBundle/DefaultMapModNoAtmo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 69 KiB |
BIN
NewHorizons/AssetBundle/DefaultMapModePlanet.png
Normal file
BIN
NewHorizons/AssetBundle/DefaultMapModePlanet.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
NewHorizons/AssetBundle/DefaultMapModeStar.png
Normal file
BIN
NewHorizons/AssetBundle/DefaultMapModeStar.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
@ -31,7 +31,7 @@ namespace NewHorizons.Atmosphere
|
||||
new Keyframe(surfaceSize - 0.5f, 0),
|
||||
new Keyframe(surfaceSize, 10f),
|
||||
new Keyframe(atmoSize, 0f)
|
||||
});
|
||||
});
|
||||
|
||||
rainGO.GetComponent<PlanetaryVectionController>().SetValue("_activeInSector", sector);
|
||||
rainGO.GetComponent<PlanetaryVectionController>().SetValue("_exclusionSectors", new Sector[] { });
|
||||
|
||||
@ -39,7 +39,6 @@ namespace NewHorizons.Builder.Body
|
||||
tempArray[i] = new Material(GDSharedMaterials[i]);
|
||||
if (module.Tint != null)
|
||||
{
|
||||
tempArray[i].color = module.Tint.ToColor32();
|
||||
tempArray[i].color = module.Tint.ToColor();
|
||||
tempArray[i].SetColor("_FogColor", module.Tint.ToColor());
|
||||
}
|
||||
@ -82,11 +81,11 @@ namespace NewHorizons.Builder.Body
|
||||
fogGO.name = "OceanFog";
|
||||
fogGO.transform.localPosition = Vector3.zero;
|
||||
fogGO.transform.localScale = Vector3.one;
|
||||
|
||||
if (module.Tint != null)
|
||||
{
|
||||
var adjustedColour = module.Tint.ToColor() / 4f;
|
||||
adjustedColour.a = adjustedColour.a * 4f;
|
||||
|
||||
fogGO.GetComponent<MeshRenderer>().material.color = adjustedColour;
|
||||
}
|
||||
|
||||
|
||||
@ -8,8 +8,10 @@ using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
using System.Reflection;
|
||||
using NewHorizons.Builder.General;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using NewHorizons.Builder.ShipLog;
|
||||
|
||||
namespace NewHorizons.Builder.Props
|
||||
{
|
||||
@ -53,6 +55,20 @@ namespace NewHorizons.Builder.Props
|
||||
DialogueBuilder.Make(go, sector, dialogueInfo, mod);
|
||||
}
|
||||
}
|
||||
if (config.Props.Reveal != null)
|
||||
{
|
||||
foreach (var revealInfo in config.Props.Reveal)
|
||||
{
|
||||
RevealBuilder.Make(go, sector, revealInfo, mod);
|
||||
}
|
||||
}
|
||||
if (config.Props.EntryLocation != null)
|
||||
{
|
||||
foreach (var entryLocationInfo in config.Props.EntryLocation)
|
||||
{
|
||||
EntryLocationBuilder.Make(go, sector, entryLocationInfo, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static GameObject LoadPrefab(string assetBundle, string path, string uniqueModName, IModAssets assets)
|
||||
|
||||
@ -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;
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
557
NewHorizons/Builder/ShipLog/MapModeBuilder.cs
Normal file
557
NewHorizons/Builder/ShipLog/MapModeBuilder.cs
Normal file
@ -0,0 +1,557 @@
|
||||
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;
|
||||
using System;
|
||||
|
||||
namespace NewHorizons.Builder.ShipLog
|
||||
{
|
||||
public static class MapModeBuilder
|
||||
{
|
||||
#region General
|
||||
public static ShipLogAstroObject[][] ConstructMapMode(string systemName, GameObject transformParent, ShipLogAstroObject[][] currentNav, int layer)
|
||||
{
|
||||
Material greyScaleMaterial = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/Sprite").GetComponent<Image>().material;
|
||||
List<NewHorizonsBody> bodies = Main.BodyDict[systemName].Where(
|
||||
b => (b.Config.ShipLog?.mapMode?.remove ?? false) == false
|
||||
).ToList();
|
||||
bool flagManualPositionUsed = systemName == "SolarSystem";
|
||||
bool flagAutoPositionUsed = false;
|
||||
foreach (NewHorizonsBody body in bodies.Where(b => ShipLogHandler.IsVanillaBody(b) == false))
|
||||
{
|
||||
if (body.Config.ShipLog == null) continue;
|
||||
|
||||
if (body.Config.ShipLog?.mapMode?.manualPosition == null)
|
||||
{
|
||||
flagAutoPositionUsed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
flagManualPositionUsed = true;
|
||||
if (body.Config.ShipLog?.mapMode?.manualNavigationPosition == null)
|
||||
{
|
||||
Logger.LogError("Navigation position is missing for: " + body.Config.Name);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(flagManualPositionUsed)
|
||||
{
|
||||
if (flagAutoPositionUsed && flagManualPositionUsed)
|
||||
Logger.LogWarning("Can't mix manual and automatic layout of ship log map mode, defaulting to manual");
|
||||
return ConstructMapModeManual(bodies, transformParent, greyScaleMaterial, currentNav, layer);
|
||||
}
|
||||
else if (flagAutoPositionUsed)
|
||||
{
|
||||
return ConstructMapModeAuto(bodies, transformParent, greyScaleMaterial, layer);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static string GetAstroBodyShipLogName(string id)
|
||||
{
|
||||
return ShipLogHandler.GetNameFromAstroID(id) ?? id;
|
||||
}
|
||||
|
||||
private static GameObject CreateImage(GameObject nodeGO, IModAssets assets, Texture2D texture, 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>();
|
||||
|
||||
Rect rect = new Rect(0, 0, texture.width, texture.height);
|
||||
Vector2 pivot = new Vector2(texture.width / 2, texture.height / 2);
|
||||
newImage.sprite = Sprite.Create(texture, rect, pivot);
|
||||
|
||||
return newImageGO;
|
||||
}
|
||||
|
||||
private static GameObject CreateMapModeGameObject(NewHorizonsBody body, GameObject parent, int layer, Vector2 position)
|
||||
{
|
||||
GameObject newGameObject = new GameObject(body.Config.Name + "_ShipLog");
|
||||
newGameObject.layer = layer;
|
||||
newGameObject.transform.SetParent(parent.transform);
|
||||
|
||||
RectTransform transform = newGameObject.AddComponent<RectTransform>();
|
||||
float scale = body.Config.ShipLog?.mapMode?.scale ?? 1f;
|
||||
transform.localPosition = position;
|
||||
transform.localRotation = Quaternion.identity;
|
||||
transform.localScale = Vector3.one * scale;
|
||||
transform.SetAsFirstSibling();
|
||||
return newGameObject;
|
||||
}
|
||||
|
||||
private static ShipLogAstroObject AddShipLogAstroObject(GameObject gameObject, NewHorizonsBody body, Material greyScaleMaterial, int layer)
|
||||
{
|
||||
const float unviewedIconOffset = 15;
|
||||
|
||||
GameObject unviewedReference = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/TimberHearth/UnviewedIcon");
|
||||
|
||||
ShipLogAstroObject astroObject = gameObject.AddComponent<ShipLogAstroObject>();
|
||||
astroObject._id = ShipLogHandler.GetAstroObjectId(body);
|
||||
|
||||
Texture2D image;
|
||||
Texture2D outline;
|
||||
|
||||
string imagePath = body.Config.ShipLog?.mapMode?.revealedSprite;
|
||||
string outlinePath = body.Config.ShipLog?.mapMode?.outlineSprite;
|
||||
|
||||
if (imagePath != null) image = body.Mod.Assets.GetTexture(imagePath);
|
||||
else image = AutoGenerateMapModePicture(body);
|
||||
|
||||
if (outlinePath != null) outline = body.Mod.Assets.GetTexture(outlinePath);
|
||||
else outline = ImageUtilities.MakeOutline(image, Color.white, 10);
|
||||
|
||||
astroObject._imageObj = CreateImage(gameObject, body.Mod.Assets, image, body.Config.Name + " Revealed", layer);
|
||||
astroObject._outlineObj = CreateImage(gameObject, body.Mod.Assets, outline, body.Config.Name + " Outline", layer);
|
||||
if (ShipLogHandler.BodyHasEntries(body))
|
||||
{
|
||||
Image revealedImage = astroObject._imageObj.GetComponent<Image>();
|
||||
astroObject._greyscaleMaterial = greyScaleMaterial;
|
||||
revealedImage.material = greyScaleMaterial;
|
||||
revealedImage.color = Color.white;
|
||||
astroObject._image = revealedImage;
|
||||
}
|
||||
|
||||
astroObject._unviewedObj = GameObject.Instantiate(unviewedReference, gameObject.transform, false);
|
||||
astroObject._invisibleWhenHidden = body.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);
|
||||
return astroObject;
|
||||
}
|
||||
#endregion
|
||||
|
||||
# region Details
|
||||
private static void MakeDetail(ShipLogModule.ShipLogDetailInfo info, Transform parent, NewHorizonsBody body, Material greyScaleMaterial)
|
||||
{
|
||||
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));
|
||||
|
||||
Texture2D image;
|
||||
Texture2D outline;
|
||||
|
||||
string imagePath = info.revealedSprite;
|
||||
string outlinePath = info.outlineSprite;
|
||||
|
||||
if (imagePath != null) image = body.Mod.Assets.GetTexture(imagePath);
|
||||
else image = AutoGenerateMapModePicture(body);
|
||||
|
||||
if (outlinePath != null) outline = body.Mod.Assets.GetTexture(outlinePath);
|
||||
else outline = ImageUtilities.MakeOutline(image, Color.white, 10);
|
||||
|
||||
Image revealedImage = CreateImage(detailGameObject, body.Mod.Assets, image, "Detail Revealed", parent.gameObject.layer).GetComponent<Image>();
|
||||
Image outlineImage = CreateImage(detailGameObject, body.Mod.Assets, outline, "Detail Outline", parent.gameObject.layer).GetComponent<Image>();
|
||||
|
||||
ShipLogDetail detail = detailGameObject.AddComponent<ShipLogDetail>();
|
||||
detail.Init(info, revealedImage, outlineImage, greyScaleMaterial);
|
||||
detailGameObject.SetActive(true);
|
||||
}
|
||||
|
||||
private static void MakeDetails(NewHorizonsBody body, Transform parent, Material greyScaleMaterial)
|
||||
{
|
||||
if (body.Config.ShipLog?.mapMode?.details?.Length > 0)
|
||||
{
|
||||
GameObject detailsParent = new GameObject("Details");
|
||||
detailsParent.transform.SetParent(parent);
|
||||
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 body.Config.ShipLog.mapMode.details)
|
||||
{
|
||||
MakeDetail(detailInfo, detailsTransform, body, greyScaleMaterial);
|
||||
}
|
||||
detailsParent.SetActive(true);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Manual Map Mode
|
||||
private static ShipLogAstroObject[][] ConstructMapModeManual(List<NewHorizonsBody> bodies, GameObject transformParent, Material greyScaleMaterial, ShipLogAstroObject[][] currentNav, int layer)
|
||||
{
|
||||
int maxAmount = bodies.Count + 20;
|
||||
ShipLogAstroObject[][] navMatrix = new ShipLogAstroObject[maxAmount][];
|
||||
for (int i = 0; i < maxAmount; i++)
|
||||
{
|
||||
navMatrix[i] = new ShipLogAstroObject[maxAmount];
|
||||
}
|
||||
|
||||
Dictionary<string, int[]> astroIdToNavIndex = new Dictionary<string, int[]>();
|
||||
|
||||
if (Main.Instance.CurrentStarSystem == "SolarSystem")
|
||||
{
|
||||
|
||||
for (int y = 0; y < currentNav.Length; y++)
|
||||
{
|
||||
for (int x = 0; x < currentNav[y].Length; x++)
|
||||
{
|
||||
navMatrix[y][x] = currentNav[y][x];
|
||||
astroIdToNavIndex.Add(currentNav[y][x].GetID(), new [] {y, x});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach(NewHorizonsBody body in bodies)
|
||||
{
|
||||
if (body.Config.ShipLog?.mapMode?.manualNavigationPosition == null) continue;
|
||||
|
||||
// Sometimes they got other names idk
|
||||
var name = body.Config.Name.Replace(" ", "");
|
||||
var existingBody = AstroObjectLocator.GetAstroObject(body.Config.Name);
|
||||
if (existingBody != null)
|
||||
{
|
||||
var astroName = existingBody.GetAstroObjectName();
|
||||
if (astroName == AstroObject.Name.RingWorld) name = "InvisiblePlanet";
|
||||
else if (astroName != AstroObject.Name.CustomString) name = astroName.ToString();
|
||||
}
|
||||
// Should probably also just fix the IsVanilla method
|
||||
var isVanilla = ShipLogHandler.IsVanillaBody(body);
|
||||
|
||||
if (!isVanilla)
|
||||
{
|
||||
GameObject newMapModeGO = CreateMapModeGameObject(body, transformParent, layer, body.Config.ShipLog?.mapMode?.manualPosition);
|
||||
ShipLogAstroObject newAstroObject = AddShipLogAstroObject(newMapModeGO, body, greyScaleMaterial, layer);
|
||||
MakeDetails(body, newMapModeGO.transform, greyScaleMaterial);
|
||||
Vector2 navigationPosition = body.Config.ShipLog?.mapMode?.manualNavigationPosition;
|
||||
navMatrix[(int)navigationPosition.y][(int)navigationPosition.x] = newAstroObject;
|
||||
}
|
||||
else if (Main.Instance.CurrentStarSystem == "SolarSystem")
|
||||
{
|
||||
GameObject gameObject = GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + name);
|
||||
if (body.Config.Destroy || (body.Config.ShipLog?.mapMode?.remove ?? false))
|
||||
{
|
||||
ShipLogAstroObject astroObject = gameObject.GetComponent<ShipLogAstroObject>();
|
||||
if (astroObject != null)
|
||||
{
|
||||
int[] navIndex = astroIdToNavIndex[astroObject.GetID()];
|
||||
navMatrix[navIndex[0]][navIndex[1]] = null;
|
||||
if (astroObject.GetID() == "CAVE_TWIN" || astroObject.GetID() == "TOWER_TWIN")
|
||||
{
|
||||
GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + "SandFunnel").SetActive(false);
|
||||
}
|
||||
}
|
||||
else if (name == "SandFunnel")
|
||||
{
|
||||
GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + "SandFunnel").SetActive(false);
|
||||
}
|
||||
gameObject.SetActive(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (body.Config.ShipLog?.mapMode?.manualPosition != null)
|
||||
{
|
||||
gameObject.transform.localPosition = (Vector2)body.Config.ShipLog.mapMode.manualPosition;
|
||||
}
|
||||
if (body.Config.ShipLog?.mapMode?.manualNavigationPosition != null)
|
||||
{
|
||||
Vector2 navigationPosition = body.Config.ShipLog?.mapMode?.manualNavigationPosition;
|
||||
navMatrix[(int)navigationPosition.y][(int)navigationPosition.x] = gameObject.GetComponent<ShipLogAstroObject>();
|
||||
}
|
||||
if (body.Config.ShipLog?.mapMode?.scale != null)
|
||||
{
|
||||
gameObject.transform.localScale = Vector3.one * body.Config.ShipLog.mapMode.scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
navMatrix = navMatrix.Where(a => a.Count(c => c != null && c.gameObject != null) > 0).Prepend(new ShipLogAstroObject[1]).ToArray();
|
||||
for (var index = 0; index < navMatrix.Length; index++)
|
||||
{
|
||||
navMatrix[index] = navMatrix[index].Where(a => a != null && a.gameObject != null).ToArray();
|
||||
}
|
||||
|
||||
return navMatrix;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Automatic Map Mode
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
private static ShipLogAstroObject[][] ConstructMapModeAuto(List<NewHorizonsBody> bodies, GameObject transformParent, Material greyScaleMaterial, int layer)
|
||||
{
|
||||
MapModeObject rootObject = ConstructPrimaryNode(bodies);
|
||||
if (rootObject.mainBody != null)
|
||||
{
|
||||
MakeAllNodes(ref rootObject, transformParent, greyScaleMaterial, layer);
|
||||
}
|
||||
|
||||
int maxAmount = bodies.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, Material greyScaleMaterial, int layer)
|
||||
{
|
||||
MakeNode(ref parentNode, parent, greyScaleMaterial, layer);
|
||||
for (var i = 0; i < parentNode.children.Count; i++)
|
||||
{
|
||||
MapModeObject child = parentNode.children[i];
|
||||
MakeAllNodes(ref child, parent, greyScaleMaterial, layer);
|
||||
parentNode.children[i] = child;
|
||||
}
|
||||
}
|
||||
|
||||
private static MapModeObject ConstructPrimaryNode(List<NewHorizonsBody> bodies)
|
||||
{
|
||||
foreach (NewHorizonsBody body in bodies.Where(b => b.Config.Base.CenterOfSolarSystem))
|
||||
{
|
||||
bodies.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(newNode, bodies);
|
||||
return newNode;
|
||||
}
|
||||
Logger.LogError("Couldn't find center of system!");
|
||||
return new MapModeObject();
|
||||
}
|
||||
|
||||
private static List<MapModeObject> ConstructChildrenNodes(MapModeObject parent, List<NewHorizonsBody> searchList, string secondaryName = "")
|
||||
{
|
||||
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 || b.Config.Name == secondaryName))
|
||||
{
|
||||
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
|
||||
};
|
||||
string newSecondaryName = "";
|
||||
if (body.Config.FocalPoint != null)
|
||||
{
|
||||
newNode.mainBody = searchList.Find(b => b.Config.Name == body.Config.FocalPoint.Primary);
|
||||
newSecondaryName = searchList.Find(b => b.Config.Name == body.Config.FocalPoint.Secondary).Config.Name;
|
||||
}
|
||||
|
||||
newNode.children = ConstructChildrenNodes(newNode, searchList, newSecondaryName);
|
||||
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;
|
||||
}
|
||||
|
||||
private static void ConnectNodeToLastSibling(MapModeObject node, Material greyScaleMaterial)
|
||||
{
|
||||
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.12f);
|
||||
|
||||
ShipLogModule.ShipLogDetailInfo linkDetailInfo = new ShipLogModule.ShipLogDetailInfo()
|
||||
{
|
||||
invisibleWhenHidden = node.mainBody.Config.ShipLog?.mapMode?.invisibleWhenHidden ?? false
|
||||
};
|
||||
|
||||
ShipLogDetail linkDetail = newLink.AddComponent<ShipLogDetail>();
|
||||
linkDetail.Init(linkDetailInfo, linkImage, linkImage, greyScaleMaterial);
|
||||
|
||||
transform.SetParent(node.astroObject.transform);
|
||||
transform.SetAsFirstSibling();
|
||||
newLink.SetActive(true);
|
||||
}
|
||||
|
||||
private static void MakeNode(ref MapModeObject node, GameObject parent, Material greyScaleMaterial, int layer)
|
||||
{
|
||||
const float padding = 50f;
|
||||
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.parent != null)
|
||||
{
|
||||
var branchDistance = node.parent.children.IndexOf(node);
|
||||
var goingUp = node.parent.level % 2 != 0;
|
||||
|
||||
if(goingUp && branchDistance == 0) position.y += (int)padding;
|
||||
if(!goingUp && branchDistance == 0) position.x += (int)padding;
|
||||
}
|
||||
|
||||
if (node.level % 2 == 0)
|
||||
{
|
||||
position.y += padding * (node.y - node.lastSibling.y) + extraDistance;
|
||||
}
|
||||
else
|
||||
{
|
||||
position.x += padding * (node.x - node.lastSibling.x) + extraDistance;
|
||||
}
|
||||
}
|
||||
GameObject newNodeGO = CreateMapModeGameObject(node.mainBody, parent, layer, position);
|
||||
ShipLogAstroObject astroObject = AddShipLogAstroObject(newNodeGO, node.mainBody, greyScaleMaterial, layer);
|
||||
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;
|
||||
}
|
||||
node.astroObject = astroObject;
|
||||
if (node.lastSibling != null) ConnectNodeToLastSibling(node, greyScaleMaterial);
|
||||
MakeDetails(node.mainBody, newNodeGO.transform, greyScaleMaterial);
|
||||
}
|
||||
#endregion
|
||||
|
||||
private static Texture2D AutoGenerateMapModePicture(NewHorizonsBody body)
|
||||
{
|
||||
Texture2D texture;
|
||||
|
||||
if(body.Config.Star != null) texture = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/DefaultMapModeStar.png");
|
||||
else if(body.Config.Atmosphere != null) texture = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/DefaultMapModNoAtmo.png");
|
||||
else texture = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/DefaultMapModePlanet.png");
|
||||
|
||||
var color = GetDominantPlanetColor(body);
|
||||
var darkColor = new Color(color.r / 3f, color.g / 3f, color.b / 3f);
|
||||
|
||||
texture = ImageUtilities.LerpGreyscaleImage(texture, color, darkColor);
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
private static Color GetDominantPlanetColor(NewHorizonsBody body)
|
||||
{
|
||||
var starColor = body.Config?.Star?.Tint;
|
||||
if (starColor != null) return starColor.ToColor();
|
||||
|
||||
var atmoColor = body.Config.Atmosphere?.AtmosphereTint;
|
||||
if (body.Config.Atmosphere?.Cloud != null) return atmoColor.ToColor();
|
||||
|
||||
if (body.Config?.HeightMap?.TextureMap != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var texture = body.Mod.Assets.GetTexture(body.Config.HeightMap.TextureMap);
|
||||
var landColor = ImageUtilities.GetAverageColor(texture);
|
||||
if (landColor != null) return landColor;
|
||||
}
|
||||
catch (Exception) { }
|
||||
}
|
||||
|
||||
var waterColor = body.Config.Water?.Tint;
|
||||
if (waterColor != null) return waterColor.ToColor();
|
||||
|
||||
var lavaColor = body.Config.Lava?.Tint;
|
||||
if (lavaColor != null) return lavaColor.ToColor();
|
||||
|
||||
var sandColor = body.Config.Sand?.Tint;
|
||||
if (sandColor != null) return sandColor.ToColor();
|
||||
|
||||
return Color.white;
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
236
NewHorizons/Builder/ShipLog/RumorModeBuilder.cs
Normal file
236
NewHorizons/Builder/ShipLog/RumorModeBuilder.cs
Normal file
@ -0,0 +1,236 @@
|
||||
using System;
|
||||
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 Dictionary<CuriosityName, Color> _curiosityColors;
|
||||
private static Dictionary<CuriosityName, Color> _curiosityHighlightColors;
|
||||
private static Dictionary<string, CuriosityName> _rawNameToCuriosityName;
|
||||
private static Dictionary<string, string> _entryIdToRawName;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_curiosityColors = new Dictionary<CuriosityName, Color>();
|
||||
_curiosityHighlightColors = new Dictionary<CuriosityName, Color>();
|
||||
_rawNameToCuriosityName = new Dictionary<string, CuriosityName>();
|
||||
_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(body.Mod.Manifest.ModFolderPath + "/" + body.Config.ShipLog.xmlFile);
|
||||
XElement astroBodyId = astroBodyFile.Element("ID");
|
||||
if (astroBodyId == null)
|
||||
{
|
||||
Logger.LogError("Failed to load ship logs for " + systemName + "!");
|
||||
}
|
||||
else
|
||||
{
|
||||
var entryIDs = new List<string>();
|
||||
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)
|
||||
{
|
||||
entryIDs.Add(id.Value);
|
||||
_entryIdToRawName.Add(id.Value, curiosityName.Value);
|
||||
}
|
||||
foreach (XElement childEntryElement in entryElement.Elements("Entry"))
|
||||
{
|
||||
XElement childCuriosityName = childEntryElement.Element("Curiosity");
|
||||
XElement childId = childEntryElement.Element("ID");
|
||||
if (childId != null && _entryIdToRawName.ContainsKey(childId.Value))
|
||||
{
|
||||
if (childCuriosityName == null && curiosityName != null)
|
||||
{
|
||||
_entryIdToRawName.Add(childId.Value, curiosityName.Value);
|
||||
}
|
||||
else if (childCuriosityName != null)
|
||||
{
|
||||
_entryIdToRawName.Add(childId.Value, childCuriosityName.Value);
|
||||
}
|
||||
entryIDs.Add(childId.Value);
|
||||
}
|
||||
AddTranslation(childEntryElement);
|
||||
}
|
||||
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, entryIDs, 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.GetConfigFromEntryID(entry._id);
|
||||
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, true),
|
||||
altSprite = body.Config.ShipLog.spriteFolder == null ? null : GetEntrySprite(entry._id + "_ALT", body, false)
|
||||
};
|
||||
entry.SetSprite(newData.sprite == null ? manager._shipLogLibrary.defaultEntrySprite : newData.sprite);
|
||||
entry.SetAltSprite(newData.sprite == null ? manager._shipLogLibrary.defaultEntrySprite : newData.altSprite);
|
||||
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"))
|
||||
{
|
||||
AddTranslationForElement(rumorFact, "RumorName", string.Empty, table);
|
||||
AddTranslationForElement(rumorFact, "Text", name, table);
|
||||
AddTranslationForAltText(rumorFact, name, table);
|
||||
}
|
||||
foreach (XElement exploreFact in entry.Elements("ExploreFact"))
|
||||
{
|
||||
AddTranslationForElement(exploreFact, "Text", name, table);
|
||||
AddTranslationForAltText(exploreFact, name, table);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddTranslationForElement(XElement parent, string elementName, string keyName, Dictionary<string, string> table)
|
||||
{
|
||||
XElement element = parent.Element(elementName);
|
||||
if (element != null)
|
||||
{
|
||||
table[keyName + element.Value] = element.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private static void AddTranslationForAltText(XElement fact, string keyName, Dictionary<string, string> table)
|
||||
{
|
||||
XElement altText = fact.Element("AltText");
|
||||
if (altText != null)
|
||||
{
|
||||
AddTranslationForElement(altText, "Text", keyName, table);
|
||||
}
|
||||
}
|
||||
|
||||
public static void UpdateEntryCuriosity(ref ShipLogEntry entry)
|
||||
{
|
||||
if (_entryIdToRawName.ContainsKey(entry._id))
|
||||
{
|
||||
var raw = _entryIdToRawName[entry._id];
|
||||
if (_rawNameToCuriosityName.ContainsKey(raw))
|
||||
{
|
||||
entry._curiosity = _rawNameToCuriosityName[raw];
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError($"Couldn't find {raw}. Did you define the curiosity in a json config? Because you have to.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Sprite GetEntrySprite(string entryId, NewHorizonsBody body, bool logError)
|
||||
{
|
||||
string relativePath = body.Config.ShipLog.spriteFolder + "/" + entryId + ".png";
|
||||
try
|
||||
{
|
||||
Texture2D newTexture = body.Mod.Assets.GetTexture(relativePath);
|
||||
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);
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
if(logError) Logger.LogError($"Couldn't load image for {entryId} at {relativePath}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Vector2? GetManualEntryPosition(string entryId, ShipLogModule config)
|
||||
{
|
||||
if (config.entryPositions == null) return null;
|
||||
foreach (ShipLogModule.EntryPositionInfo position in config.entryPositions)
|
||||
{
|
||||
if (position.id == entryId)
|
||||
{
|
||||
return position.position;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
60
NewHorizons/Components/ShipLogDetail.cs
Normal file
60
NewHorizons/Components/ShipLogDetail.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using NewHorizons.External;
|
||||
using OWML.Common;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.Components
|
||||
{
|
||||
public class ShipLogDetail : MonoBehaviour
|
||||
{
|
||||
private Image _revealedImage;
|
||||
private Image _outlineImage;
|
||||
private Material _greyScaleMaterial;
|
||||
private ShipLogModule.ShipLogDetailInfo _detailInfo;
|
||||
|
||||
public void Init(ShipLogModule.ShipLogDetailInfo info, Image revealed, Image outline, Material greyScale)
|
||||
{
|
||||
_detailInfo = info;
|
||||
_revealedImage = revealed;
|
||||
_outlineImage = outline;
|
||||
_greyScaleMaterial = greyScale;
|
||||
_revealedImage.enabled = false;
|
||||
_outlineImage.enabled = false;
|
||||
}
|
||||
|
||||
public void UpdateState(ShipLogEntry.State parentState)
|
||||
{
|
||||
switch (parentState)
|
||||
{
|
||||
case ShipLogEntry.State.Explored:
|
||||
_outlineImage.enabled = false;
|
||||
_revealedImage.enabled = true;
|
||||
SetGreyScale(false);
|
||||
break;
|
||||
case ShipLogEntry.State.Rumored:
|
||||
_outlineImage.enabled = false;
|
||||
_revealedImage.enabled = true;
|
||||
SetGreyScale(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;
|
||||
default:
|
||||
Logger.LogError("Invalid ShipLogEntryState for " + _revealedImage.transform.parent.parent.gameObject.name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetGreyScale(bool greyScale)
|
||||
{
|
||||
_revealedImage.material = (greyScale ? _greyScaleMaterial : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
1
NewHorizons/External/IPlanetConfig.cs
vendored
1
NewHorizons/External/IPlanetConfig.cs
vendored
@ -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; }
|
||||
|
||||
2
NewHorizons/External/PlanetConfig.cs
vendored
2
NewHorizons/External/PlanetConfig.cs
vendored
@ -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; }
|
||||
@ -36,6 +37,7 @@ namespace NewHorizons.External
|
||||
// Always have to have a base module
|
||||
Base = new BaseModule();
|
||||
Orbit = new OrbitModule();
|
||||
ShipLog = new ShipLogModule();
|
||||
|
||||
if (dict == null) return;
|
||||
|
||||
|
||||
19
NewHorizons/External/PropModule.cs
vendored
19
NewHorizons/External/PropModule.cs
vendored
@ -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
|
||||
{
|
||||
@ -67,5 +69,22 @@ namespace NewHorizons.External
|
||||
public MVector3 remoteTriggerPosition;
|
||||
public string blockAfterPersistentCondition;
|
||||
}
|
||||
|
||||
public class RevealInfo
|
||||
{
|
||||
public string revealOn = "enter";
|
||||
public string[] reveals;
|
||||
public MVector3 position = new MVector3(0, 0, 0);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
50
NewHorizons/External/ShipLogModule.cs
vendored
Normal file
50
NewHorizons/External/ShipLogModule.cs
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
using NewHorizons.Utility;
|
||||
|
||||
namespace NewHorizons.External
|
||||
{
|
||||
public class ShipLogModule : Module
|
||||
{
|
||||
public string xmlFile;
|
||||
public string spriteFolder;
|
||||
public string[] initialReveal;
|
||||
public MapModeInfo mapMode = new MapModeInfo();
|
||||
public CuriosityColorInfo[] curiosities;
|
||||
public EntryPositionInfo[] entryPositions;
|
||||
|
||||
public class MapModeInfo
|
||||
{
|
||||
public string revealedSprite;
|
||||
public string outlineSprite;
|
||||
public float scale = 1f;
|
||||
public bool invisibleWhenHidden;
|
||||
public float offset = 0f;
|
||||
public MVector2 manualPosition;
|
||||
public MVector2 manualNavigationPosition;
|
||||
public bool remove = false;
|
||||
public ShipLogDetailInfo[] details;
|
||||
}
|
||||
|
||||
public class ShipLogDetailInfo
|
||||
{
|
||||
public string revealedSprite;
|
||||
public string outlineSprite;
|
||||
public float rotation = 0f;
|
||||
public bool invisibleWhenHidden;
|
||||
public MVector2 position;
|
||||
public MVector2 scale;
|
||||
}
|
||||
|
||||
public class CuriosityColorInfo
|
||||
{
|
||||
public string id;
|
||||
public MColor color;
|
||||
public MColor highlightColor;
|
||||
}
|
||||
|
||||
public class EntryPositionInfo
|
||||
{
|
||||
public string id;
|
||||
public MVector2 position;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
NewHorizons/External/SignalModule.cs
vendored
1
NewHorizons/External/SignalModule.cs
vendored
@ -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;
|
||||
|
||||
98
NewHorizons/Handlers/ShipLogHandler.cs
Normal file
98
NewHorizons/Handlers/ShipLogHandler.cs
Normal file
@ -0,0 +1,98 @@
|
||||
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";
|
||||
|
||||
// NewHorizonsBody -> EntryIDs
|
||||
private static Dictionary<NewHorizonsBody, List<string>> _nhBodyToEntryIDs;
|
||||
//EntryID -> NewHorizonsBody
|
||||
private static Dictionary<string, NewHorizonsBody> _entryIDsToNHBody;
|
||||
// NewHorizonsBody -> AstroID
|
||||
private static Dictionary<NewHorizonsBody, string> _nhBodyToAstroIDs;
|
||||
|
||||
private static string[] vanillaBodies;
|
||||
private static string[] vanillaIDs;
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
_nhBodyToEntryIDs = new Dictionary<NewHorizonsBody, List<string>>();
|
||||
_entryIDsToNHBody = new Dictionary<string, NewHorizonsBody>();
|
||||
_nhBodyToAstroIDs = new Dictionary<NewHorizonsBody, string>();
|
||||
|
||||
List<GameObject> gameObjects = SearchUtilities.GetAllChildren(GameObject.Find(PAN_ROOT_PATH));
|
||||
vanillaBodies = gameObjects.ConvertAll(g => g.name).ToArray();
|
||||
vanillaIDs = gameObjects.ConvertAll(g => g.GetComponent<ShipLogAstroObject>()?.GetID()).ToArray();
|
||||
}
|
||||
|
||||
public static bool IsVanillaAstroID(string astroId)
|
||||
{
|
||||
return vanillaIDs.Contains(astroId);
|
||||
}
|
||||
|
||||
public static bool IsVanillaBody(NewHorizonsBody body)
|
||||
{
|
||||
var existingBody = AstroObjectLocator.GetAstroObject(body.Config.Name);
|
||||
if (existingBody != null && existingBody.GetAstroObjectName() != AstroObject.Name.CustomString)
|
||||
return true;
|
||||
|
||||
return vanillaBodies.Contains(body.Config.Name.Replace(" ", ""));
|
||||
}
|
||||
|
||||
public static string GetNameFromAstroID(string astroID)
|
||||
{
|
||||
return CollectionUtilities.KeyByValue(_nhBodyToAstroIDs, astroID)?.Config.Name;
|
||||
}
|
||||
|
||||
public static NewHorizonsBody GetConfigFromEntryID(string entryID)
|
||||
{
|
||||
if (_entryIDsToNHBody.ContainsKey(entryID)) return _entryIDsToNHBody[entryID];
|
||||
else
|
||||
{
|
||||
Logger.LogError($"Couldn't find NewHorizonsBody that corresponds to {entryID}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddConfig(string astroID, List<string> entryIDs, NewHorizonsBody body)
|
||||
{
|
||||
// Nice to be able to just get the AstroID from the body
|
||||
if (!_nhBodyToEntryIDs.ContainsKey(body)) _nhBodyToEntryIDs.Add(body, entryIDs);
|
||||
else Logger.LogWarning($"Possible duplicate shiplog entry {body.Config.Name}");
|
||||
|
||||
// AstroID
|
||||
if (!_nhBodyToAstroIDs.ContainsKey(body)) _nhBodyToAstroIDs.Add(body, astroID);
|
||||
else Logger.LogWarning($"Possible duplicate shiplog entry {astroID} for {body.Config.Name}");
|
||||
|
||||
// EntryID to Body
|
||||
foreach (var entryID in entryIDs)
|
||||
{
|
||||
if (!_entryIDsToNHBody.ContainsKey(entryID)) _entryIDsToNHBody.Add(entryID, body);
|
||||
else Logger.LogWarning($"Possible duplicate shiplog entry {entryID} for {astroID} from NewHorizonsBody {body.Config.Name}");
|
||||
}
|
||||
}
|
||||
|
||||
public static string GetAstroObjectId(NewHorizonsBody body)
|
||||
{
|
||||
if (_nhBodyToAstroIDs.ContainsKey(body)) return _nhBodyToAstroIDs[body];
|
||||
else return body.Config.Name;
|
||||
}
|
||||
|
||||
public static bool BodyHasEntries(NewHorizonsBody body)
|
||||
{
|
||||
return _nhBodyToAstroIDs.ContainsKey(body) && _nhBodyToAstroIDs[body].Length > 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ using NewHorizons.Builder.Body;
|
||||
using NewHorizons.Builder.General;
|
||||
using NewHorizons.Builder.Orbital;
|
||||
using NewHorizons.Builder.Props;
|
||||
using NewHorizons.Builder.ShipLog;
|
||||
using NewHorizons.Builder.Updater;
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.External;
|
||||
@ -14,17 +15,12 @@ using NewHorizons.Utility;
|
||||
using OWML.Common;
|
||||
using OWML.ModHelper;
|
||||
using OWML.Utils;
|
||||
using PacificEngine.OW_CommonResources.Game.Player;
|
||||
using PacificEngine.OW_CommonResources.Game.Resource;
|
||||
using PacificEngine.OW_CommonResources.Game.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UI;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons
|
||||
@ -67,6 +63,7 @@ namespace NewHorizons
|
||||
Tools.Patches.Apply();
|
||||
Tools.WarpDrivePatches.Apply();
|
||||
Tools.OWCameraFix.Apply();
|
||||
Tools.ShipLogPatches.Apply();
|
||||
|
||||
Logger.Log("Begin load of config files...", Logger.LogType.Log);
|
||||
|
||||
@ -79,7 +76,7 @@ namespace NewHorizons
|
||||
Logger.LogWarning("Couldn't find planets folder");
|
||||
}
|
||||
|
||||
UnityEngine.Random.InitState((int)DateTime.Now.Ticks);
|
||||
//UnityEngine.Random.InitState((int)DateTime.Now.Ticks);
|
||||
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single));
|
||||
}
|
||||
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ProjectView>ProjectFiles</ProjectView>
|
||||
<OutputPath>$(AppData)\OuterWildsModManager\OWML\Mods\xen.NewHorizons</OutputPath>
|
||||
<OuterWildsModsDirectory>$(AppData)\OuterWildsModManager\OWML\Mods</OuterWildsModsDirectory>
|
||||
<OutputPath>$(AppData)\OuterWildsModManager\OWML\Mods\xen.NewHorizons</OutputPath>
|
||||
<OuterWildsModsDirectory>$(AppData)\OuterWildsModManager\OWML\Mods</OuterWildsModsDirectory>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@ -5,11 +5,20 @@ 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;
|
||||
using NewHorizons.Handlers;
|
||||
using NewHorizons.Builder.ShipLog;
|
||||
using NewHorizons.Builder.Handlers;
|
||||
|
||||
namespace NewHorizons.Tools
|
||||
{
|
||||
|
||||
215
NewHorizons/Tools/ShipLogPatches.cs
Normal file
215
NewHorizons/Tools/ShipLogPatches.cs
Normal file
@ -0,0 +1,215 @@
|
||||
using NewHorizons.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NewHorizons.Utility;
|
||||
using UnityEngine;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
using Object = UnityEngine.Object;
|
||||
using NewHorizons.Builder.ShipLog;
|
||||
using NewHorizons.Builder.Handlers;
|
||||
|
||||
namespace NewHorizons.Tools
|
||||
{
|
||||
public static class ShipLogPatches
|
||||
{
|
||||
public static void Apply()
|
||||
{
|
||||
var playerDataGetNewlyRevealedFactIDs = typeof(PlayerData).GetMethod("GetNewlyRevealedFactIDs");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix(playerDataGetNewlyRevealedFactIDs, typeof(ShipLogPatches), nameof(ShipLogPatches.OnPlayerDataGetNewlyRevealedFactIDsComplete));
|
||||
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogManager>("Awake", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogManagerAwake));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogManager>("Start", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogManagerStart));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogManager>("IsFactRevealed", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogManagerIsFactRevealed));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogManager>("CheckForCompletionAchievement", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogManagerCheckForCompletionAchievement));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<UIStyleManager>("GetCuriosityColor", typeof(ShipLogPatches), nameof(ShipLogPatches.OnUIStyleManagerGetCuriosityColor));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogSandFunnel>("Awake", typeof(ShipLogPatches), nameof(ShipLogPatches.DisableShipLogSandFunnel));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogSandFunnel>("UpdateState", typeof(ShipLogPatches), nameof(ShipLogPatches.DisableShipLogSandFunnel));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogAstroObject>("GetName", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogAstroObjectGetName));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<ShipLogMapMode>("Initialize", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogMapModeInitialize));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<ShipLogManager>("Awake", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogManagerAwakeComplete));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<ShipLogAstroObject>("UpdateState", typeof(ShipLogPatches), nameof(ShipLogPatches.OnShipLogAstroObjectUpdateState));
|
||||
}
|
||||
|
||||
public static void OnShipLogManagerAwake(ShipLogManager __instance)
|
||||
{
|
||||
RumorModeBuilder.Init();
|
||||
ShipLogHandler.Init();
|
||||
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<ShipLogEntryLocation>())
|
||||
{
|
||||
logEntryLocation._initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem])
|
||||
{
|
||||
if (body.Config.ShipLog?.curiosities != null)
|
||||
{
|
||||
RumorModeBuilder.AddCuriosityColors(body.Config.ShipLog.curiosities);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem])
|
||||
{
|
||||
if (body.Config.ShipLog?.xmlFile != null)
|
||||
{
|
||||
RumorModeBuilder.AddBodyToShipLog(__instance, body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnShipLogManagerAwakeComplete(ShipLogManager __instance)
|
||||
{
|
||||
RumorModeBuilder.GenerateEntryData(__instance);
|
||||
for (var i = 0; i < __instance._entryList.Count; i++)
|
||||
{
|
||||
ShipLogEntry logEntry = __instance._entryList[i];
|
||||
RumorModeBuilder.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 (__instance._factDict != null && __instance._factDict.ContainsKey(__0))
|
||||
{
|
||||
__result = __instance._factDict[__0].IsRevealed();
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool OnShipLogManagerCheckForCompletionAchievement(ShipLogManager __instance)
|
||||
{
|
||||
foreach (KeyValuePair<string, ShipLogFact> keyValuePair in __instance._factDict)
|
||||
{
|
||||
if (ShipLogHandler.IsVanillaAstroID(__instance.GetEntry(keyValuePair.Value.GetEntryID()).GetAstroObjectID()) && !keyValuePair.Value.IsRumor() && !keyValuePair.Value.IsRevealed() && !keyValuePair.Key.Equals("TH_VILLAGE_X3") && !keyValuePair.Key.Equals("GD_GABBRO_ISLAND_X1") && __instance.GetEntry(keyValuePair.Value.GetEntryID()).GetCuriosityName() != CuriosityName.InvisiblePlanet)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Achievements.Earn(Achievements.Type.STUDIOUS);
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool OnShipLogManagerStart(ShipLogManager __instance)
|
||||
{
|
||||
foreach (NewHorizonsBody body in Main.BodyDict[Main.Instance.CurrentStarSystem])
|
||||
{
|
||||
foreach (string fact in body.Config.ShipLog?.initialReveal ?? Array.Empty<string>())
|
||||
{
|
||||
__instance.RevealFact(fact, false, false);
|
||||
}
|
||||
}
|
||||
|
||||
if (Main.Instance.CurrentStarSystem == "SolarSystem")
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
EntryLocationBuilder.InitializeLocations();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool OnUIStyleManagerGetCuriosityColor(UIStyleManager __instance, CuriosityName __0, bool __1, ref Color __result)
|
||||
{
|
||||
if ((int) __0 < 7)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = RumorModeBuilder.GetCuriosityColor(__0, __1, __instance._neutralColor, __instance._neutralHighlight);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static void OnShipLogMapModeInitialize(ShipLogMapMode __instance)
|
||||
{
|
||||
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, __instance._astroObjects, sunObject.layer);
|
||||
if (navMatrix == null || navMatrix.Length <= 1)
|
||||
{
|
||||
Logger.LogWarning("Skipping Map Mode Generation.");
|
||||
}
|
||||
else
|
||||
{
|
||||
__instance._astroObjects = navMatrix;
|
||||
__instance._startingAstroObjectID = navMatrix[1][0].GetID();
|
||||
if (Main.Instance.CurrentStarSystem != "SolarSystem")
|
||||
{
|
||||
List<GameObject> delete = SearchUtilities.GetAllChildren(panRoot).Where(g => g.name.Contains("_ShipLog") == false).ToList();
|
||||
foreach (GameObject gameObject in delete)
|
||||
{
|
||||
Object.Destroy(GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + gameObject.name));
|
||||
}
|
||||
if (GameObject.Find(ShipLogHandler.PAN_ROOT_PATH + "/" + "SandFunnel") == null)
|
||||
{
|
||||
__instance._sandFunnel = __instance.gameObject.AddComponent<ShipLogSandFunnel>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log("Map Mode Construction Complete", Logger.LogType.Log);
|
||||
}
|
||||
|
||||
public static bool OnShipLogAstroObjectGetName(ShipLogAstroObject __instance, ref string __result)
|
||||
{
|
||||
if (ShipLogHandler.IsVanillaAstroID(__instance.GetID()))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
__result = MapModeBuilder.GetAstroBodyShipLogName(__instance.GetID());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Transform lineObject = __instance.transform.Find("Line_ShipLog");
|
||||
if (lineObject != null)
|
||||
{
|
||||
ShipLogDetail lineDetail = lineObject.gameObject.GetComponent<ShipLogDetail>();
|
||||
lineDetail.UpdateState(__instance._state);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool DisableShipLogSandFunnel()
|
||||
{
|
||||
return Main.Instance.CurrentStarSystem == "SolarSystem";
|
||||
}
|
||||
|
||||
public static void OnPlayerDataGetNewlyRevealedFactIDsComplete(ref List<string> __result)
|
||||
{
|
||||
ShipLogManager manager = Locator.GetShipLogManager();
|
||||
__result = __result.Where(e => manager.GetFact(e) != null).ToList();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -14,9 +14,7 @@ namespace NewHorizons.Tools
|
||||
public static void Apply()
|
||||
{
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipCockpitController>("Update", typeof(WarpDrivePatches), nameof(WarpDrivePatches.OnShipCockpitControllerUpdate));
|
||||
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<ShipLogMapMode>("EnterMode", typeof(WarpDrivePatches), nameof(WarpDrivePatches.OnShipLogMapModeEnterMode));
|
||||
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogController>("Update", typeof(WarpDrivePatches), nameof(WarpDrivePatches.OnShipLogControllerUpdate));
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,7 @@ namespace NewHorizons.Utility
|
||||
public class DebugRaycaster : MonoBehaviour
|
||||
{
|
||||
private OWRigidbody _rb;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_rb = this.GetRequiredComponent<OWRigidbody>();
|
||||
|
||||
@ -1,10 +1,55 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Utility
|
||||
{
|
||||
static class ImageUtilities
|
||||
{
|
||||
public static Texture2D MakeOutline(Texture2D texture, Color color, int thickness)
|
||||
{
|
||||
var outline = new Texture2D(texture.width, texture.height, TextureFormat.ARGB32, false);
|
||||
var outlinePixels = new Color[texture.width * texture.height];
|
||||
var pixels = texture.GetPixels();
|
||||
|
||||
for (int x = 0; x < texture.width; x++)
|
||||
{
|
||||
for (int y = 0; y < texture.height; y++)
|
||||
{
|
||||
var fillColor = new Color(0, 0, 0, 0);
|
||||
|
||||
if(pixels[x + y * texture.width].a == 1 && CloseToTransparent(pixels, texture.width, texture.height, x, y, thickness))
|
||||
{
|
||||
fillColor = color;
|
||||
}
|
||||
outlinePixels[x + y * texture.width] = fillColor;
|
||||
}
|
||||
}
|
||||
|
||||
outline.SetPixels(outlinePixels);
|
||||
outline.Apply();
|
||||
|
||||
return outline;
|
||||
}
|
||||
|
||||
private static bool CloseToTransparent(Color[] pixels, int width, int height, int x, int y, int thickness)
|
||||
{
|
||||
// Check nearby
|
||||
var minX = Math.Max(0, x - thickness/2);
|
||||
var minY = Math.Max(0, y - thickness/2);
|
||||
var maxX = Math.Min(width, x + thickness/2);
|
||||
var maxY = Math.Min(height, y + thickness/2);
|
||||
|
||||
for (int i = minX; i < maxX; i++)
|
||||
{
|
||||
for (int j = minY; j < maxY; j++)
|
||||
{
|
||||
if (pixels[i + j * width].a < 1) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Texture2D TintImage(Texture2D image, Color tint)
|
||||
{
|
||||
var pixels = image.GetPixels();
|
||||
@ -74,49 +119,22 @@ namespace NewHorizons.Utility
|
||||
return tex;
|
||||
}
|
||||
|
||||
// Thank you PETERSVP
|
||||
public static Texture2D Scaled(Texture2D src, int width, int height, FilterMode mode = FilterMode.Trilinear)
|
||||
public static Color GetAverageColor(Texture2D src)
|
||||
{
|
||||
Rect texR = new Rect(0, 0, width, height);
|
||||
_gpu_scale(src, width, height, mode);
|
||||
var pixels = src.GetPixels32();
|
||||
var r = 0f;
|
||||
var g = 0f;
|
||||
var b = 0f;
|
||||
var length = pixels.Length;
|
||||
for(int i = 0; i < pixels.Length; i++)
|
||||
{
|
||||
var color = pixels[i];
|
||||
r += (float)color.r / length;
|
||||
g += (float)color.g / length;
|
||||
b += (float)color.b / length;
|
||||
}
|
||||
|
||||
//Get rendered data back to a new texture
|
||||
Texture2D result = new Texture2D(width, height, TextureFormat.ARGB32, true);
|
||||
result.Resize(width, height);
|
||||
result.ReadPixels(texR, 0, 0, true);
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void Scale(Texture2D tex, int width, int height, FilterMode mode = FilterMode.Trilinear)
|
||||
{
|
||||
Rect texR = new Rect(0, 0, width, height);
|
||||
_gpu_scale(tex, width, height, mode);
|
||||
|
||||
// Update new texture
|
||||
tex.Resize(width, height);
|
||||
tex.ReadPixels(texR, 0, 0, true);
|
||||
tex.Apply(true); //Remove this if you hate us applying textures for you :)
|
||||
}
|
||||
|
||||
// Internal unility that renders the source texture into the RTT - the scaling method itself.
|
||||
static void _gpu_scale(Texture2D src, int width, int height, FilterMode fmode)
|
||||
{
|
||||
//We need the source texture in VRAM because we render with it
|
||||
src.filterMode = fmode;
|
||||
src.Apply(true);
|
||||
|
||||
//Using RTT for best quality and performance. Thanks, Unity 5
|
||||
RenderTexture rtt = new RenderTexture(width, height, 32);
|
||||
|
||||
//Set the RTT in order to render to it
|
||||
Graphics.SetRenderTarget(rtt);
|
||||
|
||||
//Setup 2D matrix in range 0..1, so nobody needs to care about sized
|
||||
GL.LoadPixelMatrix(0, 1, 1, 0);
|
||||
|
||||
//Then clear & draw the texture to fill the entire RTT.
|
||||
GL.Clear(true, true, new Color(0, 0, 0, 0));
|
||||
Graphics.DrawTexture(new Rect(0, 0, 1, 1), src);
|
||||
return new Color(r / 255, g / 255, b / 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
26
NewHorizons/Utility/MVector2.cs
Normal file
26
NewHorizons/Utility/MVector2.cs
Normal file
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -162,5 +162,15 @@ namespace NewHorizons.Utility
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static List<GameObject> GetAllChildren(GameObject parent)
|
||||
{
|
||||
List<GameObject> children = new List<GameObject>();
|
||||
foreach (Transform child in parent.transform)
|
||||
{
|
||||
children.Add(child.gameObject);
|
||||
}
|
||||
return children;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
NewHorizons/dialogue_schema.xsd
Normal file
48
NewHorizons/dialogue_schema.xsd
Normal file
@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<xs:element name="DialogueTree">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="NameField" type="xs:string"/>
|
||||
<xs:element name="DialogueNode" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Name" type="xs:string"/>
|
||||
<xs:element name="EntryCondition" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="Dialogue">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Page" type="xs:string" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="RevealFacts" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="FactID" type="xs:string" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name="DialogueOptionsList" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="DialogueOption" maxOccurs="unbounded">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="RequiredPersistentCondition" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="CancelledPersistentCondition" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="Text" type="xs:string"/>
|
||||
<xs:element name="DialogueTarget" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
@ -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?"
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -680,9 +680,6 @@
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"count": {
|
||||
"type": "integer"
|
||||
},
|
||||
"path": {
|
||||
"type": "string",
|
||||
"description": "Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle"
|
||||
@ -739,6 +736,10 @@
|
||||
"default": false,
|
||||
"description": "For each mesh filter found here should we make a mesh collider?"
|
||||
}
|
||||
},
|
||||
"scale": {
|
||||
"type": "number",
|
||||
"default": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -791,6 +792,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 +975,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 +1247,241 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"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"
|
||||
}
|
||||
},
|
||||
"entryPositions": {
|
||||
"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"
|
||||
},
|
||||
"manualPosition": {
|
||||
"type": "object",
|
||||
"description": "Manually place this planet at the specified position",
|
||||
"properties": {
|
||||
"x": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
},
|
||||
"y": {
|
||||
"type": "number",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"manualNavigationPosition": {
|
||||
"type": "object",
|
||||
"description": "Specify where this planet is in terms of navigation",
|
||||
"properties": {
|
||||
"x": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
},
|
||||
"y": {
|
||||
"type": "integer",
|
||||
"default": 0
|
||||
}
|
||||
}
|
||||
},
|
||||
"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 (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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
65
NewHorizons/shiplog_schema.xsd
Normal file
65
NewHorizons/shiplog_schema.xsd
Normal file
@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
|
||||
<!-- Astro Object Entry Info -->
|
||||
<xs:element name="AstroObjectEntry">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="Entry" maxOccurs="unbounded" type="entryInfo">
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
|
||||
<!-- Entry Info -->
|
||||
<xs:complexType name="entryInfo">
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="Name" type="xs:string"/>
|
||||
<xs:element name="Curiosity" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="IsCuriosity" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="IgnoreMoreToExplore" minOccurs="0"/>
|
||||
<xs:element name="IgnoreMoreToExploreCondition" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="AltPhotoCondition" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="RumorFact" type="rumorFactInfo" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="ExploreFact" type="exploreFactInfo" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="Entry" type="entryInfo" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- Rumor Fact Info -->
|
||||
<xs:complexType name="rumorFactInfo">
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="SourceID" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="RumorName" type="xs:string" minOccurs="0"/>
|
||||
<xs:element name="RumorNamePriority" type="xs:int" minOccurs="0"/>
|
||||
<xs:element name="IgnoreMoreToExplore" minOccurs="0"/>
|
||||
<xs:group ref="textData"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- Explore Fact Info -->
|
||||
<xs:complexType name="exploreFactInfo">
|
||||
<xs:sequence>
|
||||
<xs:element name="ID" type="xs:string"/>
|
||||
<xs:element name="IgnoreMoreToExplore" minOccurs="0"/>
|
||||
<xs:group ref="textData"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<!-- Text Data Group -->
|
||||
<xs:group name="textData">
|
||||
<xs:sequence>
|
||||
<xs:element name="Text" type="xs:string"/>
|
||||
<xs:element name="AltText" minOccurs="0">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element name="Text" type="xs:string"/>
|
||||
<xs:element name="Condition" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:sequence>
|
||||
</xs:group>
|
||||
</xs:schema>
|
||||
11
README.md
11
README.md
@ -34,6 +34,7 @@ Check the ship's log for how to use your warp drive to travel between star syste
|
||||
- [Water](#water)
|
||||
- [Lava](#lava)
|
||||
- [Sand](#sand)
|
||||
- [Ship Log](#ship-log)
|
||||
- [How to destroy existing planets](#how-to-destroy-existing-planets)
|
||||
- [How to update existing planets](#how-to-update-existing-planets)
|
||||
- [How to use New Horizons in other mods](#how-to-use-new-horizons-in-other-mods)
|
||||
@ -576,6 +577,9 @@ This allows you to make black holes and white holes, and to pair them.
|
||||
- "tint" : (colour)
|
||||
- "curve": (scale curve)
|
||||
|
||||
### Ship Log
|
||||
You can make custom ship logs for your planets. There's a guide [here](https://gist.github.com/Bwc9876/1817f8726e7f1900e57e3b05dd047d86#intro).
|
||||
|
||||
### How to destroy existing planets
|
||||
|
||||
You do this (but with the appropriate name) as it's own config.
|
||||
@ -640,9 +644,10 @@ Authors:
|
||||
- [Mister_Nebula](https://github.com/misternebula) ([Marshmallow](https://github.com/misternebula/Marshmallow) v0.1 to v1.1.0)
|
||||
|
||||
New Horizons was made with help from:
|
||||
- [jtsalomo](https://github.com/jtsalomo) (Implemented [OW_CommonResources](https://github.com/PacificEngine/OW_CommonResources) support introduced in v0.5.0)
|
||||
- [Raicuparta](https://github.com/Raicuparta) (Integrated the [New Horizons Template](https://github.com/xen-42/ow-new-horizons-config-template) into the Outer Wilds Mods website)
|
||||
- [Nageld](https://github.com/Nageld) (Set up xml reading for custom dialogue in v0.8.0)
|
||||
- [jtsalomo](https://github.com/jtsalomo): Implemented [OW_CommonResources](https://github.com/PacificEngine/OW_CommonResources) support introduced in v0.5.0
|
||||
- [Raicuparta](https://github.com/Raicuparta): Integrated the [New Horizons Template](https://github.com/xen-42/ow-new-horizons-config-template) into the Outer Wilds Mods website
|
||||
- [Nageld](https://github.com/Nageld): Set up xml reading for custom dialogue in v0.8.0
|
||||
- [Bwc9876](https://github.com/Bwc9876): Set up ship log entires for planets in v0.9.0
|
||||
|
||||
Marshmallow was made with help from:
|
||||
- TAImatem
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user