Merge branch 'master' into ship-log

This commit is contained in:
Nick J. Connors 2022-02-19 15:41:01 -05:00
commit 14a08d9ad8
23 changed files with 374 additions and 132 deletions

38
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,38 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View File

@ -7,7 +7,7 @@ namespace NewHorizons.Atmosphere
{
static class VolumesBuilder
{
public static void Make(GameObject body, float innerRadius, float outerRadius)
public static void Make(GameObject body, float innerRadius, float outerRadius, IPlanetConfig config)
{
GameObject volumesGO = new GameObject("Volumes");
volumesGO.SetActive(false);
@ -24,17 +24,18 @@ namespace NewHorizons.Atmosphere
SS.pointChecksOnly = true;
SS.radius = outerRadius;
/*OWTriggerVolume trigvol = */
rulesetGO.AddComponent<OWTriggerVolume>();
PlanetoidRuleset PR = rulesetGO.AddComponent<PlanetoidRuleset>();
PR.SetValue("_altitudeFloor", innerRadius);
PR.SetValue("_altitudeCeiling", outerRadius);
PR._altitudeFloor = innerRadius;
PR._altitudeCeiling = outerRadius;
PR._useMinimap = !config.Base.IsSatellite;
PR._useAltimeter = !config.Base.IsSatellite;
EffectRuleset ER = rulesetGO.AddComponent<EffectRuleset>();
ER.SetValue("_type", EffectRuleset.BubbleType.Underwater);
ER.SetValue("_material", GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_material"));
ER.SetValue("_cloudMaterial", GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_cloudMaterial"));
ER._type = EffectRuleset.BubbleType.Underwater;
ER._material = GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_material");
ER._cloudMaterial = GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_cloudMaterial");
volumesGO.transform.localPosition = Vector3.zero;
rulesetGO.SetActive(true);

View File

@ -81,11 +81,11 @@ namespace NewHorizons.Builder.Body
fogGO.name = "OceanFog";
fogGO.transform.localPosition = Vector3.zero;
fogGO.transform.localScale = Vector3.one;
if(module.Tint != null)
if (module.Tint != null)
{
var adjustedColour = module.Tint.ToColor() / 4f;
adjustedColour.a = 1f;
adjustedColour.a = adjustedColour.a * 4f;
fogGO.GetComponent<MeshRenderer>().material.color = adjustedColour;
}

View File

@ -22,22 +22,22 @@ namespace NewHorizons.Builder.General
ReferenceFrameVolume RFV = rfGO.AddComponent<ReferenceFrameVolume>();
ReferenceFrame RV = new ReferenceFrame(rigidbody);
RV.SetValue("_minSuitTargetDistance", sphereOfInfluence);
RV.SetValue("_maxTargetDistance", 0);
RV.SetValue("_autopilotArrivalDistance", sphereOfInfluence * 2f);
RV.SetValue("_autoAlignmentDistance", sphereOfInfluence * 1.5f);
RV._minSuitTargetDistance = sphereOfInfluence;
RV._maxTargetDistance = 0;
RV._autopilotArrivalDistance = 2.0f * sphereOfInfluence;
RV._autoAlignmentDistance = sphereOfInfluence * 1.5f;
RV._hideLandingModePrompt = false;
RV._matchAngularVelocity = true;
RV._minMatchAngularVelocityDistance = 70;
RV._maxMatchAngularVelocityDistance = 400;
RV._bracketsRadius = sphereOfInfluence;
RV.SetValue("_hideLandingModePrompt", false);
RV.SetValue("_matchAngularVelocity", true);
RV.SetValue("_minMatchAngularVelocityDistance", 70);
RV.SetValue("_maxMatchAngularVelocityDistance", 400);
RV.SetValue("_bracketsRadius", sphereOfInfluence);
RFV.SetValue("_referenceFrame", RV);
RFV.SetValue("_minColliderRadius", sphereOfInfluence);
RFV.SetValue("_maxColliderRadius", sphereOfInfluence * 2f);
RFV.SetValue("_isPrimaryVolume", true);
RFV.SetValue("_isCloseRangeVolume", false);
RFV._referenceFrame = RV;
RFV._minColliderRadius = sphereOfInfluence;
RFV._maxColliderRadius = sphereOfInfluence * 2f;
RFV._isPrimaryVolume = true;
RFV._isCloseRangeVolume = false;
rfGO.SetActive(true);
}

View File

@ -22,7 +22,7 @@ namespace NewHorizons.Builder.General
playerSpawn = spawnGO.AddComponent<SpawnPoint>();
spawnGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, (playerSpawn.transform.position - body.transform.position).normalized);
spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 2f;
spawnGO.transform.position = spawnGO.transform.position + spawnGO.transform.TransformDirection(Vector3.up) * 4f;
GameObject.FindObjectOfType<PlayerSpawner>().SetInitialSpawnPoint(playerSpawn);
}
@ -41,7 +41,7 @@ namespace NewHorizons.Builder.General
ship.transform.position = spawnPoint.transform.position;
ship.transform.rotation = Quaternion.FromToRotation(Vector3.up, (spawnPoint.transform.position - body.transform.position).normalized);
// Move it up a bit more
ship.transform.position = ship.transform.position + ship.transform.TransformDirection(Vector3.up) * 5f;
ship.transform.position = ship.transform.position + ship.transform.TransformDirection(Vector3.up) * 4f;
ship.GetRequiredComponent<MatchInitialMotion>().SetBodyToMatch(rb);

View File

@ -21,10 +21,15 @@ namespace NewHorizons.Builder.Orbital
return Update(initialMotion, body, primaryBody, OWRB, orbit);
}
public static float SiderealPeriodToAngularSpeed(float siderealPeriod)
{
return siderealPeriod == 0 ? 0f : 2f * Mathf.PI / (siderealPeriod * 60f);
}
public static InitialMotion Update(InitialMotion initialMotion, GameObject body, AstroObject primaryBody, OWRigidbody OWRB, OrbitModule orbit)
{
// Rotation
initialMotion.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0f : 2f * Mathf.PI / (orbit.SiderealPeriod * 60f));
initialMotion.SetValue("_initAngularSpeed", SiderealPeriodToAngularSpeed(orbit.SiderealPeriod));
var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + 90f, Vector3.right) * Vector3.up;
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);

