mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Merge branch 'master' into ship-log
This commit is contained in:
commit
14a08d9ad8
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal 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.
|
||||||
@ -7,7 +7,7 @@ namespace NewHorizons.Atmosphere
|
|||||||
{
|
{
|
||||||
static class VolumesBuilder
|
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");
|
GameObject volumesGO = new GameObject("Volumes");
|
||||||
volumesGO.SetActive(false);
|
volumesGO.SetActive(false);
|
||||||
@ -24,17 +24,18 @@ namespace NewHorizons.Atmosphere
|
|||||||
SS.pointChecksOnly = true;
|
SS.pointChecksOnly = true;
|
||||||
SS.radius = outerRadius;
|
SS.radius = outerRadius;
|
||||||
|
|
||||||
/*OWTriggerVolume trigvol = */
|
|
||||||
rulesetGO.AddComponent<OWTriggerVolume>();
|
rulesetGO.AddComponent<OWTriggerVolume>();
|
||||||
|
|
||||||
PlanetoidRuleset PR = rulesetGO.AddComponent<PlanetoidRuleset>();
|
PlanetoidRuleset PR = rulesetGO.AddComponent<PlanetoidRuleset>();
|
||||||
PR.SetValue("_altitudeFloor", innerRadius);
|
PR._altitudeFloor = innerRadius;
|
||||||
PR.SetValue("_altitudeCeiling", outerRadius);
|
PR._altitudeCeiling = outerRadius;
|
||||||
|
PR._useMinimap = !config.Base.IsSatellite;
|
||||||
|
PR._useAltimeter = !config.Base.IsSatellite;
|
||||||
|
|
||||||
EffectRuleset ER = rulesetGO.AddComponent<EffectRuleset>();
|
EffectRuleset ER = rulesetGO.AddComponent<EffectRuleset>();
|
||||||
ER.SetValue("_type", EffectRuleset.BubbleType.Underwater);
|
ER._type = EffectRuleset.BubbleType.Underwater;
|
||||||
ER.SetValue("_material", GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_material"));
|
ER._material = GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_material");
|
||||||
ER.SetValue("_cloudMaterial", GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_cloudMaterial"));
|
ER._cloudMaterial = GameObject.Find("RulesetVolumes_GD").GetComponent<RulesetVolume>().GetValue<Material>("_cloudMaterial");
|
||||||
|
|
||||||
volumesGO.transform.localPosition = Vector3.zero;
|
volumesGO.transform.localPosition = Vector3.zero;
|
||||||
rulesetGO.SetActive(true);
|
rulesetGO.SetActive(true);
|
||||||
|
|||||||
@ -81,11 +81,11 @@ namespace NewHorizons.Builder.Body
|
|||||||
fogGO.name = "OceanFog";
|
fogGO.name = "OceanFog";
|
||||||
fogGO.transform.localPosition = Vector3.zero;
|
fogGO.transform.localPosition = Vector3.zero;
|
||||||
fogGO.transform.localScale = Vector3.one;
|
fogGO.transform.localScale = Vector3.one;
|
||||||
|
|
||||||
if (module.Tint != null)
|
if (module.Tint != null)
|
||||||
{
|
{
|
||||||
var adjustedColour = module.Tint.ToColor() / 4f;
|
var adjustedColour = module.Tint.ToColor() / 4f;
|
||||||
adjustedColour.a = 1f;
|
adjustedColour.a = adjustedColour.a * 4f;
|
||||||
|
|
||||||
fogGO.GetComponent<MeshRenderer>().material.color = adjustedColour;
|
fogGO.GetComponent<MeshRenderer>().material.color = adjustedColour;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -22,22 +22,22 @@ namespace NewHorizons.Builder.General
|
|||||||
ReferenceFrameVolume RFV = rfGO.AddComponent<ReferenceFrameVolume>();
|
ReferenceFrameVolume RFV = rfGO.AddComponent<ReferenceFrameVolume>();
|
||||||
|
|
||||||
ReferenceFrame RV = new ReferenceFrame(rigidbody);
|
ReferenceFrame RV = new ReferenceFrame(rigidbody);
|
||||||
RV.SetValue("_minSuitTargetDistance", sphereOfInfluence);
|
RV._minSuitTargetDistance = sphereOfInfluence;
|
||||||
RV.SetValue("_maxTargetDistance", 0);
|
RV._maxTargetDistance = 0;
|
||||||
RV.SetValue("_autopilotArrivalDistance", sphereOfInfluence * 2f);
|
RV._autopilotArrivalDistance = 2.0f * sphereOfInfluence;
|
||||||
RV.SetValue("_autoAlignmentDistance", sphereOfInfluence * 1.5f);
|
RV._autoAlignmentDistance = sphereOfInfluence * 1.5f;
|
||||||
|
|
||||||
RV.SetValue("_hideLandingModePrompt", false);
|
RV._hideLandingModePrompt = false;
|
||||||
RV.SetValue("_matchAngularVelocity", true);
|
RV._matchAngularVelocity = true;
|
||||||
RV.SetValue("_minMatchAngularVelocityDistance", 70);
|
RV._minMatchAngularVelocityDistance = 70;
|
||||||
RV.SetValue("_maxMatchAngularVelocityDistance", 400);
|
RV._maxMatchAngularVelocityDistance = 400;
|
||||||
RV.SetValue("_bracketsRadius", sphereOfInfluence);
|
RV._bracketsRadius = sphereOfInfluence;
|
||||||
|
|
||||||
RFV.SetValue("_referenceFrame", RV);
|
RFV._referenceFrame = RV;
|
||||||
RFV.SetValue("_minColliderRadius", sphereOfInfluence);
|
RFV._minColliderRadius = sphereOfInfluence;
|
||||||
RFV.SetValue("_maxColliderRadius", sphereOfInfluence * 2f);
|
RFV._maxColliderRadius = sphereOfInfluence * 2f;
|
||||||
RFV.SetValue("_isPrimaryVolume", true);
|
RFV._isPrimaryVolume = true;
|
||||||
RFV.SetValue("_isCloseRangeVolume", false);
|
RFV._isCloseRangeVolume = false;
|
||||||
|
|
||||||
rfGO.SetActive(true);
|
rfGO.SetActive(true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,7 +22,7 @@ namespace NewHorizons.Builder.General
|
|||||||
|
|
||||||
playerSpawn = spawnGO.AddComponent<SpawnPoint>();
|
playerSpawn = spawnGO.AddComponent<SpawnPoint>();
|
||||||
spawnGO.transform.rotation = Quaternion.FromToRotation(Vector3.up, (playerSpawn.transform.position - body.transform.position).normalized);
|
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);
|
GameObject.FindObjectOfType<PlayerSpawner>().SetInitialSpawnPoint(playerSpawn);
|
||||||
}
|
}
|
||||||
@ -41,7 +41,7 @@ namespace NewHorizons.Builder.General
|
|||||||
ship.transform.position = spawnPoint.transform.position;
|
ship.transform.position = spawnPoint.transform.position;
|
||||||
ship.transform.rotation = Quaternion.FromToRotation(Vector3.up, (spawnPoint.transform.position - body.transform.position).normalized);
|
ship.transform.rotation = Quaternion.FromToRotation(Vector3.up, (spawnPoint.transform.position - body.transform.position).normalized);
|
||||||
// Move it up a bit more
|
// 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);
|
ship.GetRequiredComponent<MatchInitialMotion>().SetBodyToMatch(rb);
|
||||||
|
|
||||||
|
|||||||
@ -21,10 +21,15 @@ namespace NewHorizons.Builder.Orbital
|
|||||||
return Update(initialMotion, body, primaryBody, OWRB, orbit);
|
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)
|
public static InitialMotion Update(InitialMotion initialMotion, GameObject body, AstroObject primaryBody, OWRigidbody OWRB, OrbitModule orbit)
|
||||||
{
|
{
|
||||||
// Rotation
|
// 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;
|
var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + 90f, Vector3.right) * Vector3.up;
|
||||||
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
|
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
|
||||||
|
|||||||
@ -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)
|
public static void Make(GameObject go, Sector sector, IPlanetConfig config, IModAssets assets, string uniqueModName, PropModule.DetailInfo detail)
|
||||||
{
|
{
|
||||||
|
GameObject detailGO = null;
|
||||||
|
|
||||||
if (detail.assetBundle != null)
|
if (detail.assetBundle != null)
|
||||||
{
|
{
|
||||||
var prefab = PropBuildManager.LoadPrefab(detail.assetBundle, detail.path, uniqueModName, assets);
|
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)
|
else if (detail.objFilePath != null)
|
||||||
{
|
{
|
||||||
@ -27,24 +29,33 @@ namespace NewHorizons.Builder.Props
|
|||||||
{
|
{
|
||||||
var prefab = assets.Get3DObject(detail.objFilePath, detail.mtlFilePath);
|
var prefab = assets.Get3DObject(detail.objFilePath, detail.mtlFilePath);
|
||||||
prefab.SetActive(false);
|
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)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}");
|
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);
|
var prefab = SearchUtilities.Find(propToClone);
|
||||||
if (prefab == null) Logger.LogError($"Couldn't find detail {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;
|
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 GhostIK) (component as GhostIK).enabled = false;
|
||||||
if (component is GhostEffects) (component as GhostEffects).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 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);
|
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}");
|
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);
|
prop.transform.position = position == null ? go.transform.position : go.transform.TransformPoint((Vector3)position);
|
||||||
|
|||||||
@ -15,7 +15,6 @@ namespace NewHorizons.Builder.Props
|
|||||||
{
|
{
|
||||||
public static void Make(GameObject go, Sector sector, PropModule.DialogueInfo info, IModHelper mod)
|
public static void Make(GameObject go, Sector sector, PropModule.DialogueInfo info, IModHelper mod)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return;
|
if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return;
|
||||||
|
|
||||||
var dialogue = MakeConversationZone(go, sector, info, mod);
|
var dialogue = MakeConversationZone(go, sector, info, mod);
|
||||||
|
|||||||
@ -71,7 +71,7 @@ namespace NewHorizons.Builder.Props
|
|||||||
height -= 0.2f;
|
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.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset);
|
||||||
if (propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation);
|
if (propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation);
|
||||||
points.RemoveAt(randomInd);
|
points.RemoveAt(randomInd);
|
||||||
|
|||||||
69
NewHorizons/Builder/Updater/OrbitUpdater.cs
Normal file
69
NewHorizons/Builder/Updater/OrbitUpdater.cs
Normal 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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
2
NewHorizons/External/OrbitModule.cs
vendored
2
NewHorizons/External/OrbitModule.cs
vendored
@ -9,7 +9,7 @@ namespace NewHorizons.External
|
|||||||
{
|
{
|
||||||
public class OrbitModule : Module
|
public class OrbitModule : Module
|
||||||
{
|
{
|
||||||
public int SemiMajorAxis { get; set; } = 5000;
|
public int SemiMajorAxis { get; set; }
|
||||||
public float Inclination { get; set; }
|
public float Inclination { get; set; }
|
||||||
public string PrimaryBody { get; set; }
|
public string PrimaryBody { get; set; }
|
||||||
public bool IsMoon { get; set; }
|
public bool IsMoon { get; set; }
|
||||||
|
|||||||
2
NewHorizons/External/PlanetConfig.cs
vendored
2
NewHorizons/External/PlanetConfig.cs
vendored
@ -34,7 +34,7 @@ namespace NewHorizons.External
|
|||||||
|
|
||||||
public PlanetConfig(Dictionary<string, object> dict)
|
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();
|
Base = new BaseModule();
|
||||||
Orbit = new OrbitModule();
|
Orbit = new OrbitModule();
|
||||||
|
|
||||||
|
|||||||
3
NewHorizons/External/PropModule.cs
vendored
3
NewHorizons/External/PropModule.cs
vendored
@ -27,7 +27,6 @@ namespace NewHorizons.External
|
|||||||
public MVector3 offset;
|
public MVector3 offset;
|
||||||
public MVector3 rotation;
|
public MVector3 rotation;
|
||||||
public float scale { get; set; } = 1f;
|
public float scale { get; set; } = 1f;
|
||||||
public bool generateColliders = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DetailInfo
|
public class DetailInfo
|
||||||
@ -40,7 +39,7 @@ namespace NewHorizons.External
|
|||||||
public MVector3 rotation;
|
public MVector3 rotation;
|
||||||
public float scale { get; set; } = 1f;
|
public float scale { get; set; } = 1f;
|
||||||
public bool alignToNormal;
|
public bool alignToNormal;
|
||||||
public bool generateColliders = false;
|
public string[] removeChildren;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class RaftInfo
|
public class RaftInfo
|
||||||
|
|||||||
@ -4,14 +4,19 @@ using NewHorizons.Builder.Body;
|
|||||||
using NewHorizons.Builder.General;
|
using NewHorizons.Builder.General;
|
||||||
using NewHorizons.Builder.Orbital;
|
using NewHorizons.Builder.Orbital;
|
||||||
using NewHorizons.Builder.Props;
|
using NewHorizons.Builder.Props;
|
||||||
|
using NewHorizons.Builder.Updater;
|
||||||
using NewHorizons.Components;
|
using NewHorizons.Components;
|
||||||
using NewHorizons.External;
|
using NewHorizons.External;
|
||||||
using NewHorizons.External.VariableSize;
|
using NewHorizons.External.VariableSize;
|
||||||
|
using NewHorizons.Handlers;
|
||||||
using NewHorizons.OrbitalPhysics;
|
using NewHorizons.OrbitalPhysics;
|
||||||
using NewHorizons.Utility;
|
using NewHorizons.Utility;
|
||||||
using OWML.Common;
|
using OWML.Common;
|
||||||
using OWML.ModHelper;
|
using OWML.ModHelper;
|
||||||
using OWML.Utils;
|
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;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -423,7 +428,16 @@ namespace NewHorizons
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do stuff that's shared between generating new planets and updating old ones
|
// 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
|
#endregion Load
|
||||||
@ -487,7 +501,7 @@ namespace NewHorizons
|
|||||||
var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence * 2f);
|
var sector = MakeSector.Make(go, owRigidBody, sphereOfInfluence * 2f);
|
||||||
ao.SetValue("_rootSector", sector);
|
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)
|
if (body.Config.HeightMap != null)
|
||||||
HeightMapBuilder.Make(go, body.Config.HeightMap, body.Mod.Assets);
|
HeightMapBuilder.Make(go, body.Config.HeightMap, body.Mod.Assets);
|
||||||
@ -506,13 +520,7 @@ namespace NewHorizons
|
|||||||
body.Object = go;
|
body.Object = go;
|
||||||
|
|
||||||
// Now that we're done move the planet into place
|
// Now that we're done move the planet into place
|
||||||
go.transform.parent = Locator.GetRootTransform();
|
UpdatePosition(go, body, primaryBody);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Have to do this after setting position
|
// Have to do this after setting position
|
||||||
var initialMotion = InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit);
|
var initialMotion = InitialMotionBuilder.Make(go, primaryBody, owRigidBody, body.Config.Orbit);
|
||||||
@ -605,6 +613,17 @@ namespace NewHorizons
|
|||||||
return go;
|
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
|
#endregion Body generation
|
||||||
|
|
||||||
#region Change star system
|
#region Change star system
|
||||||
|
|||||||
@ -77,9 +77,12 @@ namespace NewHorizons.Tools
|
|||||||
|
|
||||||
public static bool CheckShipOutersideSolarSystem(PlayerState __instance, ref bool __result)
|
public static bool CheckShipOutersideSolarSystem(PlayerState __instance, ref bool __result)
|
||||||
{
|
{
|
||||||
|
if (PlayerState._inBrambleDimension) return false;
|
||||||
|
|
||||||
Transform sunTransform = Locator.GetSunTransform();
|
Transform sunTransform = Locator.GetSunTransform();
|
||||||
OWRigidbody shipBody = Locator.GetShipBody();
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
61
NewHorizons/Utility/CommonResourcesUtilities.cs
Normal file
61
NewHorizons/Utility/CommonResourcesUtilities.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,7 +17,7 @@ namespace NewHorizons.Utility
|
|||||||
public int B { get; }
|
public int B { get; }
|
||||||
public int A { 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);
|
public Color ToColor() => new Color(R / 255f, G / 255f, B / 255f, A / 255f);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -98,6 +98,8 @@ namespace NewHorizons.Utility
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public static GameObject Find(string path)
|
public static GameObject Find(string path)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
var go = GameObject.Find(path);
|
var go = GameObject.Find(path);
|
||||||
|
|
||||||
@ -113,9 +115,9 @@ namespace NewHorizons.Utility
|
|||||||
if (t == null)
|
if (t == null)
|
||||||
{
|
{
|
||||||
Logger.LogWarning($"Couldn't find root object in path ({names[0]})");
|
Logger.LogWarning($"Couldn't find root object in path ({names[0]})");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
for (int i = 1; i < names.Length; i++)
|
for (int i = 1; i < names.Length; i++)
|
||||||
{
|
{
|
||||||
var child = t.transform.Find(names[i]);
|
var child = t.transform.Find(names[i]);
|
||||||
@ -141,6 +143,7 @@ namespace NewHorizons.Utility
|
|||||||
|
|
||||||
t = child;
|
t = child;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
go = t?.gameObject;
|
go = t?.gameObject;
|
||||||
}
|
}
|
||||||
@ -154,6 +157,11 @@ namespace NewHorizons.Utility
|
|||||||
|
|
||||||
return go;
|
return go;
|
||||||
}
|
}
|
||||||
|
catch(Exception)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static List<GameObject> GetAllChildren(GameObject parent)
|
public static List<GameObject> GetAllChildren(GameObject parent)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
"author": "xen",
|
"author": "xen",
|
||||||
"name": "New Horizons",
|
"name": "New Horizons",
|
||||||
"uniqueName": "xen.NewHorizons",
|
"uniqueName": "xen.NewHorizons",
|
||||||
"version": "0.8.1",
|
"version": "0.8.3",
|
||||||
"owmlVersion": "2.1.0",
|
"owmlVersion": "2.1.0",
|
||||||
"dependencies": [ "PacificEngine.OW_CommonResources" ],
|
"dependencies": [ "PacificEngine.OW_CommonResources" ],
|
||||||
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.OuterWildsMMO", "Vesper.AutoResume" ]
|
"conflicts": [ "Raicuparta.QuantumSpaceBuddies", "Vesper.OuterWildsMMO", "Vesper.AutoResume" ]
|
||||||
|
|||||||
60
README.md
60
README.md
@ -1,4 +1,4 @@
|
|||||||

|

|
||||||
|
|
||||||

|

|
||||||

|

|
||||||
@ -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)
|
- Separate solar system scenes accessible via wormhole (done)
|
||||||
- Warp drive with target set in ship's log (done)
|
- Warp drive with target set in ship's log (done)
|
||||||
- Implement custom dialogue (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)
|
- Procedural terrain generation (started)
|
||||||
- "Quantum" planet parameters
|
- "Quantum" planet parameters
|
||||||
- Better terrain and water LOD
|
- Better terrain and water LOD
|
||||||
- Edit existing planet orbits
|
- Edit existing planet orbits
|
||||||
- Implement all planet features:
|
- 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)
|
- 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
|
- Let any star go supernova
|
||||||
- Geysers
|
- Geysers
|
||||||
- Meteors
|
- Meteors
|
||||||
- Ghost matter
|
|
||||||
- Pocket dimensions
|
- Pocket dimensions
|
||||||
- Timed position/velocity changes
|
- Timed position/velocity changes
|
||||||
- Zero-g volumes
|
|
||||||
- Implement custom Nomai scrolls
|
- Implement custom Nomai scrolls
|
||||||
- Implement custom translatable writing
|
- Implement custom translatable writing
|
||||||
- Implement constant gravity volumes
|
|
||||||
- Destroy planets that fall into a star
|
- 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
|
## 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.
|
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).
|
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
|
|||||||

|

|
||||||
|
|
||||||
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:
|
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",
|
"name" : "Wetrock",
|
||||||
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/master/NewHorizons/schema.json",
|
"$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" :
|
"Base" :
|
||||||
{
|
{
|
||||||
"groundSize" : 100,
|
"groundSize" : 100,
|
||||||
"waterSize" : 101,
|
|
||||||
"surfaceSize" : 101,
|
"surfaceSize" : 101,
|
||||||
"surfaceGravity" : 12,
|
"surfaceGravity" : 12,
|
||||||
"hasMapMarker" : true,
|
"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:
|
Modules look like this:
|
||||||
|
|
||||||
```
|
```json
|
||||||
"Star" :
|
"Star" :
|
||||||
{
|
{
|
||||||
"size" : 3000,
|
"size" : 3000,
|
||||||
@ -174,7 +174,7 @@ 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:
|
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:
|
#### Colour:
|
||||||
```
|
```json
|
||||||
{
|
{
|
||||||
"r" : 200,
|
"r" : 200,
|
||||||
"g" : 255,
|
"g" : 255,
|
||||||
@ -184,7 +184,7 @@ Most fields are either true/false, a decimal number, and integer number, or a st
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Position:
|
#### Position:
|
||||||
```
|
```json
|
||||||
{
|
{
|
||||||
"x" : 182.4,
|
"x" : 182.4,
|
||||||
"y" : 227.4,
|
"y" : 227.4,
|
||||||
@ -193,7 +193,7 @@ Most fields are either true/false, a decimal number, and integer number, or a st
|
|||||||
```
|
```
|
||||||
|
|
||||||
#### Scale curve:
|
#### Scale curve:
|
||||||
```
|
```json
|
||||||
[
|
[
|
||||||
{"time":0, "value":1},
|
{"time":0, "value":1},
|
||||||
{"time":5, "value":0},
|
{"time":5, "value":0},
|
||||||
@ -271,7 +271,7 @@ Let's you put asteroids in orbit around a planet or star. Can probably negativel
|
|||||||
### FocalPoint
|
### 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 "..."):
|
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",
|
"name" : "Alpha Centauri",
|
||||||
"Base" :
|
"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.
|
Then you would make config files for the two bodies in the binary pair.
|
||||||
```
|
```json
|
||||||
{
|
{
|
||||||
"name" : "Alpha Centauri A",
|
"name" : "Alpha Centauri A",
|
||||||
"Base" :
|
"Base" :
|
||||||
@ -312,7 +312,7 @@ Then you would make config files for the two bodies in the binary pair.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
and
|
and
|
||||||
```
|
```json
|
||||||
{
|
{
|
||||||
"name" : "Alpha Centauri B",
|
"name" : "Alpha Centauri B",
|
||||||
"Base" :
|
"Base" :
|
||||||
@ -346,7 +346,7 @@ The different things you can specify in the props section are:
|
|||||||
|
|
||||||
- "scatter" : (list) I'll just give an example.
|
- "scatter" : (list) I'll just give an example.
|
||||||
|
|
||||||
```
|
```json
|
||||||
"scatter" : [
|
"scatter" : [
|
||||||
{"path" : "DreamWorld_Body/Sector_DreamWorld/Sector_DreamZone_1/Props_DreamZone_1/OtherComponentsGroup/Trees_Z1/DreamHouseIsland/Tree_DW_M_Var", "count" : 12}
|
{"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)
|
- "rotation" : (x, y, z) the euler angle rotation from a 3d vector (in degrees)
|
||||||
- "scale" : (decimal number)
|
- "scale" : (decimal number)
|
||||||
- "alignToNormal" : (true/false) If it should align with the normal vector of the surface its own (overwrites rotation)
|
- "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.
|
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
|
#### 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.
|
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:
|
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 UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
@ -407,7 +415,7 @@ An array of object, each one has the following properties:
|
|||||||
#### XML
|
#### XML
|
||||||
Here's an example dialogue XML:
|
Here's an example dialogue XML:
|
||||||
|
|
||||||
```
|
```xml
|
||||||
<DialogueTree>
|
<DialogueTree>
|
||||||
<NameField>EXAMPLE NPC</NameField>
|
<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
|
- "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:
|
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" :
|
"Signal" :
|
||||||
{
|
{
|
||||||
"Signals" :
|
"Signals" :
|
||||||
@ -570,7 +578,7 @@ This allows you to make black holes and white holes, and to pair them.
|
|||||||
### How to destroy existing planets
|
### How to destroy existing planets
|
||||||
|
|
||||||
You do this (but with the appropriate name) as it's own config.
|
You do this (but with the appropriate name) as it's own config.
|
||||||
```
|
```json
|
||||||
{
|
{
|
||||||
"name" : "Ember Twin",
|
"name" : "Ember Twin",
|
||||||
"destroy" : true,
|
"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.
|
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
|
## How to use New Horizons in other mods
|
||||||
|
|
||||||
First create the following interface in your mod:
|
First create the following interface in your mod:
|
||||||
|
|
||||||
```
|
```cs
|
||||||
public interface INewHorizons
|
public interface INewHorizons
|
||||||
{
|
{
|
||||||
void Create(Dictionary<string, object> config, IModBehaviour mod);
|
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:
|
In your main `ModBehaviour` class you can get the NewHorizons API like so:
|
||||||
```
|
```cs
|
||||||
INewHorizons NewHorizonsAPI = ModHelper.Interaction.GetModApi<INewHorizons>("xen.NewHorizons")
|
INewHorizons NewHorizonsAPI = ModHelper.Interaction.GetModApi<INewHorizons>("xen.NewHorizons")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user