Merge branch 'master' into common-resources

This commit is contained in:
Nick J. Connors 2022-01-04 12:55:46 -05:00
commit e5ced93768
34 changed files with 875 additions and 134 deletions

Binary file not shown.

View File

@ -1,9 +1,9 @@
ManifestFileVersion: 0
CRC: 3840241390
CRC: 3597037522
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 1c2c90716d1ed7c9cbf5f785e41eace6
Hash: 33678ea445c06b269454371064cc3a5c
TypeTreeHash:
serializedVersion: 2
Hash: 6370d3f9de9eca57f523bce048404a46
@ -12,6 +12,7 @@ ClassTypes:
- Class: 48
Script: {instanceID: 0}
Assets:
- Assets/SphereTextureWrapper.shader
- Assets/UnlitTransparent.shader
- Assets/Shaders/SphereTextureWrapper.shader
- Assets/Shaders/Ring.shader
- Assets/Shaders/UnlitTransparent.shader
Dependencies: []

View File

@ -20,8 +20,6 @@ namespace NewHorizons.Atmosphere
if (atmo.CloudCap == null) cap = ImageUtilities.ClearTexture(128, 128);
else cap = assets.GetTexture(atmo.CloudCap);
//if(atmo.CloudRamp == null) ramp = ImageUtilities.Scaled(image, 1, 128);
if(atmo.CloudRamp == null) ramp = ImageUtilities.CanvasScaled(image, 1, image.height);
else ramp = assets.GetTexture(atmo.CloudRamp);
}
@ -31,6 +29,8 @@ namespace NewHorizons.Atmosphere
return;
}
Color cloudTint = atmo.CloudTint == null ? Color.white : (Color)atmo.CloudTint.ToColor32();
GameObject cloudsMainGO = new GameObject();
cloudsMainGO.SetActive(false);
cloudsMainGO.transform.parent = body.transform;
@ -56,8 +56,8 @@ namespace NewHorizons.Atmosphere
foreach (var material in topMR.sharedMaterials)
{
material.SetColor("_Color", atmo.CloudTint.ToColor32());
material.SetColor("_TintColor", atmo.CloudTint.ToColor32());
material.SetColor("_Color", cloudTint);
material.SetColor("_TintColor", cloudTint);
material.SetTexture("_MainTex", image);
material.SetTexture("_RampTex", ramp);
@ -84,7 +84,7 @@ namespace NewHorizons.Atmosphere
bottomTSR.LODRadius = 1f;
// It's always more green than expected
var bottomCloudTint = atmo.CloudTint.ToColor32();
var bottomCloudTint = cloudTint;
bottomCloudTint.g = (byte)(bottomCloudTint.g * 0.8f);
foreach (Material material in bottomTSR.sharedMaterials)
{

View File

@ -14,8 +14,10 @@ namespace NewHorizons.Builder.Body
{
static class AsteroidBeltBuilder
{
public static void Make(string bodyName, AsteroidBeltModule belt, IModAssets assets)
public static void Make(string bodyName, IPlanetConfig parentConfig, IModAssets assets, string uniqueName)
{
var belt = parentConfig.AsteroidBelt;
var minSize = 20;
var maxSize = 50;
int count = (int)(2f * Mathf.PI * belt.InnerRadius / (10f * maxSize));
@ -28,7 +30,8 @@ namespace NewHorizons.Builder.Body
var size = Random.Range(minSize, maxSize);
var config = new Dictionary<string, object>()
{
{"Name", $"{bodyName} Asteroid {i+1}"},
{"Name", $"{bodyName} Asteroid {i}"},
{"StarSystem", parentConfig.StarSystem },
{"Base", new Dictionary<string, object>()
{
{"HasMapMarker", false },
@ -57,7 +60,9 @@ namespace NewHorizons.Builder.Body
}
};
var asteroid = new NewHorizonsBody(new PlanetConfig(config), assets);
var asteroidConfig = new PlanetConfig(config);
if (belt.ProcGen != null) asteroidConfig.ProcGen = belt.ProcGen;
var asteroid = new NewHorizonsBody(new PlanetConfig(config), assets, uniqueName);
Main.NextPassBodies.Add(asteroid);
}
}

View File

@ -1,36 +0,0 @@
using NewHorizons.External;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Builder.Body
{
static class BlackHoleBuilder
{
public static void Make(GameObject body, BaseModule module, Sector sector)
{
var blackHole = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH"), body.transform);
blackHole.name = "BlackHole";
blackHole.transform.localPosition = Vector3.zero;
//blackHole.transform.localScale = Vector3.one; //* module.BlackHoleSize;
var blackHoleRenderer = blackHole.transform.Find("BlackHoleRenderer");
//blackHoleRenderer.transform.localScale = Vector3.one;
var singularityLOD = blackHoleRenderer.GetComponent<SingularityLOD>();
singularityLOD.SetSector(sector);
/*
var meshRenderer = blackHoleRenderer.GetComponent<MeshRenderer>();
meshRenderer.material.SetFloat("_Radius", module.BlackHoleSize * 0.4f);
var owRenderer = blackHoleRenderer.gameObject.AddComponent<OWRenderer>();
var propID_Radius = Shader.PropertyToID("_Radius");
owRenderer.SetMaterialProperty(propID_Radius, module.BlackHoleSize * 0.4f);
*/
}
}
}

View File

@ -97,8 +97,8 @@ namespace NewHorizons.Body
float latitude = (Mathf.Rad2Deg * Mathf.Acos(v.z / Mathf.Sqrt(v.x * v.x + v.y * v.y + v.z * v.z)));
float longitude = 180f;
if(v.x > 0) longitude = Mathf.Rad2Deg * Mathf.Atan(v.y / v.x) + 90f;
if(v.x < 0) longitude = Mathf.Rad2Deg * (Mathf.Atan(v.y / v.x) + Mathf.PI) + 90f;
if(v.x > 0) longitude = Mathf.Rad2Deg * Mathf.Atan(v.y / v.x);
if(v.x < 0) longitude = Mathf.Rad2Deg * (Mathf.Atan(v.y / v.x) + Mathf.PI);
float sampleX = heightMap.width * longitude / 360f;
float sampleY = heightMap.height * latitude / 180f;

View File

@ -33,6 +33,7 @@ namespace NewHorizons.Builder.Body
}
GameObject cubeSphere = new GameObject("CubeSphere");
cubeSphere.SetActive(false);
cubeSphere.transform.parent = go.transform;
cubeSphere.transform.rotation = Quaternion.Euler(90, 0, 0);
@ -41,7 +42,7 @@ namespace NewHorizons.Builder.Body
cubeSphere.AddComponent<MeshFilter>();
cubeSphere.GetComponent<MeshFilter>().mesh = mesh;
if(PlanetShader == null) PlanetShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/SphereTextureWrapper.shader");
if(PlanetShader == null) PlanetShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/Shaders/SphereTextureWrapper.shader");
var cubeSphereMR = cubeSphere.AddComponent<MeshRenderer>();
cubeSphereMR.material = new Material(PlanetShader);
@ -50,9 +51,13 @@ namespace NewHorizons.Builder.Body
var cubeSphereMC = cubeSphere.AddComponent<MeshCollider>();
cubeSphereMC.sharedMesh = mesh;
if(go.GetComponent<ProxyShadowCasterSuperGroup>() != null) cubeSphere.AddComponent<ProxyShadowCaster>();
// Fix rotation in the end
cubeSphere.transform.localRotation = Quaternion.Euler(90, 0, 0);
cubeSphere.transform.localPosition = Vector3.zero;
cubeSphere.SetActive(true);
}
}
}

View File

@ -30,6 +30,8 @@ namespace NewHorizons.Builder.Body
var cubeSphereMC = icosphere.AddComponent<MeshCollider>();
cubeSphereMC.sharedMesh = mesh;
icosphere.transform.localRotation = Quaternion.Euler(90, 0, 0);
icosphere.AddComponent<ProxyShadowCaster>();
}
}
}

View File

