Decluttered logs and added asteroid belts

Also includes some basic proc gen
This commit is contained in:
Nick J. Connors 2021-12-19 02:37:52 -05:00
parent 66b099c594
commit c977cb5333
42 changed files with 929 additions and 356 deletions

Binary file not shown.

View File

@ -1,9 +1,9 @@
ManifestFileVersion: 0
CRC: 3655445632
CRC: 3840241390
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 160438a2f12bb2f4bd67ddfa0e6f2f3f
Hash: 1c2c90716d1ed7c9cbf5f785e41eace6
TypeTreeHash:
serializedVersion: 2
Hash: 6370d3f9de9eca57f523bce048404a46
@ -13,4 +13,5 @@ ClassTypes:
Script: {instanceID: 0}
Assets:
- Assets/SphereTextureWrapper.shader
- Assets/UnlitTransparent.shader
Dependencies: []

View File

@ -60,7 +60,6 @@ namespace NewHorizons.Atmosphere
}
airGO.SetActive(true);
Logger.Log("Finished building air.", Logger.LogType.Log);
}
}
}

View File

@ -77,7 +77,6 @@ namespace NewHorizons.Atmosphere
}
atmoGO.SetActive(true);
Logger.Log("Finished building atmosphere.", Logger.LogType.Log);
}
}
}

View File

@ -110,11 +110,13 @@ namespace NewHorizons.Atmosphere
fluidCLFV.SetValue("_allowShipAutoroll", true);
fluidCLFV.SetValue("_disableOnStart", false);
// Fix the rotations once the rest is done
cloudsMainGO.transform.localRotation = Quaternion.Euler(0, 0, 0);
cloudsTopGO.SetActive(true);
cloudsBottomGO.SetActive(true);
cloudsFluidGO.SetActive(true);
cloudsMainGO.SetActive(true);
Logger.Log("Finished building clouds.", Logger.LogType.Log);
}
}
}

View File

@ -51,8 +51,6 @@ namespace NewHorizons.Atmosphere
}
effectsGO.SetActive(true);
Logger.Log("Finished building effects", Logger.LogType.Log);
}
}
}

View File

@ -21,7 +21,6 @@ namespace NewHorizons.Atmosphere
GDSOV.SetValue("_waterInnerRadius", 0f);
overrideGO.SetActive(true);
Logger.Log("Finished building sun override.", Logger.LogType.Log);
}
}
}

View File

@ -38,7 +38,6 @@ namespace NewHorizons.Atmosphere
rulesetGO.SetActive(true);
volumesGO.SetActive(true);
Logger.Log("Finished building volumes", Logger.LogType.Log);
}
}
}

View File

@ -0,0 +1,64 @@
using NewHorizons.External;
using NewHorizons.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
using Random = UnityEngine.Random;
namespace NewHorizons.Body
{
static class AsteroidBeltBuilder
{
public static void Make(string bodyName, AsteroidBeltModule belt)
{
var minSize = 20;
var maxSize = 50;
int count = (int)(2f * Mathf.PI * belt.InnerRadius / (10f * maxSize));
if (count > 400) count = 400;
Logger.Log($"Making {count} asteroids around {bodyName}");
for (int i = 0; i < count; i++)
{
var size = Random.Range(minSize, maxSize);
var config = new Dictionary<string, object>()
{
{"Name", $"{bodyName} Asteroid {i}"},
{"Base", new Dictionary<string, object>()
{
{"HasMapMarker", false },
{"SurfaceGravity", 1 },
{"SurfaceSize", size },
{"HideOrbitLine", true }
}
},
{"Orbit", new Dictionary<string, object>()
{
{"IsMoon", true },
{"Inclination", belt.Inclination + Random.Range(-2f, 2f) },
{"LongitudeOfAscendingNode", belt.LongitudeOfAscendingNode },
{"TrueAnomaly", 360f * (i + Random.Range(-0.2f, 0.2f)) / (float)count },
{"PrimaryBody", bodyName },
{"SemiMajorAxis", maxSize * Random.Range(belt.InnerRadius, belt.OuterRadius) }
}
},
{"ProcGen", new Dictionary<string, object>()
{
{"Scale", size },
{"Color", new MColor32(126, 94, 73, 255) }
}
}
};
Logger.Log($"{config}");
var asteroid = new NewHorizonsBody(new PlanetConfig(config));
Main.AdditionalBodies.Add(asteroid);
}
}
}
}

View File

@ -48,10 +48,6 @@ namespace NewHorizons.Body
for (int x = 0; x <= resolution; x++)
{
SetVertex(vertices, normals, uvs, v++, x, y, 0, resolution, heightMap, minHeight, maxHeight);
if (x == resolution / 2 && y < resolution / 2)
{
Logger.Log($"{uvs[v - 1]}");
}
}
for (int z = 1; z <= resolution; z++)
{
@ -60,10 +56,6 @@ namespace NewHorizons.Body
for (int x = resolution - 1; x >= 0; x--)
{
SetVertex(vertices, normals, uvs, v++, x, y, resolution, resolution, heightMap, minHeight, maxHeight);
if (x == resolution / 2 && y < resolution / 2)
{
Logger.Log($"{uvs[v - 1]}");
}
}
for (int z = resolution - 1; z > 0; z--)
{
@ -83,10 +75,6 @@ namespace NewHorizons.Body
for (int x = 1; x < resolution; x++)
{
SetVertex(vertices, normals, uvs, v++, x, 0, z, resolution, heightMap, minHeight, maxHeight);
if (x == resolution / 2)
{
Logger.Log($"{uvs[v - 1]}");
}
}
}

View File

@ -4,6 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Random = UnityEngine.Random;
namespace NewHorizons.Body.Geometry
{
@ -59,7 +60,7 @@ namespace NewHorizons.Body.Geometry
}
};
public static Mesh Build(int subdivisions, Texture2D heightMap, float minHeight, float maxHeight)
public static Mesh Build(int subdivisions, float minHeight, float maxHeight)
{
Mesh mesh = new Mesh();
@ -72,7 +73,7 @@ namespace NewHorizons.Body.Geometry
Vector3[] normals = new Vector3[verticesToCopy.Length];
Vector2[] uvs = new Vector2[verticesToCopy.Length];
Dictionary<float, int> seamVertices = new Dictionary<float, int>();
var randomOffset = new Vector3(Random.Range(0, 10f), Random.Range(0, 10f), Random.Range(0, 10f));
for(int i = 0; i < verticesToCopy.Length; i++)
{
@ -80,11 +81,8 @@ namespace NewHorizons.Body.Geometry
float latitude = Mathf.Repeat(Mathf.Rad2Deg * Mathf.Acos(v.z / Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z)), 180f);
float longitude = Mathf.Repeat(Mathf.Rad2Deg * (v.x > 0 ? Mathf.Atan(v.y / v.x) : Mathf.Atan(v.y / v.x) + Mathf.PI) + 90f, 360f);
float sampleX = heightMap.width * longitude / 360f;
float sampleY = heightMap.height * latitude / 180f;
float height = heightMap.GetPixel((int)sampleX, (int)sampleY).r * (maxHeight - minHeight) + minHeight;
float height = Perlin.Noise(v + randomOffset) * (maxHeight - minHeight) + minHeight;
newVertices[i] = verticesToCopy[i] * height;
normals[i] = v.normalized;
@ -92,9 +90,6 @@ namespace NewHorizons.Body.Geometry
var x = longitude / 360f;
var y = latitude / 180f;
if (x == 0) seamVertices.Add(y, i);
uvs[i] = new Vector2(x, y);
}

View File