View File

@ -16,10 +16,12 @@ namespace NewHorizons.Builder.Props
{
public static void Make(GameObject go, Sector sector, IPlanetConfig config, IModAssets assets, string uniqueModName, PropModule.DetailInfo detail)
{
GameObject detailGO = null;
if (detail.assetBundle != null)
{
var prefab = PropBuildManager.LoadPrefab(detail.assetBundle, detail.path, uniqueModName, assets);
MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal, detail.generateColliders);
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
else if (detail.objFilePath != null)
{
@ -27,24 +29,33 @@ namespace NewHorizons.Builder.Props
{
var prefab = assets.Get3DObject(detail.objFilePath, detail.mtlFilePath);
prefab.SetActive(false);
MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal, detail.generateColliders);
detailGO = MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
catch (Exception e)
{
Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}");
}
}
else MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal, detail.generateColliders);
else detailGO = MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
if(detailGO != null && detail.removeChildren != null)
{
foreach(var childPath in detail.removeChildren)
{
var childObj = SearchUtilities.Find(SearchUtilities.GetPath(detailGO.transform) + "/" + childPath);
childObj.gameObject.SetActive(false);
}
}
}
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal, bool generateColliders)
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
var prefab = SearchUtilities.Find(propToClone);
if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}");
return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal, generateColliders);
return MakeDetail(go, sector, prefab, position, rotation, scale, alignWithNormal);
}
public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal, bool generateColliders)
public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
if (prefab == null) return null;
@ -77,7 +88,11 @@ namespace NewHorizons.Builder.Props
if (component is GhostIK) (component as GhostIK).enabled = false;
if (component is GhostEffects) (component as GhostEffects).enabled = false;
if (component is Animator) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as Animator).enabled = true);
// If it's not a moving anglerfish make sure the anim controller is off
if(component is AnglerfishAnimController && component.GetComponentInParent<AnglerfishController>() == null)
Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as AnglerfishAnimController).enabled = false);
if (component is Animator) Main.Instance.ModHelper.Events.Unity.FireInNUpdates(() => (component as Animator).enabled = true, 5);
if (component is Collider) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as Collider).enabled = true);
if(component is Shape) Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => (component as Shape).enabled = true);
@ -104,17 +119,6 @@ namespace NewHorizons.Builder.Props
Logger.LogError($"Couldn't update AnglerFish chase speed: {e.Message}");
}
}
// Mesh colliders
if (generateColliders)
{
if (component is MeshFilter && component.gameObject.GetComponent<MeshCollider>() == null)
{
var mesh = (component as MeshFilter).mesh;
if (mesh.isReadable) component.gameObject.AddComponent<MeshCollider>();
else Logger.LogError($"Couldn't change mesh for {component.gameObject.name} because it is not readable");
}
}
}
prop.transform.position = position == null ? go.transform.position : go.transform.TransformPoint((Vector3)position);