@ -13,6 +13,7 @@ namespace NewHorizons.Builder.Body
static class RingBuilder
{
public static Shader RingShader;
public static Shader UnlitShader;
public static void Make(GameObject body, RingModule ring, IModAssets assets)
{
@ -39,15 +40,16 @@ namespace NewHorizons.Builder.Body
var ringMR = ringGO.AddComponent<MeshRenderer>();
var texture = ringTexture;
if (RingShader == null) RingShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/UnlitTransparent.shader");
if (RingShader == null) RingShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/Shaders/Ring.shader");
if (UnlitShader == null) UnlitShader = Main.ShaderBundle.LoadAsset<Shader>("Assets/Shaders/UnlitTransparent.shader");
var mat = new Material(RingShader);
var mat = new Material(ring.Unlit ? UnlitShader : RingShader);
mat.mainTexture = texture;
mat.renderQueue = 3000;
mat.renderQueue = 2895;
ringMR.material = mat;
// Make mesh
var segments = (int)Math.Max(20, ring.OuterRadius);
var segments = (int)Mathf.Clamp(ring.OuterRadius, 20, 2000);
BuildRingMesh(ringMesh, segments, ring.InnerRadius, ring.OuterRadius);
}

View File

@ -0,0 +1,234 @@
using NewHorizons.Components;
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;
namespace NewHorizons.Builder.Body
{
static class SingularityBuilder
{
enum Polarity
{
BlackHole,
WhiteHole
}
private static Shader blackHoleShader = null;
private static Shader whiteHoleShader = null;
public static void Make(GameObject body, Sector sector, OWRigidbody OWRB, IPlanetConfig config)
{
var size = config.Base.BlackHoleSize;
string pairedSingularity = null;
var polarity = Polarity.BlackHole;
if (config.Singularity != null)
{
size = config.Singularity.Size;
pairedSingularity = config.Singularity.PairedSingularity;
if(config.Singularity.Type != null && config.Singularity.Type.ToUpper().Equals("WHITEHOLE"))
{
polarity = Polarity.WhiteHole;
}
}
bool isWormHole = config.Singularity.TargetStarSystem != null;
bool hasHazardVolume = !isWormHole && (pairedSingularity == null);
Vector3 localPosition = config.Singularity.Position == null ? Vector3.zero : (Vector3)config.Singularity.Position;
GameObject newSingularity = null;
switch (polarity)
{
case Polarity.BlackHole:
newSingularity = MakeBlackHole(body, sector, localPosition, size, hasHazardVolume, config.Singularity.TargetStarSystem);
break;
case Polarity.WhiteHole:
newSingularity = MakeWhiteHole(body, sector, OWRB, localPosition, size);
break;
}
// Try to pair them
if(pairedSingularity != null && newSingularity != null)
{
var pairedSingularityAO = AstroObjectLocator.GetAstroObject(pairedSingularity);
if(pairedSingularityAO != null)
{
switch (polarity)
{
case Polarity.BlackHole:
PairSingularities(newSingularity, pairedSingularityAO.gameObject);
break;
case Polarity.WhiteHole:
PairSingularities(pairedSingularityAO.gameObject, newSingularity);
break;
}
}
}
}
public static void PairSingularities(GameObject blackHole, GameObject whiteHole)
{
Logger.Log($"Pairing singularities {blackHole?.name}, {whiteHole?.name}");
try
{
blackHole.GetComponentInChildren<BlackHoleVolume>()._whiteHole = whiteHole.GetComponentInChildren<WhiteHoleVolume>();
}
catch (Exception)
{
Logger.LogError($"Couldn't pair singularities");
}
}
public static GameObject MakeBlackHole(GameObject body, Sector sector, Vector3 localPosition, float size, bool hasDestructionVolume, string targetSolarSystem, bool makeAudio = true)
{
var blackHole = new GameObject("BlackHole");
blackHole.SetActive(false);
blackHole.transform.parent = body.transform;
blackHole.transform.localPosition = localPosition;
var blackHoleRender = new GameObject("BlackHoleRender");
blackHoleRender.transform.parent = blackHole.transform;
blackHoleRender.transform.localPosition = Vector3.zero;
blackHoleRender.transform.localScale = Vector3.one * size;
var meshFilter = blackHoleRender.AddComponent<MeshFilter>();
meshFilter.mesh = GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleRenderer").GetComponent<MeshFilter>().mesh;
var meshRenderer = blackHoleRender.AddComponent<MeshRenderer>();
if (blackHoleShader == null) blackHoleShader = GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleRenderer").GetComponent<MeshRenderer>().sharedMaterial.shader;
meshRenderer.material = new Material(blackHoleShader);
meshRenderer.material.SetFloat("_Radius", size * 0.4f);
meshRenderer.material.SetFloat("_MaxDistortRadius", size * 0.95f);
meshRenderer.material.SetFloat("_MassScale", 1);
meshRenderer.material.SetFloat("_DistortFadeDist", size * 0.55f);
if(makeAudio)
{
var blackHoleAmbience = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleAmbience"), blackHole.transform);
blackHoleAmbience.name = "BlackHoleAmbience";
blackHoleAmbience.GetComponent<SectorAudioGroup>().SetSector(sector);
var blackHoleAudioSource = blackHoleAmbience.GetComponent<AudioSource>();
blackHoleAudioSource.maxDistance = size * 2.5f;
blackHoleAudioSource.minDistance = size * 0.4f;
blackHoleAmbience.transform.localPosition = Vector3.zero;
var blackHoleOneShot = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleEmissionOneShot"), blackHole.transform);
var oneShotAudioSource = blackHoleOneShot.GetComponent<AudioSource>();
oneShotAudioSource.maxDistance = size * 3f;
oneShotAudioSource.minDistance = size * 0.4f;
}
if (hasDestructionVolume || targetSolarSystem != null)
{
var destructionVolumeGO = new GameObject("DestructionVolume");
destructionVolumeGO.layer = LayerMask.NameToLayer("BasicEffectVolume");
destructionVolumeGO.transform.parent = blackHole.transform;
destructionVolumeGO.transform.localScale = Vector3.one;
destructionVolumeGO.transform.localPosition = Vector3.zero;
var sphereCollider = destructionVolumeGO.AddComponent<SphereCollider>();
sphereCollider.radius = size * 0.4f;
sphereCollider.isTrigger = true;
if (hasDestructionVolume) destructionVolumeGO.AddComponent<BlackHoleDestructionVolume>();
else if (targetSolarSystem != null)
{
var wormholeVolume = destructionVolumeGO.AddComponent<ChangeStarSystemVolume>();
wormholeVolume.TargetSolarSystem = targetSolarSystem;
}
}
else
{
var blackHoleVolume = GameObject.Instantiate(GameObject.Find("BrittleHollow_Body/BlackHole_BH/BlackHoleVolume"), blackHole.transform);
blackHoleVolume.name = "BlackHoleVolume";
blackHoleVolume.GetComponent<SphereCollider>().radius = size * 0.4f;
}
blackHole.SetActive(true);
return blackHole;
}
public static GameObject MakeWhiteHole(GameObject body, Sector sector, OWRigidbody OWRB, Vector3 localPosition, float size, bool makeZeroGVolume = true)
{
var whiteHole = new GameObject("WhiteHole");
whiteHole.SetActive(false);
whiteHole.transform.parent = body.transform;
whiteHole.transform.localPosition = localPosition;
var whiteHoleRenderer = new GameObject("WhiteHoleRenderer");
whiteHoleRenderer.transform.parent = whiteHole.transform;
whiteHoleRenderer.transform.localPosition = Vector3.zero;
whiteHoleRenderer.transform.localScale = Vector3.one * size * 2.8f;
var meshFilter = whiteHoleRenderer.AddComponent<MeshFilter>();
meshFilter.mesh = GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/Singularity").GetComponent<MeshFilter>().mesh;
var meshRenderer = whiteHoleRenderer.AddComponent<MeshRenderer>();
if (whiteHoleShader == null) whiteHoleShader = GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/Singularity").GetComponent<MeshRenderer>().sharedMaterial.shader;
meshRenderer.material = new Material(whiteHoleShader);
meshRenderer.sharedMaterial.SetFloat("_Radius", size * 0.4f);
meshRenderer.sharedMaterial.SetFloat("_DistortFadeDist", size);
meshRenderer.sharedMaterial.SetFloat("_MaxDistortRadius", size * 2.8f);
meshRenderer.sharedMaterial.SetColor("_Color", new Color(1.88f, 1.88f, 1.88f, 1f));
var ambientLight = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/WhiteHoleVisuals/AmbientLight_WH"));
ambientLight.transform.parent = whiteHole.transform;
ambientLight.transform.localScale = Vector3.one;
ambientLight.transform.localPosition = Vector3.zero;
ambientLight.name = "AmbientLight";
ambientLight.GetComponent<Light>().range = size * 7f;
GameObject whiteHoleVolumeGO = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/WhiteHoleVolume"));
whiteHoleVolumeGO.transform.parent = whiteHole.transform;
whiteHoleVolumeGO.transform.localPosition = Vector3.zero;
whiteHoleVolumeGO.transform.localScale = Vector3.one;
whiteHoleVolumeGO.GetComponent<SphereCollider>().radius = size;
whiteHoleVolumeGO.name = "WhiteHoleVolume";
var whiteHoleFluidVolume = whiteHoleVolumeGO.GetComponent<WhiteHoleFluidVolume>();
whiteHoleFluidVolume._innerRadius = size * 0.5f;
whiteHoleFluidVolume._outerRadius = size;
whiteHoleFluidVolume._attachedBody = OWRB;
var whiteHoleVolume = whiteHoleVolumeGO.GetComponent<WhiteHoleVolume>();
whiteHoleVolume._debrisDistMax = size * 6.5f;
whiteHoleVolume._debrisDistMin = size * 2f;
whiteHoleVolume._whiteHoleSector = sector;
whiteHoleVolume._fluidVolume = whiteHoleFluidVolume;
whiteHoleVolume._whiteHoleBody = OWRB;
whiteHoleVolume._whiteHoleProxyShadowSuperGroup = body.GetComponent<ProxyShadowCasterSuperGroup>();
whiteHoleVolumeGO.GetComponent<SphereCollider>().radius = size;
whiteHoleVolume.enabled = true;
whiteHoleFluidVolume.enabled = true;
if(makeZeroGVolume)
{
var zeroGVolume = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/ZeroGVolume"), whiteHole.transform);
zeroGVolume.name = "ZeroGVolume";
zeroGVolume.transform.localPosition = Vector3.zero;
zeroGVolume.GetComponent<SphereCollider>().radius = size * 10f;
zeroGVolume.GetComponent<ZeroGVolume>()._attachedBody = OWRB;
var rulesetVolume = GameObject.Instantiate(GameObject.Find("WhiteHole_Body/Sector_WhiteHole/RulesetVolumes_WhiteHole"), body.transform);
rulesetVolume.name = "RulesetVolume";
rulesetVolume.transform.localPosition = Vector3.zero;
rulesetVolume.transform.localScale = Vector3.one * size / 100f;
rulesetVolume.GetComponent<SphereShape>().enabled = true;
}
whiteHole.SetActive(true);
return whiteHole;
}
}
}

View File

@ -12,6 +12,8 @@ namespace NewHorizons.Builder.General
{
public static Tuple<AstroObject, OWRigidbody> Make(GameObject body, AstroObject primaryBody, IPlanetConfig config)
{
body.AddComponent<ProxyShadowCasterSuperGroup>();
Rigidbody rigidBody = body.AddComponent<Rigidbody>();
rigidBody.mass = 10000;
rigidBody.drag = 0f;
@ -38,6 +40,7 @@ namespace NewHorizons.Builder.General
var type = AstroObject.Type.Planet;
if (config.Orbit.IsMoon) type = AstroObject.Type.Moon;
else if (config.Base.IsSatellite) type = AstroObject.Type.Satellite;
else if (config.Base.HasCometTail) type = AstroObject.Type.Comet;
else if (config.Star != null) type = AstroObject.Type.Star;
else if (config.FocalPoint != null) type = AstroObject.Type.None;

View File

@ -13,22 +13,26 @@ namespace NewHorizons.Builder.General
MapMarker mapMarker = body.AddComponent<MapMarker>();
mapMarker.SetValue("_labelID", (UITextType)Utility.AddToUITable.Add(name.ToUpper()));
var markerType = "Planet";
var markerType = MapMarker.MarkerType.Planet;
if (config.Orbit.IsMoon)
{
markerType = "Moon";
markerType = MapMarker.MarkerType.Moon;
}
else if (config.Star != null)
{
markerType = "Sun";
markerType = MapMarker.MarkerType.Sun;
}
else if (config.FocalPoint != null)
{
markerType = "HourglassTwins";
markerType = MapMarker.MarkerType.HourglassTwins;
}
else if(config.Base.IsSatellite)
{
markerType = MapMarker.MarkerType.Probe;
}
mapMarker.SetValue("_markerType", mapMarker.GetType().GetNestedType("MarkerType", BindingFlags.NonPublic).GetField(markerType).GetValue(mapMarker));
mapMarker._markerType = markerType;
}
}
}