@ -0,0 +1,176 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Body.Geometry
{
// Perlin noise generator for Unity
// Keijiro Takahashi, 2013, 2015
// https://github.com/keijiro/PerlinNoise
public static class Perlin
{
#region Noise functions
public static float Noise(float x)
{
var X = Mathf.FloorToInt(x) & 0xff;
x -= Mathf.Floor(x);
var u = Fade(x);
return Lerp(u, Grad(perm[X], x), Grad(perm[X + 1], x - 1)) * 2;
}
public static float Noise(float x, float y)
{
var X = Mathf.FloorToInt(x) & 0xff;
var Y = Mathf.FloorToInt(y) & 0xff;
x -= Mathf.Floor(x);
y -= Mathf.Floor(y);
var u = Fade(x);
var v = Fade(y);
var A = (perm[X] + Y) & 0xff;
var B = (perm[X + 1] + Y) & 0xff;
return Lerp(v, Lerp(u, Grad(perm[A], x, y), Grad(perm[B], x - 1, y)),
Lerp(u, Grad(perm[A + 1], x, y - 1), Grad(perm[B + 1], x - 1, y - 1)));
}
public static float Noise(Vector2 coord)
{
return Noise(coord.x, coord.y);
}
public static float Noise(float x, float y, float z)
{
var X = Mathf.FloorToInt(x) & 0xff;
var Y = Mathf.FloorToInt(y) & 0xff;
var Z = Mathf.FloorToInt(z) & 0xff;
x -= Mathf.Floor(x);
y -= Mathf.Floor(y);
z -= Mathf.Floor(z);
var u = Fade(x);
var v = Fade(y);
var w = Fade(z);
var A = (perm[X] + Y) & 0xff;
var B = (perm[X + 1] + Y) & 0xff;
var AA = (perm[A] + Z) & 0xff;
var BA = (perm[B] + Z) & 0xff;
var AB = (perm[A + 1] + Z) & 0xff;
var BB = (perm[B + 1] + Z) & 0xff;
return Lerp(w, Lerp(v, Lerp(u, Grad(perm[AA], x, y, z), Grad(perm[BA], x - 1, y, z)),
Lerp(u, Grad(perm[AB], x, y - 1, z), Grad(perm[BB], x - 1, y - 1, z))),
Lerp(v, Lerp(u, Grad(perm[AA + 1], x, y, z - 1), Grad(perm[BA + 1], x - 1, y, z - 1)),
Lerp(u, Grad(perm[AB + 1], x, y - 1, z - 1), Grad(perm[BB + 1], x - 1, y - 1, z - 1))));
}
public static float Noise(Vector3 coord)
{
return Noise(coord.x, coord.y, coord.z);
}
#endregion
#region fBm functions
public static float Fbm(float x, int octave)
{
var f = 0.0f;
var w = 0.5f;
for (var i = 0; i < octave; i++)
{
f += w * Noise(x);
x *= 2.0f;
w *= 0.5f;
}
return f;
}
public static float Fbm(Vector2 coord, int octave)
{
var f = 0.0f;
var w = 0.5f;
for (var i = 0; i < octave; i++)
{
f += w * Noise(coord);
coord *= 2.0f;
w *= 0.5f;
}
return f;
}
public static float Fbm(float x, float y, int octave)
{
return Fbm(new Vector2(x, y), octave);
}
public static float Fbm(Vector3 coord, int octave)
{
var f = 0.0f;
var w = 0.5f;
for (var i = 0; i < octave; i++)
{
f += w * Noise(coord);
coord *= 2.0f;
w *= 0.5f;
}
return f;
}
public static float Fbm(float x, float y, float z, int octave)
{
return Fbm(new Vector3(x, y, z), octave);
}
#endregion
#region Private functions
static float Fade(float t)
{
return t * t * t * (t * (t * 6 - 15) + 10);
}
static float Lerp(float t, float a, float b)
{
return a + t * (b - a);
}
static float Grad(int hash, float x)
{
return (hash & 1) == 0 ? x : -x;
}
static float Grad(int hash, float x, float y)
{
return ((hash & 1) == 0 ? x : -x) + ((hash & 2) == 0 ? y : -y);
}
static float Grad(int hash, float x, float y, float z)
{
var h = hash & 15;
var u = h < 8 ? x : y;
var v = h < 4 ? y : (h == 12 || h == 14 ? x : z);
return ((h & 1) == 0 ? u : -u) + ((h & 2) == 0 ? v : -v);
}
static int[] perm = {
151,160,137,91,90,15,
131,13,201,95,96,53,194,233,7,225,140,36,103,30,69,142,8,99,37,240,21,10,23,
190, 6,148,247,120,234,75,0,26,197,62,94,252,219,203,117,35,11,32,57,177,33,
88,237,149,56,87,174,20,125,136,171,168, 68,175,74,165,71,134,139,48,27,166,
77,146,158,231,83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,
102,143,54, 65,25,63,161, 1,216,80,73,209,76,132,187,208, 89,18,169,200,196,
135,130,116,188,159,86,164,100,109,198,173,186, 3,64,52,217,226,250,124,123,
5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16,58,17,182,189,28,42,
223,183,170,213,119,248,152, 2,44,154,163, 70,221,153,101,155,167, 43,172,9,
129,22,39,253, 19,98,108,110,79,113,224,232,178,185, 112,104,218,246,97,228,
251,34,242,193,238,210,144,12,191,179,162,241, 81,51,145,235,249,14,239,107,
49,192,214, 31,181,199,106,157,184, 84,204,176,115,121,50,45,127, 4,150,254,
138,236,205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180,
151
};
#endregion
}
}

View File

@ -49,7 +49,6 @@ namespace NewHorizons.Body
geo.SetActive(true);
*/
Logger.Log("Finished building geometry", Logger.LogType.Log);
}
}
}

View File

@ -12,7 +12,6 @@ namespace NewHorizons.Body
{
static class HeightMapBuilder
{
public static AssetBundle ShaderBundle;
public static Shader PlanetShader;
public static void Make(GameObject go, HeightMapModule module)
@ -29,7 +28,6 @@ namespace NewHorizons.Body
return;
}
GameObject cubeSphere = new GameObject("CubeSphere");
cubeSphere.transform.parent = go.transform;
cubeSphere.transform.rotation = Quaternion.Euler(90, 0, 0);
@ -39,8 +37,7 @@ namespace NewHorizons.Body
cubeSphere.AddComponent<MeshFilter>();
cubeSphere.GetComponent<MeshFilter>().mesh = mesh;
if(ShaderBundle == null) ShaderBundle = Main.Instance.ModHelper.Assets.LoadBundle("assets/shader");
if(PlanetShader == null) PlanetShader = ShaderBundle.LoadAsset<Shader>("Assets/SphereTextureWrapper.shader");
if(PlanetShader == null) PlanetShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/SphereTextureWrapper.shader");
var cubeSphereMR = cubeSphere.AddComponent<MeshRenderer>();
cubeSphereMR.material = new Material(PlanetShader);
@ -48,7 +45,9 @@ namespace NewHorizons.Body
var cubeSphereMC = cubeSphere.AddComponent<MeshCollider>();
cubeSphereMC.sharedMesh = mesh;
// Fix rotation in the end
cubeSphere.transform.localRotation = Quaternion.Euler(90, 0, 0);
/*
GameObject icosphere = new GameObject("Icosphere");
@ -66,6 +65,7 @@ namespace NewHorizons.Body
var cubeSphereMC = icosphere.AddComponent<MeshCollider>();
cubeSphereMC.sharedMesh = mesh;
icosphere.transform.localRotation = Quaternion.Euler(90, 0, 0);
*/
}
}

View File

@ -0,0 +1,34 @@
using NewHorizons.Body.Geometry;
using NewHorizons.External;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Body
{
static class ProcGenBuilder
{
public static void Make(GameObject go, ProcGenModule module)
{
GameObject icosphere = new GameObject("Icosphere");
icosphere.transform.parent = go.transform;
icosphere.transform.rotation = Quaternion.Euler(90, 0, 0);
Mesh mesh = Icosphere.Build(3, module.Scale, module.Scale * 1.2f);
icosphere.AddComponent<MeshFilter>();
icosphere.GetComponent<MeshFilter>().mesh = mesh;
var cubeSphereMR = icosphere.AddComponent<MeshRenderer>();
cubeSphereMR.material = new Material(Shader.Find("Standard"));
cubeSphereMR.material.color = module.Color.ToColor32();
var cubeSphereMC = icosphere.AddComponent<MeshCollider>();
cubeSphereMC.sharedMesh = mesh;
icosphere.transform.localRotation = Quaternion.Euler(90, 0, 0);
}
}
}

View File