View File

@ -15,7 +15,6 @@ namespace NewHorizons.Builder.Props
{
public static void Make(GameObject go, Sector sector, PropModule.DialogueInfo info, IModHelper mod)
{
if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return;
var dialogue = MakeConversationZone(go, sector, info, mod);

View File

@ -71,7 +71,7 @@ namespace NewHorizons.Builder.Props
height -= 0.2f;
}
var prop = DetailBuilder.MakeDetail(go, sector, prefab, (MVector3)(point.normalized * height), null, propInfo.scale, true, propInfo.generateColliders);
var prop = DetailBuilder.MakeDetail(go, sector, prefab, (MVector3)(point.normalized * height), null, propInfo.scale, true);
if (propInfo.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset);
if (propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation);
points.RemoveAt(randomInd);

View File

@ -0,0 +1,69 @@
using NewHorizons.Builder.Orbital;
using NewHorizons.OrbitalPhysics;
using NewHorizons.Utility;
using PacificEngine.OW_CommonResources.Game.Resource;
using PacificEngine.OW_CommonResources.Game.State;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Updater
{
public static class OrbitUpdater
{
public static void Update(NewHorizonsBody body, GameObject go)
{
var mapping = Planet.defaultMapping;
var heavenlyBody = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(AstroObjectLocator.GetAstroObject(body.Config.Name));
Logger.Log($"Updating position of {body.Config.Name}/{heavenlyBody}");
if (heavenlyBody != HeavenlyBody.None)
{
var original = mapping[heavenlyBody];
var coords = OrbitalHelper.KeplerCoordinatesFromOrbitModule(body.Config.Orbit);
var parent = original.state.parent;
if (body.Config.Orbit.PrimaryBody != null)
{
var parentAO = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody);
var newParent = CommonResourcesUtilities.HeavenlyBodyFromAstroObject(parentAO);
if (newParent != HeavenlyBody.None)
{
Logger.LogWarning($"Sorry, can't change primary body for planets yet. You tried making {body.Config.Name} orbit {newParent}");
/*
parent = newParent;
// Have to change the gravity stuff
go.GetComponentInChildren<ConstantForceDetector>()._detectableFields = new ForceVolume[] { parentAO.GetGravityVolume() };
go.GetComponent<AstroObject>()._primaryBody = parentAO;
*/
}
else Logger.LogError($"Couldn't find new parent {body.Config.Orbit.PrimaryBody}");
}
var planetoid = new Planet.Plantoid(
original.size,
original.gravity,
go.transform.rotation,
InitialMotionBuilder.SiderealPeriodToAngularSpeed(body.Config.Orbit.SiderealPeriod),
parent,
coords
);
mapping[heavenlyBody] = planetoid;
Planet.defaultMapping = mapping;
Planet.mapping = mapping;
}
else
{
Logger.LogError($"Couldn't find heavenlyBody for {body.Config.Name}");
}
}
}
}