View File

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Builder.General
{
public static class ShipLogBuilder
{
public static ShipLogDetectiveMode StarChartMode;
public static void Init()
{
/*
var shipLogRoot = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas");
var starChartLog = GameObject.Instantiate(shipLogRoot.transform.Find("DetectiveMode"), shipLogRoot.transform);
starChartLog.transform.name = "StarChartMode";
var cardRoot = starChartLog.transform.Find("ScaleRoot").Find("PanRoot");
foreach(Transform child in cardRoot)
{
GameObject.Destroy(child.gameObject);
}
var cardPrefab = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DetectiveMode/ScaleRoot/PanRoot/TH_VILLAGE");
var detectiveMode = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DetectiveMode/");
var mapMode = GameObject.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/MapMode/");
StarChartMode = starChartLog.GetComponent<ShipLogDetectiveMode>();
StarChartMode._cardDict = new Dictionary<string, ShipLogEntryCard>();
StarChartMode._cardList = new List<ShipLogEntryCard>();
StarChartMode._centerPromptList = detectiveMode.GetComponent<ShipLogDetectiveMode>()._centerPromptList;
*/
}
}
}

View File

@ -32,13 +32,24 @@ namespace NewHorizons.Builder.Orbital
if (config.Orbit.Tint != null) color = config.Orbit.Tint.ToColor32();
else if (config.Star != null) color = config.Star.Tint.ToColor32();
else if (config.Atmosphere != null && config.Atmosphere.CloudTint != null) color = config.Atmosphere.CloudTint.ToColor32();
else if (config.Base.BlackHoleSize != 0) color = new Color(1f, 0.5f, 1f);
else if (config.Base.BlackHoleSize != 0 || config.Singularity != null) color = new Color(1f, 0.5f, 1f);
else if (config.Base.WaterSize != 0) color = new Color(0.5f, 0.5f, 1f);
else if (config.Base.LavaSize != 0) color = new Color(1f, 0.5f, 0.5f);
else if (config.Atmosphere != null && config.Atmosphere.FogTint != null) color = config.Atmosphere.FogTint.ToColor32();
var fade = isMoon;
if (config.Base.IsSatellite)
{
if(config.Orbit.Tint != null) color = new Color(0.4082f, 0.516f, 0.4469f, 1f);
fade = true;
orbitLine._fadeEndDist = 5000;
orbitLine._fadeStartDist = 3000;
}
orbitLine.SetValue("_color", color);
orbitLine.SetValue("_astroObject", astroobject);
orbitLine.SetValue("_fade", isMoon);
orbitLine.SetValue("_fade", fade);
orbitLine.SetValue("_lineWidth", 2f);
Main.Instance.ModHelper.Events.Unity.FireOnNextUpdate(() =>

View File

@ -9,39 +9,60 @@ using Random = UnityEngine.Random;
using Logger = NewHorizons.Utility.Logger;
using System.Reflection;
using NewHorizons.Utility;
using OWML.Common;
namespace NewHorizons.Builder.Props
{
public static class PropBuilder
{
public static void Make(GameObject go, Sector sector, IPlanetConfig config)
public static void Make(GameObject go, Sector sector, IPlanetConfig config, IModAssets assets, string uniqueModName)
{
if (config.Props.Scatter != null) PropBuilder.Scatter(go, config.Props.Scatter, config.Base.SurfaceSize, sector);
if (config.Props.Scatter != null)
{
PropBuilder.MakeScatter(go, config.Props.Scatter, config.Base.SurfaceSize, sector, assets, uniqueModName);
}
if(config.Props.Details != null)
{
foreach(var detail in config.Props.Details)
{
MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale);
if(detail.assetBundle != null)
{
var prefab = LoadPrefab(detail.assetBundle, detail.path, uniqueModName, assets);
MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
else if(detail.objFilePath != null)
{
try
{
var prefab = assets.Get3DObject(detail.objFilePath, detail.mtlFilePath);
prefab.SetActive(false);
MakeDetail(go, sector, prefab, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
catch(Exception e)
{
Logger.LogError($"Could not load 3d object {detail.objFilePath} with texture {detail.mtlFilePath} : {e.Message}");
}
}
else MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale, detail.alignToNormal);
}
}
}
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale)
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal)
{
var prefab = GameObject.Find(propToClone);
return MakeDetail(go, sector, prefab, position, rotation, scale);
//TODO: this is super costly
if (prefab == null) prefab = SearchUtilities.FindObjectOfTypeAndName<GameObject>(propToClone.Split(new char[] { '\\', '/' }).Last());
if (prefab == null) Logger.LogError($"Couldn't find detail {propToClone}");
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 = false)
public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal, bool snapToSurface = false)
{
if (prefab == null) return null;
GameObject prop = GameObject.Instantiate(prefab, sector.transform);
prop.transform.localPosition = position == null ? prefab.transform.localPosition : (Vector3)position;
Quaternion rot = rotation == null ? prefab.transform.localRotation : Quaternion.Euler((Vector3)rotation);
if (alignWithNormal) rot = Quaternion.FromToRotation(prop.transform.TransformDirection(Vector3.up), ((Vector3)position).normalized);
prop.transform.rotation = rot;
prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale;
prop.SetActive(false);
List<string> assetBundles = new List<string>();
@ -59,45 +80,54 @@ namespace NewHorizons.Builder.Props
sector.OnOccupantEnterSector += ((SectorDetector sd) => StreamingManager.LoadStreamingAssets(assetBundle));
}
foreach(var component in prop.GetComponentsInChildren<Component>())
foreach (var component in prop.GetComponentsInChildren<Component>())
{
try
{
var setSectorMethod = component.GetType().GetMethod("SetSector");
var sectorField = component.GetType().GetField("_sector");
// TODO: Make this work or smthng
if (component is GhostIK) (component as GhostIK).enabled = false;
if(component is GhostEffects) (component as GhostEffects).enabled = false;
if (setSectorMethod != null)
{
Logger.Log($"Found a SetSector method in {prop}.{component}");
setSectorMethod.Invoke(component, new object[] { sector });
}
else if (sectorField != null)
{
Logger.Log($"Found a _sector field in {component}");
sectorField.SetValue(component, sector);
}
}
catch (Exception e) { Logger.Log($"{e.Message}, {e.StackTrace}"); }
var enabledField = component.GetType().GetField("enabled");
if(enabledField != null && enabledField.FieldType == typeof(bool)) enabledField.SetValue(component, true);
}
prop.transform.parent = go.transform;
prop.transform.localPosition = position == null ? Vector3.zero : (Vector3)position;
Quaternion rot = rotation == null ? prefab.transform.rotation : Quaternion.Euler((Vector3)rotation);
prop.transform.rotation = rot;
if (alignWithNormal)
{
var up = prop.transform.localPosition.normalized;
var front = Vector3.Cross(up, Vector3.left);
if (front.sqrMagnitude == 0f) front = Vector3.Cross(up, Vector3.forward);
if (front.sqrMagnitude == 0f) front = Vector3.Cross(up, Vector3.up);
prop.transform.LookAt(prop.transform.position + front, up);
}
prop.transform.localScale = scale != 0 ? Vector3.one * scale : prefab.transform.localScale;
prop.SetActive(true);
return prop;
}
private static void Scatter(GameObject go, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector)
private static void MakeScatter(GameObject go, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector, IModAssets assets, string uniqueModName)
{
var area = 4f * Mathf.PI * radius * radius;
var points = FibonacciSphere((int)area);
foreach (var propInfo in scatterInfo)
{
var prefab = GameObject.Find(propInfo.path);
GameObject prefab;
if (propInfo.assetBundle != null) prefab = LoadPrefab(propInfo.assetBundle, propInfo.path, uniqueModName, assets);
else prefab = GameObject.Find(propInfo.path);
for(int i = 0; i < propInfo.count; i++)
{
var randomInd = (int)Random.Range(0, points.Count);
var point = points[randomInd];
var prop = MakeDetail(go, sector, prefab, (MVector3)(point.normalized * radius), null, 0f, true);
var prop = MakeDetail(go, sector, prefab, (MVector3)(point.normalized * radius), null, propInfo.scale, true, true);
if(propInfo.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset);
if(propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation);
points.RemoveAt(randomInd);
@ -126,5 +156,40 @@ namespace NewHorizons.Builder.Props
}
return points;
}
private static GameObject LoadPrefab(string assetBundle, string path, string uniqueModName, IModAssets assets)
{
string key = uniqueModName + "." + assetBundle;
AssetBundle bundle;
GameObject prefab;
try
{
if (Main.AssetBundles.ContainsKey(key)) bundle = Main.AssetBundles[key];
else
{
bundle = assets.LoadBundle(assetBundle);
Main.AssetBundles[key] = bundle;
}
}
catch (Exception e)
{
Logger.LogError($"Couldn't load AssetBundle {assetBundle} : {e.Message}");
return null;
}
try
{
prefab = bundle.LoadAsset<GameObject>(path);
prefab.SetActive(false);
}
catch (Exception e)
{
Logger.Log($"Couldn't load asset {path} from AssetBundle {assetBundle} : {e.Message}");
return null;
}
return prefab;
}
}
}