@ -11,7 +11,9 @@ namespace NewHorizons.General
{
static class RingBuilder
{
public static void Make(GameObject body, RingModule ring)
public static Shader RingShader;
public static void Make(GameObject body, RingModule ring)
{
Texture2D ringTexture;
try
@ -27,6 +29,7 @@ namespace NewHorizons.General
var ringGO = new GameObject("Ring");
ringGO.transform.parent = body.transform;
ringGO.transform.localPosition = Vector3.zero;
ringGO.transform.localRotation = Quaternion.Euler(0, 0, 0);
ringGO.transform.Rotate(ringGO.transform.TransformDirection(Vector3.up), ring.LongitudeOfAscendingNode);
ringGO.transform.Rotate(ringGO.transform.TransformDirection(Vector3.right), ring.Inclination);
@ -35,7 +38,9 @@ namespace NewHorizons.General
var ringMR = ringGO.AddComponent<MeshRenderer>();
var texture = ringTexture;
var mat = new Material(Shader.Find("Legacy Shaders/Particles/Alpha Blended Premultiply"));
if (RingShader == null) RingShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/UnlitTransparent.shader");
var mat = new Material(RingShader);
mat.mainTexture = texture;
mat.renderQueue = 3000;
ringMR.material = mat;
@ -43,8 +48,6 @@ namespace NewHorizons.General
// Make mesh
var segments = (int)Math.Max(20, ring.OuterRadius);
BuildRingMesh(ringMesh, segments, ring.InnerRadius, ring.OuterRadius);
Logger.Log("Finished building rings", Logger.LogType.Log);
}
// Thank you https://github.com/boardtobits/planet-ring-mesh/blob/master/PlanetRing.cs

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Body
{
static class SunBuilder
{
public static void Make(GameObject body, Sector sector)
{
}
}
}

View File

@ -80,8 +80,6 @@ namespace NewHorizons.Body
*/
waterGO.SetActive(true);
Logger.Log("Finished building water", Logger.LogType.Log);
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External
{
public class AsteroidBeltModule : Module
{
public float InnerRadius { get; set; }
public float OuterRadius { get; set; }
public float Inclination { get; set; }
public float LongitudeOfAscendingNode { get; set; }
}
}

View File

@ -17,5 +17,6 @@ namespace NewHorizons.External
public float GroundSize { get; set; }
public float BlackHoleSize { get; set; }
public float LavaSize { get; set; }
public bool HideOrbitLine { get; set; }
}
}

View File

@ -11,6 +11,8 @@ namespace NewHorizons.External
OrbitModule Orbit { get; }
RingModule Ring { get; }
HeightMapModule HeightMap { get; }
ProcGenModule ProcGen { get; }
AsteroidBeltModule AsteroidBelt { get; }
SpawnModule Spawn { get; }
}
}

View File

@ -17,10 +17,8 @@ namespace NewHorizons.External
}
foreach (var item in dict)
{
Logger.Log($"{item.Key} : {item.Value}", Logger.LogType.Log);
var field = GetType().GetField(item.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
field.SetValue(this, Convert.ChangeType(item.Value, field.FieldType));
var property = GetType().GetProperty(item.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
property.SetValue(this, Convert.ChangeType(item.Value, property.PropertyType));
}
}
}

View File

@ -15,6 +15,7 @@ namespace NewHorizons.External
public float LongitudeOfAscendingNode { get; set; }
public float Eccentricity { get; set; }
public float ArgumentOfPeriapsis { get; set; }
public float TrueAnomaly { get; set; }
public float AxialTilt { get; set; }
public float SiderealPeriod { get; set; }
public bool IsTidallyLocked { get; set; }

View File

@ -14,33 +14,32 @@ namespace NewHorizons.External
public OrbitModule Orbit { get; set; }
public RingModule Ring { get; set; }
public HeightMapModule HeightMap { get; set; }
public ProcGenModule ProcGen { get; set; }
public AsteroidBeltModule AsteroidBelt { get; set; }
public SpawnModule Spawn { get; set; }
public PlanetConfig(Dictionary<string, object> dict)
{
// Always have to have a base module
// Always have to have a base module and orbit module
Base = new BaseModule();
if (dict == null)
{
return;
}
Orbit = new OrbitModule();
if (dict == null) return;
foreach (var item in dict)
{
Logger.Log($"{item.Key} : {item.Value}", Logger.LogType.Log);
switch(item.Key)
{
case "Base":
Base.Build(item.Value as Dictionary<string, object>);
break;
case "Orbit":
Orbit.Build(item.Value as Dictionary<string, object>);
break;
case "Atmosphere":
Atmosphere = new AtmosphereModule();
Atmosphere.Build(item.Value as Dictionary<string, object>);
break;
case "Orbit":
Orbit = new OrbitModule();
Orbit.Build(item.Value as Dictionary<string, object>);
break;
case "Ring":
Ring = new RingModule();
Ring.Build(item.Value as Dictionary<string, object>);
@ -49,23 +48,24 @@ namespace NewHorizons.External
HeightMap = new HeightMapModule();
HeightMap.Build(item.Value as Dictionary<string, object>);
break;
case "ProcGen":
ProcGen = new ProcGenModule();
ProcGen.Build(item.Value as Dictionary<string, object>);
break;
case "AsteroidBelt":
AsteroidBelt = new AsteroidBeltModule();
AsteroidBelt.Build(item.Value as Dictionary<string, object>);
break;
case "Spawn":
Spawn = new SpawnModule();
Spawn.Build(item.Value as Dictionary<string, object>);
break;
default:
var field = GetType().GetField(item.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (field != null)
field.SetValue(this, Convert.ChangeType(item.Value, field.FieldType));
else
Logger.LogError($"{item.Key} is not valid. Is your config file formatted correctly?");
var property = typeof(PlanetConfig).GetProperty(item.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (property != null) property.SetValue(this, Convert.ChangeType(item.Value, property.PropertyType));
else Logger.LogError($"{item.Key} {item.Value} is not valid. Is your config formatted correctly?");
break;
}
/*
var field = GetType().GetField(item.Key, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
field.SetValue(this, Convert.ChangeType(item.Value, field.FieldType));
*/
}
}
}

15
NewHorizons/External/ProcGenModule.cs vendored Normal file
View File

@ -0,0 +1,15 @@
using NewHorizons.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External
{
public class ProcGenModule : Module
{
public float Scale { get; set; }
public MColor32 Color { get; set; }
}
}

View File

@ -19,8 +19,6 @@ namespace NewHorizons.General
light.color = new Color(0.5f, 1f, 1f, 0.0225f);
light.range = scale;
light.intensity = 0.5f;
Logger.Log("Finished building ambient light", Logger.LogType.Log);
}
}
}

View File

@ -26,18 +26,6 @@ namespace NewHorizons.General
OWRB.SetValue("_maintainOriginalCenterOfMass", true);
OWRB.SetValue("_rigidbody", RB);
InitialMotion IM = body.AddComponent<InitialMotion>();
IM.SetPrimaryBody(primaryBody.GetAttachedOWRigidbody());
IM.SetValue("_orbitAngle", config.Orbit.Inclination);
IM.SetValue("_isGlobalAxis", false);
IM.SetValue("_initAngularSpeed", config.Orbit.SiderealPeriod == 0 ? 0.02f : 1.0f / config.Orbit.SiderealPeriod);
var orbitVector = positionVector.normalized;
var rotationAxis = Quaternion.AngleAxis(config.Orbit.AxialTilt + config.Orbit.Inclination, orbitVector) * Vector3.up;
IM.SetValue("_rotationAxis", rotationAxis);
IM.SetValue("_initLinearSpeed", 0f);
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
DetectorBuilder.Make(body, primaryBody);
AstroObject AO = body.AddComponent<AstroObject>();
@ -55,7 +43,6 @@ namespace NewHorizons.General
*/
}
Logger.Log("Finished building base", Logger.LogType.Log);
return new MTuple(AO, OWRB);
}
}

View File

@ -1,4 +1,5 @@
using OWML.Utils;
using System;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
@ -14,13 +15,13 @@ namespace NewHorizons.General
detectorGO.layer = 20;
ConstantForceDetector CFD = detectorGO.AddComponent<ConstantForceDetector>();
ForceVolume[] temp = new ForceVolume[1];
temp[0] = primaryBody.GetAttachedOWRigidbody().GetAttachedGravityVolume();
CFD.SetValue("_detectableFields", temp);
GravityVolume parentGravityVolume = primaryBody.GetAttachedOWRigidbody().GetAttachedGravityVolume();
CFD.SetValue("_detectableFields", new ForceVolume[] { parentGravityVolume });
CFD.SetValue("_inheritElement0", true);
detectorGO.SetActive(true);
Logger.Log("Finished building detector", Logger.LogType.Log);
}
}
}

View File

@ -40,8 +40,6 @@ namespace NewHorizons.General
gravityGO.SetActive(true);
ao.SetValue("_gravityVolume", GV);
Logger.Log("Finished building gravity", Logger.LogType.Log);
}
}
}

View File