View File

@ -9,7 +9,7 @@ namespace NewHorizons.External
{
public class OrbitModule : Module
{
public int SemiMajorAxis { get; set; } = 5000;
public int SemiMajorAxis { get; set; }
public float Inclination { get; set; }
public string PrimaryBody { get; set; }
public bool IsMoon { get; set; }

View File

@ -34,7 +34,7 @@ namespace NewHorizons.External
public PlanetConfig(Dictionary<string, object> dict)
{
// Always have to have a base module and orbit module
// Always have to have a base module
Base = new BaseModule();
Orbit = new OrbitModule();

View File

@ -27,7 +27,6 @@ namespace NewHorizons.External
public MVector3 offset;
public MVector3 rotation;
public float scale { get; set; } = 1f;
public bool generateColliders = false;
}
public class DetailInfo
@ -40,7 +39,7 @@ namespace NewHorizons.External
public MVector3 rotation;
public float scale { get; set; } = 1f;
public bool alignToNormal;
public bool generateColliders = false;
public string[] removeChildren;
}
public class RaftInfo

View File

@ -49,4 +49,4 @@ namespace NewHorizons.Handlers
oneShotSource);
}
}
}
}

View File

@ -4,14 +4,19 @@ using NewHorizons.Builder.Body;
using NewHorizons.Builder.General;
using NewHorizons.Builder.Orbital;
using NewHorizons.Builder.Props;
using NewHorizons.Builder.Updater;
using NewHorizons.Components;
using NewHorizons.External;
using NewHorizons.External.VariableSize;
using NewHorizons.Handlers;
using NewHorizons.OrbitalPhysics;
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;
@ -423,7 +428,16 @@ namespace NewHorizons
}
// Do stuff that's shared between generating new planets and updating old ones
return SharedGenerateBody(body, go, sector, rb);
go = SharedGenerateBody(body, go, sector, rb);
// Update a position using CommonResources
// Since orbits are always there just check if they set a semi major axis
if (body.Config.Orbit != null && body.Config.Orbit.SemiMajorAxis != 0f)
{
OrbitUpdater.Update(body, go);
}
return go;
}
#endregion Load
@ -487,7 +501,7 @@ namespace NewHorizons
var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence * 2f);
ao.SetValue("_rootSector", sector);
VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence);
VolumesBuilder.Make(go, body.Config.Base.SurfaceSize, sphereOfInfluence, body.Config);
if (body.Config.HeightMap != null)
HeightMapBuilder.Make(go, body.Config.HeightMap, body.Mod.Assets);
@ -506,13 +520,7 @@ namespace NewHorizons
body.Object = go;
// Now that we're done move the planet into place
go.transform.parent = Locator.GetRootTransform();
go.transform.position = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(1, 100), body.Config.Orbit).Item1 + (primaryBody == null ? Vector3.zero : primaryBody.transform.position);
if (go.transform.position.magnitude > FurthestOrbit)
{
FurthestOrbit = go.transform.position.magnitude + 30000f;
}
UpdatePosition(go, body, primaryBody);
// Have to do this after setting position
var initialMotion = InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit);
@ -605,6 +613,17 @@ namespace NewHorizons
return go;
}
private void UpdatePosition(GameObject go, NewHorizonsBody body, AstroObject primaryBody)
{
go.transform.parent = Locator.GetRootTransform();
go.transform.position = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(1, 100), body.Config.Orbit).Item1 + (primaryBody == null ? Vector3.zero : primaryBody.transform.position);
if (go.transform.position.magnitude > FurthestOrbit)
{
FurthestOrbit = go.transform.position.magnitude + 30000f;
}
}
#endregion Body generation
#region Change star system