View File

@ -1,6 +1,7 @@
using NewHorizons.Components;
using NewHorizons.External;
using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
@ -83,20 +84,19 @@ namespace NewHorizons.Builder.Props
public static string GetCustomSignalName(SignalName signalName)
{
string name = null;
_customSignalNames.TryGetValue(signalName, out name);
_customSignalNames.TryGetValue(signalName, out string name);
return name;
}
public static void Make(GameObject body, Sector sector, SignalModule module)
public static void Make(GameObject body, Sector sector, SignalModule module, IModAssets assets)
{
foreach(var info in module.Signals)
{
Make(body, sector, info);
Make(body, sector, info, assets);
}
}
public static void Make(GameObject body, Sector sector, SignalModule.SignalInfo info)
public static void Make(GameObject body, Sector sector, SignalModule.SignalInfo info, IModAssets assets)
{
var signalGO = new GameObject($"Signal_{info.Name}");
signalGO.SetActive(false);
@ -107,15 +107,32 @@ namespace NewHorizons.Builder.Props
var source = signalGO.AddComponent<AudioSource>();
var owAudioSource = signalGO.AddComponent<OWAudioSource>();
AudioSignal audioSignal = null;
AudioSignal audioSignal;
if (info.InsideCloak) audioSignal = signalGO.AddComponent<CloakedAudioSignal>();
else audioSignal = signalGO.AddComponent<AudioSignal>();
var frequency = StringToFrequency(info.Frequency);
var name = StringToSignalName(info.Name);
AudioClip clip = SearchUtilities.FindResourceOfTypeAndName<AudioClip>(info.AudioClip);
if (clip == null) return;
AudioClip clip = null;
if(info.AudioClip != null) clip = SearchUtilities.FindResourceOfTypeAndName<AudioClip>(info.AudioClip);
else if (info.AudioFilePath != null)
{
try
{
clip = assets.GetAudio(info.AudioFilePath);
}
catch(Exception e)
{
Logger.LogError($"Couldn't load audio file {info.AudioFilePath} : {e.Message}");
}
}
if (clip == null)
{
Logger.LogError($"Couldn't find AudioClip {info.AudioClip} or AudioFile {info.AudioFilePath}");
return;
}
audioSignal.SetSector(sector);
audioSignal._frequency = frequency;

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
{
public class BlackHoleDestructionVolume : DestructionVolume
{
public override void Awake()
{
base.Awake();
_deathType = DeathType.BlackHole;
}
public override void VanishProbe(OWRigidbody probeBody, RelativeLocationData entryLocation)
{
SurveyorProbe requiredComponent = probeBody.GetRequiredComponent<SurveyorProbe>();
if (requiredComponent.IsLaunched())
{
UnityEngine.Object.Destroy(requiredComponent.gameObject);
}
}
}
}

View File

@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.Components
{
public class ChangeStarSystemVolume : BlackHoleDestructionVolume
{
public string TargetSolarSystem { get; set; }
public override void VanishPlayer(OWRigidbody playerBody, RelativeLocationData entryLocation)
{
Main.Instance.ChangeCurrentStarSystem(TargetSolarSystem);
}
}
}

View File

@ -13,5 +13,6 @@ namespace NewHorizons.External
public float Inclination { get; set; }
public float LongitudeOfAscendingNode { get; set; }
public int RandomSeed { get; set; }
public ProcGenModule ProcGen { get; set; }
}
}