@ -0,0 +1,54 @@
using NewHorizons.External;
using OWML.Utils;
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.General
{
static class InitialMotionBuilder
{
public static InitialMotion Make(GameObject body, AstroObject primaryBody, OWRigidbody OWRB, Vector3 positionVector, OrbitModule orbit)
{
InitialMotion IM = body.AddComponent<InitialMotion>();
IM.SetPrimaryBody(primaryBody.GetAttachedOWRigidbody());
IM.SetValue("_orbitAngle", orbit.Inclination);
IM.SetValue("_isGlobalAxis", false);
IM.SetValue("_initAngularSpeed", orbit.SiderealPeriod == 0 ? 0.02f : 1.0f / orbit.SiderealPeriod);
// Initial velocity
var distance = positionVector - primaryBody.transform.position;
var speed = Kepler.OrbitalHelper.VisViva(primaryBody.GetGravityVolume().GetStandardGravitationalParameter(), distance, orbit.SemiMajorAxis);
var direction = Kepler.OrbitalHelper.EllipseTangent(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.LongitudeOfAscendingNode, orbit.ArgumentOfPeriapsis, orbit.TrueAnomaly);
var velocity = speed * direction;
// Cancel out what the game does
if(orbit.Eccentricity != 0)
{
var oldVelocity = Kepler.OrbitalHelper.CalculateOrbitVelocity(primaryBody.GetAttachedOWRigidbody(), distance, orbit.Inclination);
if (!float.IsNaN(oldVelocity.magnitude)) velocity -= oldVelocity;
else Logger.LogError($"The original orbital velocity for {body.name} was calculated to be NaN?");
var trueSpeed = velocity.magnitude;
var trueDirection = velocity.normalized;
Logger.Log($"Setting initial motion {velocity.magnitude} in direction {velocity.normalized}");
if (!float.IsNaN(trueSpeed) && trueDirection != Vector3.zero)
{
IM.SetValue("_initLinearDirection", velocity.normalized);
IM.SetValue("_initLinearSpeed", velocity.magnitude);
}
else Logger.LogError($"Could not set velocity ({speed}, {direction}) -> ({trueSpeed}, {trueDirection}) for {body.name}");
}
var rotationAxis = Quaternion.AngleAxis(orbit.AxialTilt + orbit.Inclination, Vector3.right) * Vector3.up;
body.transform.rotation = Quaternion.FromToRotation(Vector3.up, rotationAxis);
return IM;
}
}
}

View File

@ -21,7 +21,6 @@ namespace NewHorizons.General
{
MM.SetValue("_markerType", MM.GetType().GetNestedType("MarkerType", BindingFlags.NonPublic).GetField("Planet").GetValue(MM));
}
Logger.Log("Finished building map marker", Logger.LogType.Log);
}
}
}

View File

@ -1,4 +1,6 @@
using OWML.Utils;
using NewHorizons.External;
using NewHorizons.Utility;
using OWML.Utils;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
@ -6,28 +8,25 @@ namespace NewHorizons.General
{
static class OrbitlineBuilder
{
public static void Make(GameObject body, AstroObject astroobject, bool isMoon)
public static void Make(GameObject body, AstroObject astroobject, bool isMoon, OrbitModule orbit)
{
GameObject orbit = new GameObject("Orbit");
orbit.transform.parent = body.transform;
GameObject orbitGO = new GameObject("Orbit");
orbitGO.transform.parent = body.transform;
var LR = orbit.AddComponent<LineRenderer>();
var LR = orbitGO.AddComponent<LineRenderer>();
var thLR = GameObject.Find("OrbitLine_TH").GetComponent<LineRenderer>();
var thLR = GameObject.Find("OrbitLine_CO").GetComponent<LineRenderer>();
LR.material = thLR.material;
LR.useWorldSpace = false;
LR.loop = false;
Logger.Log("AO primary body is " + astroobject.GetPrimaryBody().name, Logger.LogType.Log);
var ol = orbit.AddComponent<OrbitLine>();
OrbitLine ol = orbit.Eccentricity != 0 ? orbitGO.AddComponent<EllipticOrbitLine>() : orbitGO.AddComponent<OrbitLine>();
ol.SetValue("_astroObject", astroobject);
ol.SetValue("_fade", isMoon);
ol.SetValue("_lineWidth", 0.5f);
//ol.SetOrbitalParameters(orbit.Eccentricity, orbit.SemiMajorAxis, orbit.Inclination, orbit.LongitudeOfAscendingNode, orbit.ArgumentOfPeriapsis, orbit.TrueAnomaly);
typeof(OrbitLine).GetMethod("InitializeLineRenderer", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).Invoke(ol, new object[] { });
Logger.Log("Finished building orbit line", Logger.LogType.Log);
}
}
}

View File

@ -0,0 +1,118 @@
using NewHorizons.Utility;
using OWML.Utils;
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.General
{
static class PlanetDestroyer
{
public static void RemoveBody(AstroObject ao, List<AstroObject> toDestroy = null)
{
Logger.Log($"Removing {ao.name}");
if (ao.gameObject == null || !ao.gameObject.activeInHierarchy) return;
if (toDestroy == null) toDestroy = new List<AstroObject>();
if (toDestroy.Contains(ao))
{
Logger.LogError($"Possible infinite recursion in RemoveBody: {ao.name} might be it's own primary body?");
return;
}
toDestroy.Add(ao);
if (ao.GetAstroObjectName() == AstroObject.Name.BrittleHollow)
RemoveBody(AstroObjectLocator.GetAstroObject(AstroObject.Name.WhiteHole), toDestroy);
// Check if any other objects depend on it and remove them too
var aoArray = AstroObjectLocator.GetAllAstroObjects();
foreach (AstroObject obj in aoArray)
{
if (obj?.gameObject == null || !obj.gameObject.activeInHierarchy)
{
AstroObjectLocator.RemoveAstroObject(obj);
continue;
}
if (ao.Equals(obj.GetPrimaryBody()))
{
AstroObjectLocator.RemoveAstroObject(obj);
RemoveBody(obj, toDestroy);
}
}
if (ao.GetAstroObjectName() == AstroObject.Name.CaveTwin || ao.GetAstroObjectName() == AstroObject.Name.TowerTwin)
{
var focalBody = GameObject.Find("FocalBody");
if (focalBody != null) focalBody.SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.MapSatellite)
{
var msb = GameObject.Find("MapSatellite_Body");
if (msb != null) msb.SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.TowerTwin)
GameObject.Find("TimeLoopRing_Body").SetActive(false);
if (ao.GetAstroObjectName() == AstroObject.Name.ProbeCannon)
{
GameObject.Find("NomaiProbe_Body").SetActive(false);
GameObject.Find("CannonMuzzle_Body").SetActive(false);
GameObject.Find("FakeCannonMuzzle_Body (1)").SetActive(false);
GameObject.Find("CannonBarrel_Body").SetActive(false);
GameObject.Find("FakeCannonBarrel_Body (1)").SetActive(false);
GameObject.Find("Debris_Body (1)").SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.SunStation)
{
GameObject.Find("SS_Debris_Body").SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.GiantsDeep)
{
GameObject.Find("BrambleIsland_Body").SetActive(false);
GameObject.Find("GabbroIsland_Body").SetActive(false);
GameObject.Find("QuantumIsland_Body").SetActive(false);
GameObject.Find("StatueIsland_Body").SetActive(false);
GameObject.Find("ConstructionYardIsland_Body").SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.WhiteHole)
{
GameObject.Find("WhiteholeStation_Body").SetActive(false);
GameObject.Find("WhiteholeStationSuperstructure_Body").SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.TimberHearth)
{
GameObject.Find("MiningRig_Body").SetActive(false);
}
// Deal with proxies
foreach (var p in GameObject.FindObjectsOfType<ProxyOrbiter>())
{
if (p.GetValue<AstroObject>("_originalBody") == ao.gameObject)
{
p.gameObject.SetActive(false);
break;
}
}
Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => RemoveProxy(ao.name.Replace("_Body", "")));
ao.transform.root.gameObject.SetActive(false);
}
private static void RemoveProxy(string name)
{
if (name.Equals("TowerTwin")) name = "AshTwin";
if (name.Equals("CaveTwin")) name = "EmberTwin";
var distantProxy = GameObject.Find(name + "_DistantProxy");
var distantProxyClone = GameObject.Find(name + "_DistantProxy(Clone)");
if (distantProxy != null) GameObject.Destroy(distantProxy.gameObject);
if (distantProxyClone != null) GameObject.Destroy(distantProxyClone.gameObject);
}
}
}

View File