View File

@ -77,9 +77,12 @@ namespace NewHorizons.Tools
public static bool CheckShipOutersideSolarSystem(PlayerState __instance, ref bool __result)
{
if (PlayerState._inBrambleDimension) return false;
Transform sunTransform = Locator.GetSunTransform();
OWRigidbody shipBody = Locator.GetShipBody();
__result = sunTransform != null && shipBody != null && (sunTransform.position - shipBody.transform.position).sqrMagnitude > Main.FurthestOrbit * Main.FurthestOrbit * 4f;
var maxDist2 = Mathf.Max(900000000f, Main.FurthestOrbit * Main.FurthestOrbit * 2f);
__result = sunTransform != null && shipBody != null && (sunTransform.position - shipBody.transform.position).sqrMagnitude > maxDist2;
return false;
}

View File

@ -0,0 +1,61 @@
using PacificEngine.OW_CommonResources.Game.Resource;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.Utility
{
public static class CommonResourcesUtilities
{
public static HeavenlyBody HeavenlyBodyFromAstroObject(AstroObject obj)
{
switch (obj.GetAstroObjectName())
{
case AstroObject.Name.CustomString:
return HeavenlyBody.FromString(obj.GetCustomName());
case AstroObject.Name.BrittleHollow:
return HeavenlyBodies.BrittleHollow;
case AstroObject.Name.CaveTwin:
return HeavenlyBodies.EmberTwin;
case AstroObject.Name.Comet:
return HeavenlyBodies.Interloper;
case AstroObject.Name.DarkBramble:
return HeavenlyBodies.DarkBramble;
case AstroObject.Name.DreamWorld:
return HeavenlyBodies.DreamWorld;
case AstroObject.Name.GiantsDeep:
return HeavenlyBodies.GiantsDeep;
case AstroObject.Name.HourglassTwins:
return HeavenlyBodies.HourglassTwins;
case AstroObject.Name.MapSatellite:
return HeavenlyBodies.SatiliteMapping;
case AstroObject.Name.ProbeCannon:
return HeavenlyBodies.ProbeCannon;
case AstroObject.Name.QuantumMoon:
return HeavenlyBodies.QuantumMoon;
case AstroObject.Name.RingWorld:
return HeavenlyBodies.Stranger;
case AstroObject.Name.Sun:
return HeavenlyBodies.Sun;
case AstroObject.Name.SunStation:
return HeavenlyBodies.SunStation;
case AstroObject.Name.TimberHearth:
return HeavenlyBodies.TimberHearth;
case AstroObject.Name.TimberMoon:
return HeavenlyBodies.Attlerock;
case AstroObject.Name.TowerTwin:
return HeavenlyBodies.AshTwin;
case AstroObject.Name.VolcanicMoon:
return HeavenlyBodies.HollowLantern;
case AstroObject.Name.WhiteHole:
return HeavenlyBodies.WhiteHole;
case AstroObject.Name.WhiteHoleTarget:
return HeavenlyBodies.WhiteHoleStation;
default:
return HeavenlyBodies.None;
}
}
}
}

View File