View File

@ -16,10 +16,13 @@ namespace NewHorizons.External
public float SurfaceSize { get; set; }
public float WaterSize { get; set; }
public float GroundSize { get; set; }
public float BlackHoleSize { get; set; }
public float LavaSize { get; set; }
public bool HasCometTail { get; set; }
public bool HasReferenceFrame { get; set; } = true;
public bool CenterOfSolarSystem { get; set; } = false;
public bool IsSatellite { get; set; }
// Old, see SingularityModule instead
public float BlackHoleSize { get; set; }
}
}

View File

@ -5,6 +5,7 @@ namespace NewHorizons.External
public interface IPlanetConfig
{
string Name { get; }
string StarSystem { get; }
bool Destroy { get; }
int BuildPriority { get; }
BaseModule Base {get;}
@ -19,5 +20,6 @@ namespace NewHorizons.External
PropModule Props { get; }
SpawnModule Spawn { get; }
SignalModule Signal { get; }
SingularityModule Singularity { get; }
}
}

View File

@ -8,6 +8,7 @@ namespace NewHorizons.External
public class PlanetConfig : IPlanetConfig
{
public string Name { get; set; }
public string StarSystem { get; set; } = "SolarSystem";
public bool Destroy { get; set; }
public int BuildPriority { get; set; } = -1;
public MVector3 SpawnPoint { get; set; }
@ -23,6 +24,7 @@ namespace NewHorizons.External
public PropModule Props { get; set; }
public SpawnModule Spawn { get; set; }
public SignalModule Signal { get; set; }
public SingularityModule Singularity { get; set; }
public PlanetConfig(Dictionary<string, object> dict)
{

View File

@ -15,18 +15,24 @@ namespace NewHorizons.External
public class ScatterInfo
{
public string path;
public int count;
public string path;
public string assetBundle;
public MVector3 offset;
public MVector3 rotation;
public float scale { get; set; } = 1f;
}
public class DetailInfo
{
public string path;
public string objFilePath;
public string mtlFilePath;
public string assetBundle;
public MVector3 position;
public MVector3 rotation;
public float scale;
public float scale { get; set; } = 1f;
public bool alignToNormal;
}
}
}

View File

@ -13,5 +13,6 @@ namespace NewHorizons.External
public float Inclination { get; set; }
public float LongitudeOfAscendingNode { get; set; }
public string Texture { get; set; }
public bool Unlit { get; set; } = true;
}
}

View File

@ -16,7 +16,8 @@ namespace NewHorizons.External
public MVector3 Position;
public string Frequency;
public string Name;
public string AudioClip;
public string AudioClip = null;
public string AudioFilePath = null;
public float SourceRadius = 1f;
public float DetectionRadius = 0f;
public float IdentificationRadius = 10f;

View File

@ -0,0 +1,18 @@
using NewHorizons.Utility;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External
{
public class SingularityModule : Module
{
public float Size;
public string PairedSingularity;
public string TargetStarSystem;
public string Type; //BlackHole or WhiteHole
public MVector3 Position;
}
}

View File