@ -7,7 +7,7 @@ namespace NewHorizons.General
{
static class RFVolumeBuilder
{
public static void Make(GameObject body, OWRigidbody rigidbody, float atmoEndSize)
public static void Make(GameObject body, OWRigidbody rigidbody, float sphereOfInfluence)
{
GameObject rfGO = new GameObject("RFVolume");
rfGO.transform.parent = body.transform;
@ -16,30 +16,29 @@ namespace NewHorizons.General
SphereCollider SC = rfGO.AddComponent<SphereCollider>();
SC.isTrigger = true;
SC.radius = atmoEndSize * 2;
SC.radius = sphereOfInfluence * 2;
ReferenceFrameVolume RFV = rfGO.AddComponent<ReferenceFrameVolume>();
ReferenceFrame RV = new ReferenceFrame(rigidbody);
RV.SetValue("_minSuitTargetDistance", 300);
RV.SetValue("_minSuitTargetDistance", sphereOfInfluence);
RV.SetValue("_maxTargetDistance", 0);
RV.SetValue("_autopilotArrivalDistance", atmoEndSize * 2f);
RV.SetValue("_autoAlignmentDistance", atmoEndSize * 1.5f);
//Utility.AddDebugShape.AddSphere(rfGO, 1000, new Color32(0, 255, 0, 128));
RV.SetValue("_autopilotArrivalDistance", sphereOfInfluence * 2f);
RV.SetValue("_autoAlignmentDistance", sphereOfInfluence * 1.5f);
RV.SetValue("_hideLandingModePrompt", false);
RV.SetValue("_matchAngularVelocity", true);
RV.SetValue("_minMatchAngularVelocityDistance", 70);
RV.SetValue("_maxMatchAngularVelocityDistance", 400);
RV.SetValue("_bracketsRadius", 300);
RV.SetValue("_bracketsRadius", sphereOfInfluence);
RFV.SetValue("_referenceFrame", RV);
RFV.SetValue("_minColliderRadius", 300);
RFV.SetValue("_maxColliderRadius", atmoEndSize * 2f);
RFV.SetValue("_minColliderRadius", sphereOfInfluence);
RFV.SetValue("_maxColliderRadius", sphereOfInfluence * 2f);
RFV.SetValue("_isPrimaryVolume", true);
RFV.SetValue("_isCloseRangeVolume", false);
rfGO.SetActive(true);
Logger.Log("Finished building rfvolume", Logger.LogType.Log);
}
}
}

View File

@ -31,7 +31,6 @@ namespace NewHorizons.Body
sectorGO.SetActive(true);
Logger.Log("Finished building sector", Logger.LogType.Log);
return S;
}
}

View File