@ -13,7 +13,7 @@ namespace NewHorizons.Utility
public class DebugRaycaster : MonoBehaviour
{
private OWRigidbody _rb;
private void Awake()
{
_rb = this.GetRequiredComponent<OWRigidbody>();

View File

@ -17,7 +17,7 @@ namespace NewHorizons.Utility
public int B { get; }
public int A { get; }
public Color32 ToColor32() => new Color(R, G, B, A);
public Color32 ToColor32() => new Color32((byte)R, (byte)G, (byte)B, (byte)A);
public Color ToColor() => new Color(R / 255f, G / 255f, B / 255f, A / 255f);
}

View File

@ -99,60 +99,68 @@ namespace NewHorizons.Utility
public static GameObject Find(string path)
{
var go = GameObject.Find(path);
var names = path.Split(new char[] { '\\', '/' });
if (go == null)
try
{
var go = GameObject.Find(path);
// Get the root object and hope its the right one
var root = GameObject.Find(names[0]);
if (root == null) root = FindObjectOfTypeAndName<GameObject>(names[0]);
var t = root?.transform;
if (t == null)
var names = path.Split(new char[] { '\\', '/' });
if (go == null)
{
Logger.LogWarning($"Couldn't find root object in path ({names[0]})");
return null;
}
for (int i = 1; i < names.Length; i++)
{
var child = t.transform.Find(names[i]);
// Get the root object and hope its the right one
var root = GameObject.Find(names[0]);
if (root == null) root = FindObjectOfTypeAndName<GameObject>(names[0]);
if(child == null)
var t = root?.transform;
if (t == null)
{
foreach(Transform c in t.GetComponentsInChildren<Transform>(true))
Logger.LogWarning($"Couldn't find root object in path ({names[0]})");
}
else
{
for (int i = 1; i < names.Length; i++)
{
if(t.name.Equals(names[i]))
var child = t.transform.Find(names[i]);
if (child == null)
{
child = c;
foreach (Transform c in t.GetComponentsInChildren<Transform>(true))
{
if (t.name.Equals(names[i]))
{
child = c;
break;
}
}
}
if (child == null)
{
Logger.LogWarning($"Couldn't find object in path ({names[i]})");
t = null;
break;
}
t = child;
}
}
if (child == null)
{
Logger.LogWarning($"Couldn't find object in path ({names[i]})");
t = null;
break;
}
t = child;
go = t?.gameObject;
}
go = t?.gameObject;
}
if (go == null)
{
var name = names.Last();
Logger.LogWarning($"Couldn't find object {path}, will look for potential matches for name {name}");
go = FindObjectOfTypeAndName<GameObject>(name);
}
if(go == null)
return go;
}
catch(Exception)
{
var name = names.Last();
Logger.LogWarning($"Couldn't find object {path}, will look for potential matches for name {name}");
go = FindObjectOfTypeAndName<GameObject>(name);
return null;
}
return go;
}
public static List<GameObject> GetAllChildren(GameObject parent)

View File

@ -3,7 +3,7 @@
"author": "xen",
"name": "New Horizons",
"uniqueName": "xen.NewHorizons",
"version": "0.8.1",
"version": "0.8.3",
"owmlVersion": "2.1.0",
"dependencies": [ "PacificEngine.OW_CommonResources" ],
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.OuterWildsMMO", "Vesper.AutoResume" ]

View File