@ -17,6 +17,7 @@ using System.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons
@ -29,11 +30,12 @@ namespace NewHorizons
public static List<NewHorizonsBody> BodyList = new List<NewHorizonsBody>();
public static List<NewHorizonsBody> NextPassBodies = new List<NewHorizonsBody>();
public static Dictionary<string, AssetBundle> AssetBundles = new Dictionary<string, AssetBundle>();
public static float FurthestOrbit { get; set; } = 50000f;
public StarLightController StarLightController { get; private set; }
private static string _currentStarSystem = "SolarSystem";
public override object GetApi()
{
return new NewHorizonsApi();
@ -57,6 +59,9 @@ namespace NewHorizons
{
Logger.LogWarning("Couldn't find planets folder");
}
//UnityEngine.Random.InitState();
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => OnSceneLoaded(SceneManager.GetActiveScene(), LoadSceneMode.Single));
}
public void OnDestroy()
@ -71,10 +76,14 @@ namespace NewHorizons
HeavenlyBodyBuilder.Reset();
if (scene.name != "SolarSystem") { return; }
if (scene.name.Equals("TitleScreen")) DisplayBodyOnTitleScreen();
if (scene.name != "SolarSystem") return;
NewHorizonsData.Load();
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => ShipLogBuilder.Init());
// Need to manage this when there are multiple stars
var sun = GameObject.Find("Sun_Body");
var starController = sun.AddComponent<StarController>();
@ -99,7 +108,7 @@ namespace NewHorizons
StarLightController = starLightGO.AddComponent<StarLightController>();
StarLightController.AddStar(starController);
starLightGO.SetActive(true);
// TODO: Make this configurable probably
@ -115,8 +124,10 @@ namespace NewHorizons
AstroObjectLocator.AddAstroObject(ao);
}
// Stars then planets then moons (not necessary but probably speeds things up, maybe)
var toLoad = BodyList.OrderBy(b =>
// Order by stars then planets then moons (not necessary but probably speeds things up, maybe) ALSO only include current star system
var toLoad = BodyList
.Where(b => b.Config.StarSystem.Equals(_currentStarSystem))
.OrderBy(b =>
(b.Config.BuildPriority != -1 ? b.Config.BuildPriority :
(b.Config.FocalPoint != null ? 0 :
(b.Config.Star != null) ? 0 :
@ -174,6 +185,65 @@ namespace NewHorizons
*/
}
public void DisplayBodyOnTitleScreen()
{
//Try loading one planet why not
GameObject titleScreenGO = new GameObject("TitleScreenPlanet");
var eligible = BodyList.Where(b => b.Config.Ring != null && (b.Config.HeightMap != null || (b.Config.Atmosphere?.Cloud != null))).ToArray();
var body = eligible[UnityEngine.Random.Range(0, eligible.Count())];
Logger.Log($"Displaying {body.Config.Name} on the title screen");
var flag = false;
HeightMapModule heightMap = new HeightMapModule();
var minSize = 20;
var maxSize = 35;
float size = minSize;
if (body.Config.HeightMap != null)
{
size = Mathf.Clamp(body.Config.HeightMap.MaxHeight / 10, minSize, maxSize);
heightMap.TextureMap = body.Config.HeightMap.TextureMap;
heightMap.HeightMap = body.Config.HeightMap.HeightMap;
heightMap.MaxHeight = size;
heightMap.MinHeight = body.Config.HeightMap.MinHeight * size / body.Config.HeightMap.MaxHeight;
flag = true;
}
if (body.Config.Atmosphere != null && body.Config.Atmosphere.Cloud != null)
{
// Hacky but whatever I just want a sphere
size = Mathf.Clamp(body.Config.Atmosphere.Size / 10, minSize, maxSize);
heightMap.MaxHeight = heightMap.MinHeight = size+1;
heightMap.TextureMap = body.Config.Atmosphere.Cloud;
flag = true;
}
if (flag)
{
HeightMapBuilder.Make(titleScreenGO, heightMap, body.Assets);
if (body.Config.Ring != null)
{
RingModule newRing = new RingModule();
newRing.InnerRadius = size * 1.2f;
newRing.OuterRadius = size * 2f;
newRing.Texture = body.Config.Ring.Texture;
RingBuilder.Make(titleScreenGO, newRing, body.Assets);
titleScreenGO.transform.localScale = Vector3.one * 0.8f;
}
GameObject.Find("Scene/Background/PlanetPivot/Prefab_HEA_Campfire").SetActive(false);
GameObject.Find("Scene/Background/PlanetPivot/PlanetRoot").SetActive(false);
titleScreenGO.transform.parent = GameObject.Find("Scene/Background/PlanetPivot/").transform;
titleScreenGO.transform.localPosition = Vector3.zero;
var lightGO = new GameObject("Light");
lightGO.transform.parent = titleScreenGO.transform.parent.parent;
lightGO.transform.localPosition = new Vector3(-47.9203f, 145.7596f, 43.1802f);
var light = lightGO.AddComponent<Light>();
light.color = new Color(1f, 1f, 1f, 1f);
light.range = 100;
light.intensity = 0.8f;
}
}
private bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
{
var stringID = body.Config.Name.ToUpper().Replace(" ", "_").Replace("'", "");
@ -238,7 +308,7 @@ namespace NewHorizons
{
var config = mod.ModHelper.Storage.Load<PlanetConfig>(file.Replace(folder, ""));
Logger.Log($"Loaded {config.Name}");
BodyList.Add(new NewHorizonsBody(config, mod.ModHelper.Assets));
BodyList.Add(new NewHorizonsBody(config, mod.ModHelper.Assets, mod.ModHelper.Manifest.UniqueName));
}
catch (Exception e)
{
@ -291,7 +361,7 @@ namespace NewHorizons
if (body.Config.Base.GroundSize != 0) GeometryBuilder.Make(go, body.Config.Base.GroundSize);
var atmoSize = body.Config.Atmosphere != null ? body.Config.Atmosphere.Size : 0f;
float sphereOfInfluence = Mathf.Max(atmoSize, body.Config.Base.SurfaceSize * 2f);
float sphereOfInfluence = Mathf.Max(Mathf.Max(atmoSize, 50), body.Config.Base.SurfaceSize * 2f);
var outputTuple = BaseBuilder.Make(go, primaryBody, body.Config);
var ao = (AstroObject)outputTuple.Item1;
@ -321,9 +391,6 @@ namespace NewHorizons
if (body.Config.ProcGen != null)
ProcGenBuilder.Make(go, body.Config.ProcGen);
if (body.Config.Base.BlackHoleSize != 0)
BlackHoleBuilder.Make(go, body.Config.Base, sector);
if (body.Config.Star != null) StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star));
if (body.Config.FocalPoint != null)
@ -369,7 +436,7 @@ namespace NewHorizons
RingBuilder.Make(go, body.Config.Ring, body.Assets);
if (body.Config.AsteroidBelt != null)
AsteroidBeltBuilder.Make(body.Config.Name, body.Config.AsteroidBelt, body.Assets);
AsteroidBeltBuilder.Make(body.Config.Name, body.Config, body.Assets, body.ModUniqueName);
if (body.Config.Base.HasCometTail)
CometTailBuilder.Make(go, body.Config.Base, go.GetComponent<AstroObject>().GetPrimaryBody());
@ -399,13 +466,22 @@ namespace NewHorizons
}
if (body.Config.Props != null)
PropBuilder.Make(go, sector, body.Config);
PropBuilder.Make(go, sector, body.Config, body.Assets, body.ModUniqueName);
if (body.Config.Signal != null)
SignalBuilder.Make(go, sector, body.Config.Signal);
SignalBuilder.Make(go, sector, body.Config.Signal, body.Assets);
if (body.Config.Base.BlackHoleSize != 0 || body.Config.Singularity != null)
SingularityBuilder.Make(go, sector, rb, body.Config);
return go;
}
public void ChangeCurrentStarSystem(string newStarSystem)
{
_currentStarSystem = newStarSystem;
LoadManager.LoadSceneAsync(OWScene.SolarSystem, true, LoadManager.FadeType.ToBlack, 0.1f, true);
}
}
public class NewHorizonsApi
@ -421,7 +497,7 @@ namespace NewHorizons
Logger.Log("Recieved API request to create planet " + (string)config["Name"], Logger.LogType.Log);
var planetConfig = new PlanetConfig(config);
var body = new NewHorizonsBody(planetConfig, mod != null ? mod.ModHelper.Assets : Main.Instance.ModHelper.Assets);
var body = new NewHorizonsBody(planetConfig, mod != null ? mod.ModHelper.Assets : Main.Instance.ModHelper.Assets, mod.ModHelper.Manifest.UniqueName);
Main.BodyList.Add(body);
}

View File

@ -25,6 +25,9 @@
</None>
<None Include="manifest.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="AssetBundle\**">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>

View File

@ -1,4 +1,5 @@
using System;
using NewHorizons.Builder.Body;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -13,6 +14,9 @@ namespace NewHorizons.Utility
{
private OWRigidbody _rb;
private GameObject blackHole;
private GameObject whiteHole;
private void Awake()
{
_rb = this.GetRequiredComponent<OWRigidbody>();
@ -34,6 +38,48 @@ namespace NewHorizons.Utility
}
_rb.EnableCollisionDetection();
}
/*
// Portal Gun:
if (Keyboard.current == null) return;
var fireBlackHole = Keyboard.current[Key.B].wasReleasedThisFrame;
var fireWhiteHole = Keyboard.current[Key.N].wasReleasedThisFrame;
if (fireBlackHole || fireWhiteHole)
{
// Raycast
_rb.DisableCollisionDetection();
int layerMask = OWLayerMask.physicalMask;
var origin = Locator.GetActiveCamera().transform.position;
var direction = Locator.GetActiveCamera().transform.TransformDirection(Vector3.forward);
if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, Mathf.Infinity, OWLayerMask.physicalMask))
{
var pos = hitInfo.transform.InverseTransformPoint(hitInfo.point + hitInfo.normal);
var hitBody = hitInfo.transform.gameObject;
var sector = hitBody.GetComponent<AstroObject>()?.GetRootSector();
if (hitBody == null || sector == null) return;
Logger.Log($"{hitBody}");
if (fireBlackHole)
{
if (blackHole != null) GameObject.Destroy(blackHole);
blackHole = SingularityBuilder.MakeBlackHole(hitBody, sector, pos, 2, false, null, false);
Logger.Log("Make black hole");
}
else
{
if (whiteHole != null) GameObject.Destroy(whiteHole);
whiteHole = SingularityBuilder.MakeWhiteHole(hitBody, sector, hitBody.GetAttachedOWRigidbody(), pos, 2, false);
Logger.Log("Make white hole");
}
if(blackHole && whiteHole)
{
SingularityBuilder.PairSingularities(blackHole, whiteHole);
}
}
_rb.EnableCollisionDetection();
}
*/
}
}
}

View File