@ -18,9 +18,12 @@ namespace NewHorizons
{
public class Main : ModBehaviour
{
public static AssetBundle ShaderBundle;
public static Main Instance { get; private set; }
public static List<NewHorizonsBody> BodyList = new List<NewHorizonsBody>();
public static List<NewHorizonsBody> AdditionalBodies = new List<NewHorizonsBody>();
public IModAssets CurrentAssets { get; private set; }
@ -33,6 +36,7 @@ namespace NewHorizons
{
SceneManager.sceneLoaded += OnSceneLoaded;
Instance = this;
ShaderBundle = Main.Instance.ModHelper.Assets.LoadBundle("AssetBundle/shader");
Utility.Patches.Apply();
@ -51,10 +55,7 @@ namespace NewHorizons
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
if (scene.name != "SolarSystem")
{
return;
}
if (scene.name != "SolarSystem") return;
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => Locator.GetPlayerBody().gameObject.AddComponent<DebugRaycaster>());
@ -64,60 +65,73 @@ namespace NewHorizons
AstroObjectLocator.AddAstroObject(ao);
}
foreach (var body in BodyList)
{
var stringID = body.Config.Name.ToUpper().Replace(" ", "_").Replace("'", "");
if (stringID.Equals("ATTLEROCK")) stringID = "TIMBER_MOON";
if (stringID.Equals("HOLLOWS_LANTERN")) stringID = "VOLCANIC_MOON";
if (stringID.Equals("ASH_TWIN")) stringID = "TOWER_TWIN";
if (stringID.Equals("EMBER_TWIN")) stringID = "CAVE_TWIN";
if (stringID.Equals("INTERLOPER")) stringID = "COMET";
// Should make moons come after planets
BodyList = BodyList.OrderBy(b => (b.Config?.Orbit?.IsMoon)).ToList();
Logger.Log($"Checking if [{stringID}] already exists");
AstroObject existingPlanet = null;
while(BodyList.Count != 0)
{
foreach (var body in BodyList)
{
LoadBody(body);
}
BodyList = AdditionalBodies;
AdditionalBodies = new List<NewHorizonsBody>();
}
}
private void LoadBody(NewHorizonsBody body)
{
var stringID = body.Config.Name.ToUpper().Replace(" ", "_").Replace("'", "");
if (stringID.Equals("ATTLEROCK")) stringID = "TIMBER_MOON";
if (stringID.Equals("HOLLOWS_LANTERN")) stringID = "VOLCANIC_MOON";
if (stringID.Equals("ASH_TWIN")) stringID = "TOWER_TWIN";
if (stringID.Equals("EMBER_TWIN")) stringID = "CAVE_TWIN";
if (stringID.Equals("INTERLOPER")) stringID = "COMET";
AstroObject existingPlanet = null;
try
{
existingPlanet = AstroObjectLocator.GetAstroObject(stringID);
if (existingPlanet == null)
existingPlanet = existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.Name.Replace(" ", ""));
}
catch (Exception e)
{
Logger.LogWarning($"Error when looking for {body.Config.Name}: {e.Message}, {e.StackTrace}");
}
if (existingPlanet != null)
{
try
{
existingPlanet = AstroObjectLocator.GetAstroObject(stringID);
if (existingPlanet == null)
existingPlanet = existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.Name.Replace(" ", ""));
if (body.Config.Destroy)
{
Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveBody(existingPlanet), 2);
}
else UpdateBody(body, existingPlanet);
}
catch(Exception e)
catch (Exception e)
{
Logger.LogWarning($"Error when looking for {body.Config.Name}: {e.Message}, {e.StackTrace}");
Logger.LogError($"Couldn't update body {body.Config?.Name}: {e.Message}, {e.StackTrace}");
}
if (existingPlanet != null)
}
else
{
try
{
try
{
if (body.Config.Destroy)
{
Instance.ModHelper.Events.Unity.FireInNUpdates(() => RemoveBody(existingPlanet), 2);
}
else UpdateBody(body, existingPlanet);
}
catch(Exception e)
{
Logger.LogError($"Couldn't update body {body.Config?.Name}: {e.Message}, {e.StackTrace}");
}
GameObject planetObject;
planetObject = GenerateBody(body);
planetObject.SetActive(true);
}
else
catch (Exception e)
{
try
{
GameObject planetObject;
planetObject = GenerateBody(body);
planetObject.SetActive(true);
}
catch(Exception e)
{
Logger.LogError($"Couldn't generate body {body.Config?.Name}: {e.Message}, {e.StackTrace}");
}
Logger.LogError($"Couldn't generate body {body.Config?.Name}: {e.Message}, {e.StackTrace}");
}
}
}
public void LoadConfigs(IModBehaviour mod)
{
CurrentAssets = mod.ModHelper.Assets;
@ -146,144 +160,8 @@ namespace NewHorizons
var sector = go.GetComponentInChildren<Sector>();
var rb = go.GetAttachedOWRigidbody();
if (body.Config.Ring != null)
{
RingBuilder.Make(go, body.Config.Ring);
}
if (body.Config.Base.LavaSize != 0)
{
LavaBuilder.Make(go, sector, rb, body.Config.Base.LavaSize);
}
if (body.Config.Base.WaterSize != 0)
{
WaterBuilder.Make(go, sector, rb, body.Config.Base.WaterSize);
}
if(body.Config.Atmosphere != null)
{
AirBuilder.Make(go, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasOxygen);
if (body.Config.Atmosphere.Cloud != null)
{
CloudsBuilder.Make(go, sector, body.Config.Atmosphere);
SunOverrideBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere);
}
if (body.Config.Atmosphere.HasRain || body.Config.Atmosphere.HasSnow)
EffectsBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere.Size / 2f, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasSnow);
if (body.Config.Atmosphere.FogSize != 0)
FogBuilder.Make(go, sector, body.Config.Atmosphere);
AtmosphereBuilder.Make(go, body.Config.Atmosphere);
}
return go;
}
private static void RemoveBody(AstroObject ao, List<AstroObject> toDestroy = null)
{
Logger.Log($"Removing {ao.name}");
if (ao.gameObject == null || !ao.gameObject.activeInHierarchy) return;
if (toDestroy == null) toDestroy = new List<AstroObject>();
if(toDestroy.Contains(ao))
{
Logger.LogError($"Possible infinite recursion in RemoveBody: {ao.name} might be it's own primary body?");
return;
}
toDestroy.Add(ao);
if (ao.GetAstroObjectName() == AstroObject.Name.BrittleHollow)
RemoveBody(AstroObjectLocator.GetAstroObject(AstroObject.Name.WhiteHole), toDestroy);
// Check if any other objects depend on it and remove them too
var aoArray = AstroObjectLocator.GetAllAstroObjects();
foreach(AstroObject obj in aoArray)
{
if (obj?.gameObject == null || !obj.gameObject.activeInHierarchy)
{
AstroObjectLocator.RemoveAstroObject(obj);
continue;
}
if (ao.Equals(obj.GetPrimaryBody()))
{
AstroObjectLocator.RemoveAstroObject(obj);
RemoveBody(obj, toDestroy);
}
}
if (ao.GetAstroObjectName() == AstroObject.Name.CaveTwin || ao.GetAstroObjectName() == AstroObject.Name.TowerTwin)
{
var focalBody = GameObject.Find("FocalBody");
if(focalBody != null) focalBody.SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.MapSatellite)
{
var msb = GameObject.Find("MapSatellite_Body");
if (msb != null) msb.SetActive(false);
}
if (ao.GetAstroObjectName() == AstroObject.Name.TowerTwin)
GameObject.Find("TimeLoopRing_Body").SetActive(false);
if (ao.GetAstroObjectName() == AstroObject.Name.ProbeCannon)
{
GameObject.Find("NomaiProbe_Body").SetActive(false);
GameObject.Find("CannonMuzzle_Body").SetActive(false);
GameObject.Find("FakeCannonMuzzle_Body (1)").SetActive(false);
GameObject.Find("CannonBarrel_Body").SetActive(false);
GameObject.Find("FakeCannonBarrel_Body (1)").SetActive(false);
GameObject.Find("Debris_Body (1)").SetActive(false);
}
if(ao.GetAstroObjectName() == AstroObject.Name.SunStation)
{
GameObject.Find("SS_Debris_Body").SetActive(false);
}
if(ao.GetAstroObjectName() == AstroObject.Name.GiantsDeep)
{
GameObject.Find("BrambleIsland_Body").SetActive(false);
GameObject.Find("GabbroIsland_Body").SetActive(false);
GameObject.Find("QuantumIsland_Body").SetActive(false);
GameObject.Find("StatueIsland_Body").SetActive(false);
GameObject.Find("ConstructionYardIsland_Body").SetActive(false);
}
if(ao.GetAstroObjectName() == AstroObject.Name.WhiteHole)
{
GameObject.Find("WhiteholeStation_Body").SetActive(false);
GameObject.Find("WhiteholeStationSuperstructure_Body").SetActive(false);
}
if(ao.GetAstroObjectName() == AstroObject.Name.TimberHearth)
{
GameObject.Find("MiningRig_Body").SetActive(false);
}
// Deal with proxies
foreach(var p in GameObject.FindObjectsOfType<ProxyOrbiter>())
{
if(p.GetValue<AstroObject>("_originalBody") == ao.gameObject)
{
p.gameObject.SetActive(false);
break;
}
}
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => RemoveProxy(ao.name.Replace("_Body", "")));
ao.transform.root.gameObject.SetActive(false);
}
private static void RemoveProxy(string name)
{
if (name.Equals("TowerTwin")) name = "AshTwin";
if (name.Equals("CaveTwin")) name = "EmberTwin";
var distantProxy = GameObject.Find(name + "_DistantProxy");
var distantProxyClone = GameObject.Find(name + "_DistantProxy(Clone)");
if (distantProxy != null) Destroy(distantProxy.gameObject);
else Logger.LogWarning($"Couldn't find distant proxy {name + "_DistantProxy"}");
if (distantProxyClone != null) Destroy(distantProxyClone.gameObject);
else Logger.LogWarning($"Couldn't find distant proxy {name + "_DistantProxy(Clone)"}");
// Do stuff that's shared between generating new planets and updating old ones
return SharedGenerateBody(body, go, sector, rb);
}
public static GameObject GenerateBody(NewHorizonsBody body)
@ -295,23 +173,22 @@ namespace NewHorizons
if(body.Config.Base.GroundSize != 0) GeometryBuilder.Make(go, body.Config.Base.GroundSize);
AstroObject primaryBody = AstroObjectLocator.GetAstroObject(AstroObject.Name.Sun);
try
{
primaryBody = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody);
}
catch(Exception)
AstroObject primaryBody = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody);
if(primaryBody == null)
{
Logger.LogError($"Could not find AstroObject {body.Config.Orbit.PrimaryBody}, defaulting to SUN");
}
primaryBody = AstroObjectLocator.GetAstroObject(AstroObject.Name.Sun);
}
var atmoSize = body.Config.Atmosphere != null ? body.Config.Atmosphere.Size : 0f;
float sphereOfInfluence = Mathf.Max(atmoSize, body.Config.Base.SurfaceSize * 2f);
// Get initial position but set it at the end
var a = body.Config.Orbit.SemiMajorAxis;
var omega = Mathf.Deg2Rad * body.Config.Orbit.LongitudeOfAscendingNode;
var positionVector = primaryBody.gameObject.transform.position + new Vector3(a * Mathf.Sin(omega), 0, a * Mathf.Cos(omega));
//var a = body.Config.Orbit.SemiMajorAxis;
//var omega = Mathf.Deg2Rad * body.Config.Orbit.LongitudeOfAscendingNode;
//var positionVector = primaryBody.gameObject.transform.position + new Vector3(a * Mathf.Sin(omega), 0, a * Mathf.Cos(omega));
var positionVector = Kepler.OrbitalHelper.CartesianFromOrbitalElements(body.Config.Orbit.Eccentricity, body.Config.Orbit.SemiMajorAxis, body.Config.Orbit.Inclination,
body.Config.Orbit.LongitudeOfAscendingNode, body.Config.Orbit.ArgumentOfPeriapsis, body.Config.Orbit.TrueAnomaly);
var outputTuple = BaseBuilder.Make(go, primaryBody, positionVector, body.Config);
var ao = (AstroObject)outputTuple.Items[0];
@ -333,7 +210,53 @@ namespace NewHorizons
if (body.Config.HeightMap != null)
HeightMapBuilder.Make(go, body.Config.HeightMap);
// These can be shared between creating new planets and updating planets
if (body.Config.ProcGen != null)
ProcGenBuilder.Make(go, body.Config.ProcGen);
InitialMotionBuilder.Make(go, primaryBody, rb, positionVector, body.Config.Orbit);
// Do stuff that's shared between generating new planets and updating old ones
go = SharedGenerateBody(body, go, sector, rb);
body.Object = go;
// Some things have to be done the second tick
if(body.Config.Orbit != null && !body.Config.Base.HideOrbitLine)
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.IsMoon, body.Config.Orbit));
// Now that we're done move the planet into place
go.transform.parent = Locator.GetRootTransform();
go.transform.position = positionVector + primaryBody.transform.position;
// Spawning on other planets is a bit hacky so we do it last
if (body.Config.Spawn != null)
{
SpawnPointBuilder.Make(go, body.Config.Spawn, rb);
}
if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) AstroObjectLocator.RegisterCustomAstroObject(ao);
Logger.Log("Generation of [" + body.Config.Name + "] completed.", Logger.LogType.Log);
return go;
}
private static GameObject SharedGenerateBody(NewHorizonsBody body, GameObject go, Sector sector, OWRigidbody rb)
{
if (body.Config.Ring != null)
RingBuilder.Make(go, body.Config.Ring);
if (body.Config.AsteroidBelt != null)
AsteroidBeltBuilder.Make(body.Config.Name, body.Config.AsteroidBelt);
if(body.Config.Base != null)
{
if (body.Config.Base.LavaSize != 0)
LavaBuilder.Make(go, sector, rb, body.Config.Base.LavaSize);
if (body.Config.Base.WaterSize != 0)
WaterBuilder.Make(go, sector, rb, body.Config.Base.WaterSize);
}
if (body.Config.Atmosphere != null)
{
AirBuilder.Make(go, body.Config.Atmosphere.Size, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasOxygen);
@ -344,7 +267,7 @@ namespace NewHorizons
SunOverrideBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere);
}
if(body.Config.Atmosphere.HasRain || body.Config.Atmosphere.HasSnow)
if (body.Config.Atmosphere.HasRain || body.Config.Atmosphere.HasSnow)
EffectsBuilder.Make(go, sector, body.Config.Base.SurfaceSize, body.Config.Atmosphere.Size / 2f, body.Config.Atmosphere.HasRain, body.Config.Atmosphere.HasSnow);
if (body.Config.Atmosphere.FogSize != 0)
@ -353,38 +276,6 @@ namespace NewHorizons
AtmosphereBuilder.Make(go, body.Config.Atmosphere);
}
if (body.Config.Ring != null)
RingBuilder.Make(go, body.Config.Ring);
if (body.Config.Base.BlackHoleSize != 0)
BlackHoleBuilder.Make(go);
if (body.Config.Base.LavaSize != 0)
LavaBuilder.Make(go, sector, rb, body.Config.Base.LavaSize);
if (body.Config.Base.WaterSize != 0)
WaterBuilder.Make(go, sector, rb, body.Config.Base.WaterSize);
if (body.Config.Base.HasAmbientLight)
AmbientLightBuilder.Make(go, sphereOfInfluence);
Logger.Log("Generation of [" + body.Config.Name + "] completed.", Logger.LogType.Log);
body.Object = go;
// Some things have to be done the second tick
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OrbitlineBuilder.Make(body.Object, ao, body.Config.Orbit.IsMoon));
go.transform.parent = Locator.GetRootTransform();
go.transform.localPosition = positionVector;
if (body.Config.Spawn != null)
{
SpawnPointBuilder.Make(go, body.Config.Spawn, rb);
}
if (ao.GetAstroObjectName() == AstroObject.Name.CustomString) AstroObjectLocator.RegisterCustomAstroObject(ao);
return go;
}
}