@ -1,4 +1,4 @@
![new horizons thumbnail](https://user-images.githubusercontent.com/22628069/146680547-bd815057-9f4e-42da-a6c4-84d3ff82ff2c.png)
![new horizons thumbnail 2](https://user-images.githubusercontent.com/22628069/154112130-b777f618-245f-44c9-9408-e11141fc5fde.png)
![Current version](https://img.shields.io/github/manifest-json/v/xen-42/outer-wilds-new-horizons?color=gree&filename=NewHorizons%2Fmanifest.json)
![Downloads](https://img.shields.io/github/downloads/xen-42/outer-wilds-new-horizons/total)
@ -62,29 +62,30 @@ Check the ship's log for how to use your warp drive to travel between star syste
- Separate solar system scenes accessible via wormhole (done)
- Warp drive with target set in ship's log (done)
- Implement custom dialogue (done)
- Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier ([done](https://github.com/xen-42/outer-wilds-unity-template))
- Procedural terrain generation (started)
- "Quantum" planet parameters
- Better terrain and water LOD
- Edit existing planet orbits
- Implement all planet features:
- Tornados + floating islands
- Funnels (sand/water/lava/star) (done)
- Funnels (sand/water/lava/star) (done)
- Variable surface height (sand/water/lava/star) (done)
- Zero-g volumes (done, with Unity template)
- Ghost matter (done, by copying props via game hierarchy)
- Tornados + floating islands
- Let any star go supernova
- Geysers
- Meteors
- Ghost matter
- Pocket dimensions
- Timed position/velocity changes
- Zero-g volumes
- Implement custom Nomai scrolls
- Implement custom translatable writing
- Implement constant gravity volumes
- Destroy planets that fall into a star
- Make a template Unity project to use with NH, including all game scripts recovered using UtinyRipper to make AssetBundle creation easier
## How to create your own planets using configs
**Note that I'm more than happy to help you debug your planet config files, but please don't just use notepad to edit them. Use something like Visual Studio Code that will check your .json file for errors. It will save both of us time.**
There is a template [here](https://github.com/xen-42/ow-new-horizons-config-template) if you want to release your own planet mod using configs. You can learn how the configs work by picking apart the [Real Solar System](https://github.com/xen-42/outer-wilds-real-solar-system) mod or the [New Horizons Examples](https://github.com/xen-42/ow-new-horizons-examples) mod.
Planets are created using a JSON file format structure, and placed in a folder called `planets` (or in any sub-directory of it) in the location where New Horizons is installed (by default this folder doesn't exist, you have to create it within the `xen.NewHorizons` directory).
@ -96,7 +97,7 @@ To locate this directory, click the "..." symbol next to "New Horizons" in the O
![Create a planets folder in the mod directory](https://user-images.githubusercontent.com/22628069/149638007-26b872ab-f02e-455f-a7fd-99d0d2a96de8.png)
Now that you have created your planets folder, this is where you will put your planet config files. A config file will look something like this:
```
```json
{
"name" : "Wetrock",
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/master/NewHorizons/schema.json",
@ -104,7 +105,6 @@ Now that you have created your planets folder, this is where you will put your p
"Base" :
{
"groundSize" : 100,
"waterSize" : 101,
"surfaceSize" : 101,
"surfaceGravity" : 12,
"hasMapMarker" : true,
@ -155,7 +155,7 @@ Each { must match up with a closing } to denote its section. If you don't know h
Modules look like this:
```
```json
"Star" :
{
"size" : 3000,
@ -174,26 +174,26 @@ In this example the `Star` module has a `size` field and a `tint` field. Since t
Most fields are either true/false, a decimal number, and integer number, or a string (word with quotation marks around it). There are also the following types of values:
#### Colour:
```
```json
{
"r" : 200,
"g" : 255,
"b" : 255,
"a" : 255
"r" : 200,
"g" : 255,
"b" : 255,
"a" : 255
}
```
#### Position:
```
```json
{
"x" : 182.4,
"y" : 227.4,
"z" : 62.7,
"x" : 182.4,
"y" : 227.4,
"z" : 62.7,
}
```
#### Scale curve:
```
```json
[
{"time":0, "value":1},
{"time":5, "value":0},
@ -271,7 +271,7 @@ Let's you put asteroids in orbit around a planet or star. Can probably negativel
### FocalPoint
If you want to have binary planets or stars you have to do a few extra steps. First you make a focal point body. Here's an example (note the "..." means you'd be writing stuff there but it isn't important for the example. Don't literally put "..."):
```
```json
{
"name" : "Alpha Centauri",
"Base" :
@ -292,7 +292,7 @@ If you want to have binary planets or stars you have to do a few extra steps. Fi
}
```
Then you would make config files for the two bodies in the binary pair.
```
```json
{
"name" : "Alpha Centauri A",
"Base" :
@ -312,7 +312,7 @@ Then you would make config files for the two bodies in the binary pair.
}
```
and
```
```json
{
"name" : "Alpha Centauri B",
"Base" :
@ -346,7 +346,7 @@ The different things you can specify in the props section are:
- "scatter" : (list) I'll just give an example.
```
```json
"scatter" : [
{"path" : "DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/Props_DreamZone_1/OtherComponentsGroup/Trees_Z1/DreamHouseIsland/Tree_DW_M_Var", "count" : 12}
]
@ -363,14 +363,22 @@ A detail info object can have the following parameters:
- "rotation" : (x, y, z) the euler angle rotation from a 3d vector (in degrees)
- "scale" : (decimal number)
- "alignToNormal" : (true/false) If it should align with the normal vector of the surface its own (overwrites rotation)
- "removeChildren" : (list of strings) relative paths of children to get rid of
You have three options: Load from the scene hierarchy by setting "path", load from an asset bundle by setting "path" and "assetBundle", or load an obj file by setting "objFilePath" and "mtlFilePath". Asset bundles give much better results than .obj's.
#### Asset Bundles
Here is a template project: [Outer Wilds Unity Template](https://github.com/xen-42/outer-wilds-unity-template)
The template project contains ripped versions of all the game scripts, meaning you can put things like DirectionalForceVolumes in your Unity project to have artificial gravity volumes loaded right into the game.
If for whatever reason you want to set up a Unity project manually instead of using the template, follow these instructions:
1. Start up a Unity 2017 project (I use Unity 2017.4.40f1 (64-bit), so if you use something else I can't guarantee it will work). The DLC updated Outer Wilds to 2019.4.27 so that probably works but I personally haven't tried it.
2. In the "Assets" folder in Unity, create a new folder called "Editor". In it create a file called "CreateAssetBundle.cs" with the following code in it:
```
```cs
using UnityEditor;
using UnityEngine;
using System.IO;
@ -407,7 +415,7 @@ An array of object, each one has the following properties:
#### XML
Here's an example dialogue XML:
```
```xml
<DialogueTree>
<NameField>EXAMPLE NPC</NameField>
@ -529,7 +537,7 @@ Signal info objects can then have the following values set:
- "insideCloak" : (true/false) You have to set this to true if the signal is inside a cloaking field
Here's an example of what all this looks like, for more check my [Signals+](https://github.com/xen-42/outer-wilds-signals-plus) add-on:
```
```json
"Signal" :
{
"Signals" :
@ -570,7 +578,7 @@ This allows you to make black holes and white holes, and to pair them.
### How to destroy existing planets
You do this (but with the appropriate name) as it's own config.
```
```json
{
"name" : "Ember Twin",
"destroy" : true,
@ -585,11 +593,19 @@ Similar to above, make a config where "Name" is the name of the planet. The name
Only some of the above modules are supported (currently) for existing planets. Things you cannot modify for existing planets include: heightmaps, procedural generation, gravity, or their orbits. You also can't make them into stars or binary focal points (but why would you want to, just delete them and replace them entirely). However this still means there are many things you can do: completely change their atmospheres, give them rings, asteroid belts, comet tails, lava, water, prop details, or signals.
You can also delete parts of an existing planet. Here's part of an example config which would delete the rising sand from Ember Twin:
```json
"name" : "Ember Twin",
"childrenToDestroy" : ["SandSphere_Rising"],
```
In `childrenToDestroy` you list the relative paths for the children of the planet's gameObject that you want to delete.
## How to use New Horizons in other mods
First create the following interface in your mod:
```
```cs
public interface INewHorizons
{
void Create(Dictionary<string, object> config, IModBehaviour mod);
@ -601,7 +617,7 @@ public interface INewHorizons
```
In your main `ModBehaviour` class you can get the NewHorizons API like so:
```
```cs
INewHorizons NewHorizonsAPI = ModHelper.Interaction.GetModApi<INewHorizons>("xen.NewHorizons")
```