@ -6,14 +6,16 @@ namespace NewHorizons.Utility
{
public class NewHorizonsBody
{
public NewHorizonsBody(IPlanetConfig config, IModAssets assets)
public NewHorizonsBody(IPlanetConfig config, IModAssets assets, string modUniqueName)
{
Config = config;
Assets = assets;
ModUniqueName = modUniqueName;
}
public IPlanetConfig Config;
public IModAssets Assets;
public string ModUniqueName;
public GameObject Object;
}

View File

@ -1,4 +1,5 @@
using NewHorizons.Builder.Props;
using NewHorizons.Builder.General;
using NewHorizons.Builder.Props;
using NewHorizons.Components;
using NewHorizons.External;
using OWML.Common;
@ -43,6 +44,12 @@ namespace NewHorizons.Utility
var playerDataResetGame = typeof(PlayerData).GetMethod("ResetGame");
Main.Instance.ModHelper.HarmonyHelper.AddPostfix(playerDataResetGame, typeof(Patches), nameof(Patches.OnPlayerDataResetGame));
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<BlackHoleVolume>("Start", typeof(Patches), nameof(Patches.OnBlackHoleVolumeStart));
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<WhiteHoleVolume>("Awake", typeof(Patches), nameof(Patches.OnWhiteHoleVolumeAwake));
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ProbeLauncher>("UpdateOrbitalLaunchValues", typeof(Patches), nameof(Patches.OnProbeLauncherUpdateOrbitalLaunchValues));
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ShipLogController>("Update", typeof(Patches), nameof(Patches.OnShipLogControllerUpdate));
// Postfixes
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<MapController>("Awake", typeof(Patches), nameof(Patches.OnMapControllerAwake));
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<OWCamera>("Awake", typeof(Patches), nameof(Patches.OnOWCameraAwake));
@ -306,5 +313,61 @@ namespace NewHorizons.Utility
NewHorizonsData.Reset();
}
#endregion
public static bool OnBlackHoleVolumeStart(BlackHoleVolume __instance)
{
return __instance._whiteHole == null;
}
public static bool OnWhiteHoleVolumeAwake(WhiteHoleVolume __instance)
{
__instance._growQueue = new List<OWRigidbody>(8);
__instance._growQueueLocationData = new List<RelativeLocationData>(8);
__instance._ejectedBodyList = new List<OWRigidbody>(64);
try
{
__instance._whiteHoleBody = __instance.gameObject.GetAttachedOWRigidbody(false);
__instance._whiteHoleProxyShadowSuperGroup = __instance._whiteHoleBody.GetComponentInChildren<ProxyShadowCasterSuperGroup>();
__instance._fluidVolume = __instance.gameObject.GetRequiredComponent<WhiteHoleFluidVolume>();
}
catch (Exception) { }
return false;
}
public static bool OnProbeLauncherUpdateOrbitalLaunchValues(ProbeLauncher __instance)
{
return (Locator.GetPlayerRulesetDetector()?.GetPlanetoidRuleset()?.GetGravityVolume() != null);
}
public static bool OnShipLogControllerUpdate(ShipLogController __instance)
{
if (__instance._exiting
|| OWInput.GetInputMode() != InputMode.ShipComputer
|| __instance._currentMode.AllowCancelInput() && OWInput.IsNewlyPressed(InputLibrary.cancel, InputMode.All)
|| ShipLogBuilder.StarChartMode == null)
return true;
__instance._exitPrompt.SetVisibility(__instance._currentMode.AllowCancelInput());
__instance._currentMode.UpdateMode();
if (__instance._currentMode.AllowModeSwap() && OWInput.IsNewlyPressed(InputLibrary.swapShipLogMode, InputMode.All))
{
ShipLogMode currentMode = __instance._currentMode;
string focusedEntryID = currentMode.GetFocusedEntryID();
bool flag = currentMode.Equals(__instance._mapMode);
__instance._currentMode = (flag ? __instance._detectiveMode : __instance._mapMode);
if (currentMode.Equals(__instance._mapMode))
__instance._currentMode = ShipLogBuilder.StarChartMode;
else if (currentMode.Equals(ShipLogBuilder.StarChartMode))
__instance._currentMode = __instance._detectiveMode;
else
__instance._currentMode = __instance._mapMode;
currentMode.ExitMode();
__instance._currentMode.EnterMode(focusedEntryID, null);
__instance._oneShotSource.PlayOneShot(flag ? global::AudioType.ShipLogEnterDetectiveMode : global::AudioType.ShipLogEnterMapMode, 1f);
}
return false;
}
}
}

View File