View File

@ -230,14 +230,20 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Atmosphere\FogBuilder.cs" />
<Compile Include="Body\AsteroidBeltBuilder.cs" />
<Compile Include="Body\Geometry\CubeSphere.cs" />
<Compile Include="Body\Geometry\Icosphere.cs" />
<Compile Include="Body\Geometry\Perlin.cs" />
<Compile Include="Body\HeightMapBuilder.cs" />
<Compile Include="Body\ProcGenBuilder.cs" />
<Compile Include="Body\SunBuilder.cs" />
<Compile Include="External\AsteroidBeltModule.cs" />
<Compile Include="External\AtmosphereModule.cs" />
<Compile Include="External\BaseModule.cs" />
<Compile Include="External\HeightMapModule.cs" />
<Compile Include="External\Module.cs" />
<Compile Include="External\OrbitModule.cs" />
<Compile Include="External\ProcGenModule.cs" />
<Compile Include="External\RingModule.cs" />
<Compile Include="External\SpawnModule.cs" />
<Compile Include="General\BaseBuilder.cs" />
@ -245,12 +251,15 @@
<Compile Include="General\DetectorBuilder.cs" />
<Compile Include="General\GravityBuilder.cs" />
<Compile Include="Body\LavaBuilder.cs" />
<Compile Include="General\InitialMotionBuilder.cs" />
<Compile Include="General\MarkerBuilder.cs" />
<Compile Include="General\OrbitlineBuilder.cs" />
<Compile Include="General\PlanetDestroyer.cs" />
<Compile Include="General\RFVolumeBuilder.cs" />
<Compile Include="Body\RingBuilder.cs" />
<Compile Include="General\SectorBuilder.cs" />
<Compile Include="General\SpawnPointBuilder.cs" />
<Compile Include="Physics\OrbitalHelper.cs" />
<Compile Include="Utility\AddDebugShape.cs" />
<Compile Include="General\AmbientLightBuilder.cs" />
<Compile Include="External\IPlanetConfig.cs" />
@ -269,6 +278,7 @@
<Compile Include="Utility\AstroObjectLocator.cs" />
<Compile Include="Utility\DebugRaycaster.cs" />
<Compile Include="Utility\ImageUtilities.cs" />
<Compile Include="Physics\ParameterizedOrbitLine.cs" />
<Compile Include="Utility\Logger.cs" />
<Compile Include="Utility\MakeMeshDoubleFaced.cs" />
<Compile Include="Utility\NewHorizonBody.cs" />
@ -290,14 +300,14 @@
md "$(OwmlDir)\Mods\$(ModUniqueName)"
md "$(OwmlDir)\Mods\$(ModUniqueName)\planets"
md "$(OwmlDir)\Mods\$(ModUniqueName)\planets\assets"
md "$(OwmlDir)\Mods\$(ModUniqueName)\assets"
md "$(OwmlDir)\Mods\$(ModUniqueName)\AssetBundle"
copy /y "$(TargetPath)" "$(OwmlDir)\Mods\$(ModUniqueName)"
copy /y "$(ProjectDir)\default-config.json" "$(OwmlDir)\Mods\$(ModUniqueName)"
copy /y "$(ProjectDir)\manifest.json" "$(OwmlDir)\Mods\$(ModUniqueName)"
copy /y "$(ProjectDir)planets\" "$(OwmlDir)\Mods\$(ModUniqueName)\planets"
copy /y "$(ProjectDir)planets\assets" "$(OwmlDir)\Mods\$(ModUniqueName)\planets\assets"
copy /y "$(ProjectDir)assets\" "$(OwmlDir)\Mods\$(ModUniqueName)\assets"
copy /y "$(ProjectDir)AssetBundle\" "$(OwmlDir)\Mods\$(ModUniqueName)\AssetBundle"
</PostBuildEvent>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Kepler
{
public static class OrbitalHelper
{
public static Vector3 CartesianFromOrbitalElements(float e, float a, float inclination, float ascending, float periapsis, float angle)
{
float b = a * Mathf.Sqrt(1f - (e * e));
// Get point on ellipse
// Angle starts at apoapsis, shift by 90 degrees to get to periapsis and add true anomaly
float ellipseAngle = Mathf.Repeat(Mathf.PI / 4f + Mathf.Deg2Rad * angle, 2 * Mathf.PI);
float tAngle = Mathf.Tan(ellipseAngle);
float x = (a * b) / Mathf.Sqrt(b * b + a * a * tAngle * tAngle);
if (ellipseAngle > Mathf.PI / 2f && ellipseAngle < 3f * Mathf.PI / 2f) x *= -1;
float y = x * tAngle;
// Fix limits
if (float.IsNaN(x)) {
x = 0;
if (angle < 180) y = b;
else y = -b;
}
var position = new Vector3(x, 0, y);
return RotateToOrbitalPlane(position, ascending, periapsis, inclination);
}
public static float VisViva(float standardGravitationalParameter, Vector3 relativePosition, float semiMajorAxis)
{
return Mathf.Sqrt(standardGravitationalParameter * (2f / relativePosition.magnitude - 1f / semiMajorAxis));
}
public static Vector3 EllipseTangent(float e, float a, float inclination, float ascending, float periapsis, float angle)
{
float b = a * Mathf.Sqrt(1f - (e * e));
float ellipseAngle = Mathf.Repeat(Mathf.PI / 4f + Mathf.Deg2Rad * angle, 2 * Mathf.PI);
var tan = Mathf.Tan(ellipseAngle);
float x = (a * b) / Mathf.Sqrt(b * b + a * a * tan * tan);
var sec2 = 1f / (tan * tan);
float dxdt = -a * a * a * b * sec2 * tan / Mathf.Pow(a * a * tan * tan + b * b, 3f / 2f);
if (ellipseAngle > Mathf.PI / 2f && ellipseAngle < 3f * Mathf.PI / 2f)
{
dxdt *= -1;
x *= -1;
}
// Product rule
var dydt = sec2 * x + dxdt * tan;
// Fix limits
if(float.IsNaN(dxdt))
{
dydt = 0;
if (angle == Mathf.PI / 2f) dxdt = -1;
else dxdt = 1;
}
var vector = new Vector3(dxdt, 0, dydt).normalized;
return RotateToOrbitalPlane(vector, ascending, periapsis, inclination);
}
private static Vector3 RotateToOrbitalPlane(Vector3 vector, float ascending, float periapsis, float inclination)
{
// Periapsis is at 90 degrees
vector = Quaternion.AngleAxis(Mathf.Deg2Rad * (ascending + periapsis) + Mathf.PI / 2f, Vector3.up) * vector;
var inclinationAxis = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * ascending, 2f * Mathf.PI), Vector3.up) * new Vector3(1, 0, 0);
vector = Quaternion.AngleAxis(Mathf.Repeat(Mathf.Deg2Rad * inclination, 2f * Mathf.PI), inclinationAxis) * vector;
return vector;
}
public static Vector3 CalculateOrbitVelocity(OWRigidbody primaryBody, Vector3 relativePosition, float inclination = 0f)
{
GravityVolume attachedGravityVolume = primaryBody.GetAttachedGravityVolume();
if (attachedGravityVolume == null)
{
return Vector3.zero;
}
Vector3 vector2 = Vector3.Cross(relativePosition, Vector3.up).normalized;
vector2 = Quaternion.AngleAxis(inclination, relativePosition) * vector2;
float d = Mathf.Sqrt(attachedGravityVolume.CalculateForceAccelerationAtPoint(relativePosition + primaryBody.transform.position).magnitude * relativePosition.magnitude);
return vector2 * d;
}
}
}