@ -10,7 +10,7 @@ namespace NewHorizons.Utility
{
public static class SearchUtilities
{
public static List<T> FindObjectsOfTypeAndName<T>(string name) where T : MonoBehaviour
public static List<T> FindObjectsOfTypeAndName<T>(string name) where T : Object
{
T[] firstList = GameObject.FindObjectsOfType<T>();
List<T> finalList = new List<T>();
@ -26,6 +26,22 @@ namespace NewHorizons.Utility
return finalList;
}
public static T FindObjectOfTypeAndName<T>(string name) where T : Object
{
T[] firstList = GameObject.FindObjectsOfType<T>();
List<T> finalList = new List<T>();
for (var i = 0; i < firstList.Length; i++)
{
if (firstList[i].name == name)
{
return firstList[i];
}
}
return null;
}
public static List<T> FindResourcesOfTypeAndName<T>(string name) where T : Object
{
T[] firstList = Resources.FindObjectsOfTypeAll<T>();

View File

@ -3,7 +3,7 @@
"author": "xen",
"name": "New Horizons",
"uniqueName": "xen.NewHorizons",
"version": "0.3.1",
"version": "0.4.0",
"owmlVersion": "2.1.0",
"dependencies": [ "PacificEngine.OW_CommonResources" ]
}

120
README.md
View File

@ -1,8 +1,15 @@
![new horizons thumbnail](https://user-images.githubusercontent.com/22628069/146680547-bd815057-9f4e-42da-a6c4-84d3ff82ff2c.png)
![Current version](https://img.shields.io/github/manifest-json/v/xen-42/outer-wilds-new-horizons?color=gree&filename=NewHorizons%2Fmanifest.json)
![Downloads](https://img.shields.io/github/downloads/xen-42/outer-wilds-new-horizons/total)
![Downloads of newest version](https://img.shields.io/github/downloads/xen-42/outer-wilds-new-horizons/latest/total)
A planet creator for Outer Wilds.
Planets are created using a JSON file format structure, and placed in the `planets` folder.
You can view the addons creators have made [here](https://outerwildsmods.com/mods/newhorizons/addons/)!
Planets are created using a JSON file format structure, and placed in the `planets` folder (or in any sub-directory of it).
NOTE: Any mod that requires PacificEngine's CommonResources is not compatible with New Horizons currently. Both mods mess with planets and orbits and end up clashing. We're currently working on a solution.
<!-- TOC -->
@ -15,9 +22,14 @@ Planets are created using a JSON file format structure, and placed in the `plane
- [AsteroidBelt](#asteroidbelt)
- [FocalPoint](#focalpoint)
- [Props](#props)
- [Asset Bundles](#asset-bundles)
- [Ring](#ring)
- [Spawn](#spawn)
- [Star](#star)
- [Signal](#signal)
- [Singularity](#singularity)
- [How to destroy existing planets](#how-to-destroy-existing-planets)
- [How to update existing planets](#how-to-update-existing-planets)
- [How to use New Horizons in other mods](#how-to-use-new-horizons-in-other-mods)
- [Credits](#credits)
@ -31,14 +43,14 @@ Planets are created using a JSON file format structure, and placed in the `plane
- Comets (Done)
- Signalscope signals (Done)
- Asteroid belts (Done)
- Support satellites (Done)
- Surface scatter: rocks, trees, etc, using in-game models (done) or custom ones (done)
- Load planet meshes from asset bundle (technically done)
- Black hole / white hole pairs (done)
- Procedurally terrain generation (started)
- Support satellites (using custom models in the assets folder or in-game ones)
- Surface scatter: rocks, trees, etc, using in-game models (done) or custom ones
- Load planet meshes from asset bundle
- "Quantum" planet parameters
- Better terrain and water LOD
- Edit existing planet orbits
- Black hole / white hole pairs
- Separate solar system scenes accessible via wormhole
- Implement all planet features:
- Tornados
@ -177,7 +189,7 @@ Some of these I don't explain since they are just orbital parameters. If you don
- "longitudeOfAscendingNode" : (decimal number)
- "argumentOfPeriapsis" : (decimal number)
- "eccentricity" : (decimal number from 0 to < 1) The closer to 1 it is, the more oval-shaped the orbit is.
- "trueAnomaly" : (decimal number) Where the planet should start off in its orbit in terms of the central angle. From 0 to 360.
- "trueAnomaly" : (decimal number) Where the planet should start off in its orbit in terms of the central angle. From 0 to 360. NOTE: This is currently broken for eccentric orbits which (for now) always start at periapsis. If you want to move the starting point, set argument of periapsis instead.
- "axialTilt" : (decimal number)
- "siderealPeriod" : (decimal number)
- "isTidallyLocked" : (true/false)
@ -282,9 +294,9 @@ and
The positions of the binaries will be based off of their masses (as determined by the "surfaceGravity" parameter). However, one of them must have a non-zero semiMajorAxis field else the mod gets confused. This example uses stars, but it will also work for planets. If you want to have other planets orbiting the center of mass, just put the focal point body as the primary body.
### Props
Lets you place items on the surface of the planet. Currently this is a very early release version.
Lets you place items on the surface of the planet.
-scatter : (list) I'll just give an example.
- "scatter" : (list) I'll just give an example.
```
"scatter" : [
@ -294,6 +306,49 @@ Lets you place items on the surface of the planet. Currently this is a very earl
The path is in the hierarchy of the solar system. Use the [Unity Explorer](https://outerwildsmods.com/mods/unityexplorer) mod to find an object you want to copy onto your new body. Some objects work better than others for this. Good luck.
- "details" : (list of detail info objects)
A detail info object can have the following parameters:
- "path" : (string) either the location of it in the scene hierarchy or in the asset bundle provided
- "assetBundle" : (string) the asset bundle containing the object
- "objFilePath" : (string) the file path to a .obj 3d model
- "mtlFilePath" : (string) the file path to the material for the .obj model
- "position" : (x, y, z)
- "rotation" : (x, y, z) the euler angle rotation from a 3d vector
- "scale" : (decimal number)
- "alignToNormal" : (true/false) If it should align with the normal vector of the surface its own (overwrites rotation)
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
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).
2. In the root directory create a folder called "Editor". In it create a file called "CreateAssetBundle.cs" with the following code in it:
```
using UnityEditor;
using UnityEngine;
using System.IO;
public class CreateAssetBundles
{
[MenuItem("Assets/Build AssetBundles")]
static void BuildAllAssetBundles()
{
string assetBundleDirectory = "Assets/StreamingAssets";
if (!Directory.Exists(Application.streamingAssetsPath))
{
Directory.CreateDirectory(assetBundleDirectory);
}
BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows64);
}
}
```
3. Create your object in the Unity scene and save it as a prefab.
4. Add all files used (models, prefabs, textures, materials, etc) to an asset bundle by selecting them and using the drop down in the bottom right. Here I am adding a rover model to my "rss" asset bundle for the Real Solar System add-on.
![setting asset bundle](https://user-images.githubusercontent.com/22628069/147954146-e1d610c0-0336-428f-8b32-bfc01090061c.png)
5. In the top left click the "Assets" drop-down and select "Build AssetBundles". This should create your asset bundle in a folder in the root directory called "StreamingAssets".
6. Copy the asset bundle and asset bundle .manifest files from StreamingAssets into your mod's "planets" folder. If you did everything properly they should work in game. To double check everything is included, open the .manifest file in a text editor to see the files included and their paths.
### Ring
- "innerRadius" : (decimal number)
- "outerRadius" : (decimal number)
@ -312,6 +367,47 @@ Use this if you are creating a star.
- "tint" : (colour)
- "solarFlareTint" : (colour) The flares are tinted weirdly so this won't make the actual colour of the star. You'll want to use trial and error to find something that matches.
### Signal
- "signals" : (list of signal info objects)
Signal info objects can then have the following values set:
- "position" : (position) To find a good value for this, fly to the planet, look directly at where you want the signal to come from, and press "P" to have the game log the position you're looking at.
- "frequency" : (string) There are 7 acceptible values for this:
- "Default" : appears in game as ???
- "Traveler" : appears in game as "Outer Wilds Ventures"
- "Quantum" : appears in game as "Quantum Fluctuations"
- "EscapePod" : appears in game as "Distress Signal"
- "Statue" : appears in game as "Nomai Statue"
- "WarpCore" : appears in game as "Anti-Graviton Flux"
- "HideAndSeek" : appears in game as "Hide and Seek"
- "Radio" : appears in game as "Deep Space Radio"
- "name" : (string) The name as it will appear in game
- "audioClip" : (string) The audio clip from the game you want to use (can find these using Unity Explorer or by datamining)
- "audioFilePath" : (string) The file path to a .wav you want to use as the audio clip
- "sourceRadius" : (decimal number) The radius of the spherical volume the signal appears to come from
- "detectionRadius" : (decimal number) How close you must be to get the "Unidentified signal detected" pop-up
- "identiicationRadius" : (decimal number) How close you must get to identify the signal
- "onlyAudibleToScope" : (true/false)
- "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:
```
"Signal" :
{
"Signals" :
[
{ "Frequency" : "Statue", "Name" : "Museum Statue", "AudioClip" : "OW NM Flashback 082818 AP loop", "SourceRadius" : 1, "Position" : {"x": -76.35, "y": 12, "z": 214.7 } },
{ "Frequency" : "WarpCore", "Name" : "Timber Hearth Receiver", "AudioClip" : "OW_NM_WhiteHoleAmbienceL", "SourceRadius" : 0.5, "Position" : {"x": -237.8, "y": -50.8, "z": -59.2 } }
]
}
```
### Singularity
This allows you to make black holes and white holes, and to pair them.
- "size" : (decimal number)
- "pairedSingularity" : (string) The singularity you want this one to pair to. Must be the opposite type. If you don't set this, the singularity will not transport you, and if it is a black hole it will kill you on entry.
- "type" : (string) Put either "BlackHole" or "WhiteHole".
### How to destroy existing planets
You do this (but with the appropriate name) as it's own config.
@ -322,7 +418,13 @@ You do this (but with the appropriate name) as it's own config.
}
```
Remember that if you destroy Timber Hearth you better put a [Spawn](#spawn) module on another planet. I haven't tried destroying the sun. Probably don't do that, it will break everything. Probably.
Remember that if you destroy Timber Hearth you better put a [Spawn](#spawn) module on another planet. If you want to entirely replace the solar system you can restroy everything, including the sun. You can use the prefabs from my [Real Solar System](https://github.com/xen-42/outer-wilds-real-solar-system) addon, in the `planets/0 - original planets` folder. Also, deleting a planet destroys anything orbiting it, so if you want to replace the solar system you can just destroy the sun.
### How to update existing planets
Similar to above, make a config where "Name" is the name of the planet. The name should be able to just match their in-game english names, however if you encounter any issues with that here are the in-code names for planets that are guaranteed to work: `Sun`, `CaveTwin` (Ember Twin), `TowerTwin` (Ash Twin), `TimberHearth`, `BrittleHollow`, `GiantsDeep`, `DarkBramble`, `Comet` (Interloper), `WhiteHole`, `WhiteHoleTarget` (Whitehole station I believe), `QuantumMoon`, `ProbeCannon`, `TimberMoon` (Attlerock), `VolcanicMoon` (Hollow's Lantern), `DreamWorld`, `MapSatellite`, `RingWorld` (the Stranger).
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.
## How to use New Horizons in other mods