View File

@ -0,0 +1,125 @@
using NewHorizons.Kepler;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Utility
{
public class ParameterizedOrbitLine : OrbitLine
{
protected override void InitializeLineRenderer()
{
base.GetComponent<LineRenderer>().positionCount = this._numVerts;
}
protected override void OnValidate()
{
if (this._numVerts < 0 || this._numVerts > 4096)
{
this._numVerts = Mathf.Clamp(this._numVerts, 0, 4096);
}
if (base.GetComponent<LineRenderer>().positionCount != this._numVerts)
{
this.InitializeLineRenderer();
}
}
protected override void Start()
{
base.Start();
this._verts = new Vector3[this._numVerts];
base.enabled = false;
}
public void SetOrbitalParameters(float eccentricity, float semiMajorAxis, float inclination, float longitudeOfAscendingNode, float argumentOfPeriapsis, float trueAnomaly)
{
_eccentricity = eccentricity;
_semiMajorAxis = semiMajorAxis;
_inclination = inclination;
_longitudeOfAscendingNode = longitudeOfAscendingNode;
_argumentOfPeriapsis = argumentOfPeriapsis;
_trueAnomaly = trueAnomaly;
_initialMotion = (this._astroObject != null) ? this._astroObject.GetComponent<InitialMotion>() : null;
_primary = (this._astroObject != null) ? this._astroObject.GetPrimaryBody() : null;
if (_initialMotion && _primary)
{
var periapsisAngle = longitudeOfAscendingNode + argumentOfPeriapsis;
var apoapsisAngle = periapsisAngle + 90f;
_vSemiMinorAxis = OrbitalHelper.CartesianFromOrbitalElements(_eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, periapsisAngle);
_vSemiMajorAxis = OrbitalHelper.CartesianFromOrbitalElements(_eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, apoapsisAngle);
Vector3 rhs = this._astroObject.transform.position - _primary.transform.position;
Vector3 initVelocity = _initialMotion.GetInitVelocity();
Vector3 vector = Vector3.Cross(initVelocity, rhs);
this._upAxisDir = vector.normalized;
var semiMinorAxis = semiMajorAxis * Mathf.Sqrt(1 - (eccentricity * eccentricity));
_fociDistance = Mathf.Sqrt((semiMajorAxis * semiMajorAxis) - (semiMinorAxis * semiMinorAxis));
base.enabled = true;
}
else
{
Logger.LogError($"Couldn't set values for KeplerOrbitLine. InitialMotion = {_initialMotion}, AstroObject = {_primary}");
}
}
protected override void Update()
{
Vector3 vector = _primary.transform.position + _vSemiMajorAxis * _fociDistance;
float num = CalcProjectedAngleToCenter(vector, _vSemiMajorAxis, _vSemiMinorAxis, _astroObject.transform.position);
for (int i = 0; i < _numVerts; i++)
{
var angle = ((float)i / (float)(_numVerts - 1)) * 360f - Mathf.Rad2Deg * num;
_verts[i] = OrbitalHelper.CartesianFromOrbitalElements(_eccentricity, _semiMajorAxis, _inclination, _longitudeOfAscendingNode, _argumentOfPeriapsis, angle);
}
_lineRenderer.SetPositions(_verts);
// From EllipticalOrbitLine
base.transform.position = vector;
base.transform.rotation = Quaternion.LookRotation(Quaternion.AngleAxis(-48f, Vector3.up) * _vSemiMajorAxis, -_upAxisDir);
float num2 = DistanceToEllipticalOrbitLine(vector, _vSemiMajorAxis, _vSemiMinorAxis, _upAxisDir, Locator.GetActiveCamera().transform.position);
float widthMultiplier = Mathf.Min(num2 * (_lineWidth / 1000f), _maxLineWidth);
float num3 = _fade ? (1f - Mathf.Clamp01((num2 - _fadeStartDist) / (_fadeEndDist - _fadeStartDist))) : 1f;
_lineRenderer.widthMultiplier = widthMultiplier;
_lineRenderer.startColor = new Color(_color.r, _color.g, _color.b, num3 * num3);
}
private float CalcProjectedAngleToCenter(Vector3 foci, Vector3 semiMajorAxis, Vector3 semiMinorAxis, Vector3 point)
{
Vector3 lhs = point - foci;
Vector3 vector = new Vector3(Vector3.Dot(lhs, semiMajorAxis.normalized), 0f, Vector3.Dot(lhs, semiMinorAxis.normalized));
vector.x *= semiMinorAxis.magnitude / semiMajorAxis.magnitude;
return Mathf.Atan2(vector.z, vector.x);
}
private float DistanceToEllipticalOrbitLine(Vector3 foci, Vector3 semiMajorAxis, Vector3 semiMinorAxis, Vector3 upAxis, Vector3 point)
{
float f = this.CalcProjectedAngleToCenter(foci, semiMajorAxis, semiMinorAxis, point);
Vector3 b = foci + this._vSemiMajorAxis * Mathf.Cos(f) + this._vSemiMinorAxis * Mathf.Sin(f);
return Vector3.Distance(point, b);
}
private Vector3 _vSemiMajorAxis;
private Vector3 _vSemiMinorAxis;
private Vector3 _upAxisDir;
private float _fociDistance;
private float _eccentricity;
private float _semiMajorAxis;
private float _inclination;
private float _longitudeOfAscendingNode;
private float _argumentOfPeriapsis;
private float _trueAnomaly;
private Vector3[] _verts;
private InitialMotion _initialMotion;
private AstroObject _primary;
}
}

View File

@ -15,16 +15,10 @@ namespace NewHorizons.Utility
try
{
KeyValuePair<int, string> pair = instance.theUITable.First(x => x.Value.Equals(text));
if (pair.Equals(default(KeyValuePair<int, string>)))
{
Logger.Log($"UI table already contains [{text}] with key [{pair.Key}]");
return pair.Key;
}
if (pair.Equals(default(KeyValuePair<int, string>))) return pair.Key;
}
catch (Exception) { }
instance.Insert_UI(instance.theUITable.Keys.Max() + 1, text);
Logger.Log($"Added [{text}] to UI table with key [{instance.theUITable.Keys.Max()}]");
return instance.theUITable.Keys.Max();
}
}

View File

@ -22,6 +22,7 @@ namespace NewHorizons.Utility
if (name.Equals("MAP_SATELLITE"))
return GetAstroObject(AstroObject.Name.MapSatellite);
var aoName = AstroObject.StringIDToAstroObjectName(name);
if(aoName == AstroObject.Name.None) aoName = AstroObject.StringIDToAstroObjectName(name.ToUpper().Replace(" ", "_"));
if (aoName != AstroObject.Name.None && aoName != AstroObject.Name.CustomString)
return GetAstroObject(aoName);
if (_customAstroObjectDictionary.ContainsKey(name))
@ -75,23 +76,21 @@ namespace NewHorizons.Utility
}
var name = ao.GetCustomName();
if (_customAstroObjectDictionary.Keys.Contains(name))
Logger.Log($"Custom astro object dictionary already contains {name}. Replacing it.", Logger.LogType.Warning);
_customAstroObjectDictionary.Add(name, ao);
if (_customAstroObjectDictionary.Keys.Contains(name))
_customAstroObjectDictionary[name] = ao;
else
_customAstroObjectDictionary.Add(name, ao);
}
public static void DeregisterCustomAstroObject(AstroObject ao)
{
if (ao.GetAstroObjectName() != AstroObject.Name.CustomString)
{
Logger.Log($"Can't deregister {ao.name} as it's AstroObject.Name isn't CustomString.");
return;
}
if (ao.GetAstroObjectName() != AstroObject.Name.CustomString) return;
_customAstroObjectDictionary.Remove(ao.GetCustomName());
}
public static void RefreshList()
{
_customAstroObjectDictionary = new Dictionary<string, AstroObject>();
_list = new List<AstroObject>();
}

Binary file not shown.