mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Merge branch 'common-resources' of github.com:xen-42/outer-wilds-new-horizons into common-resources
This commit is contained in:
commit
f3bf6e945c
@ -6,7 +6,7 @@ namespace NewHorizons.Atmosphere
|
||||
{
|
||||
static class AtmosphereBuilder
|
||||
{
|
||||
public static void Make(GameObject body, AtmosphereModule atmosphereModule)
|
||||
public static void Make(GameObject body, AtmosphereModule atmosphereModule, float surfaceSize)
|
||||
{
|
||||
GameObject atmoGO = new GameObject("Atmosphere");
|
||||
atmoGO.SetActive(false);
|
||||
@ -14,66 +14,19 @@ namespace NewHorizons.Atmosphere
|
||||
|
||||
if (atmosphereModule.HasAtmosphere)
|
||||
{
|
||||
var mat = GameObject.Find("TimberHearth_Body/Atmosphere_TH/AtmoSphere/Atmosphere_LOD0").GetComponent<MeshRenderer>().material;
|
||||
|
||||
GameObject atmo = GameObject.Instantiate(GameObject.Find("Atmosphere_TH/AtmoSphere"));
|
||||
GameObject atmo = GameObject.Instantiate(GameObject.Find("TimberHearth_Body/Atmosphere_TH/AtmoSphere"));
|
||||
atmo.transform.parent = atmoGO.transform;
|
||||
atmo.transform.localPosition = Vector3.zero;
|
||||
atmo.transform.localScale = Vector3.one * atmosphereModule.Size;
|
||||
atmo.transform.localScale = Vector3.one * atmosphereModule.Size * 1.2f;
|
||||
foreach(var meshRenderer in atmo.GetComponentsInChildren<MeshRenderer>())
|
||||
{
|
||||
meshRenderer.material.SetFloat("_InnerRadius", atmosphereModule.Cloud != null ? atmosphereModule.Size : surfaceSize);
|
||||
meshRenderer.material.SetFloat("_OuterRadius", atmosphereModule.Size * 1.2f);
|
||||
if(atmosphereModule.AtmosphereTint != null)
|
||||
meshRenderer.material.SetColor("_SkyColor", atmosphereModule.AtmosphereTint.ToColor32());
|
||||
}
|
||||
|
||||
atmo.SetActive(true);
|
||||
|
||||
/*
|
||||
GameObject lod0 = new GameObject();
|
||||
lod0.transform.parent = atmo.transform;
|
||||
lod0.transform.localPosition = Vector3.zero;
|
||||
MeshFilter f0 = lod0.AddComponent<MeshFilter>();
|
||||
f0.mesh = GameObject.Find("Atmosphere_LOD0").GetComponent<MeshFilter>().mesh;
|
||||
MeshRenderer r0 = lod0.AddComponent<MeshRenderer>();
|
||||
r0.material = mat;
|
||||
|
||||
GameObject lod1 = new GameObject();
|
||||
lod1.transform.parent = atmo.transform;
|
||||
lod1.transform.localPosition = Vector3.zero;
|
||||
MeshFilter f1 = lod1.AddComponent<MeshFilter>();
|
||||
f1.mesh = GameObject.Find("Atmosphere_LOD1").GetComponent<MeshFilter>().mesh;
|
||||
MeshRenderer r1 = lod1.AddComponent<MeshRenderer>();
|
||||
r1.material = mat;
|
||||
|
||||
GameObject lod2 = new GameObject();
|
||||
lod2.transform.parent = atmo.transform;
|
||||
lod2.transform.localPosition = Vector3.zero;
|
||||
MeshFilter f2 = lod2.AddComponent<MeshFilter>();
|
||||
f2.mesh = GameObject.Find("Atmosphere_LOD2").GetComponent<MeshFilter>().mesh;
|
||||
MeshRenderer r2 = lod2.AddComponent<MeshRenderer>();
|
||||
r2.material = mat;
|
||||
|
||||
GameObject lod3 = new GameObject();
|
||||
lod3.transform.parent = atmo.transform;
|
||||
lod3.transform.localPosition = Vector3.zero;
|
||||
MeshFilter f3 = lod3.AddComponent<MeshFilter>();
|
||||
f3.mesh = GameObject.Find("Atmosphere_LOD3").GetComponent<MeshFilter>().mesh;
|
||||
MeshRenderer r3 = lod3.AddComponent<MeshRenderer>();
|
||||
r3.material = mat;
|
||||
|
||||
LODGroup lodg = atmo.AddComponent<LODGroup>();
|
||||
|
||||
LOD[] lodlist = new LOD[4];
|
||||
Renderer[] t0 = { r0 };
|
||||
Renderer[] t1 = { r1 };
|
||||
Renderer[] t2 = { r2 };
|
||||
Renderer[] t3 = { r3 };
|
||||
LOD one = new LOD(1, t0);
|
||||
LOD two = new LOD(0.7f, t1);
|
||||
LOD three = new LOD(0.27f, t2);
|
||||
LOD four = new LOD(0.08f, t3);
|
||||
lodlist[0] = one;
|
||||
lodlist[1] = two;
|
||||
lodlist[2] = three;
|
||||
lodlist[3] = four;
|
||||
|
||||
lodg.SetLODs(lodlist);
|
||||
lodg.fadeMode = LODFadeMode.None;
|
||||
*/
|
||||
}
|
||||
|
||||
atmoGO.transform.localPosition = Vector3.zero;
|
||||
|
||||
@ -14,79 +14,98 @@ namespace NewHorizons.Builder.Body
|
||||
static class StarBuilder
|
||||
{
|
||||
private static Texture2D _colorOverTime;
|
||||
public static void Make(GameObject body, Sector sector, StarModule starModule)
|
||||
public static StarController Make(GameObject body, Sector sector, StarModule starModule)
|
||||
{
|
||||
if (_colorOverTime == null) _colorOverTime = Main.Instance.ModHelper.Assets.GetTexture("AssetBundle/StarColorOverTime.png");
|
||||
|
||||
var sunGO = new GameObject("Star");
|
||||
sunGO.transform.parent = body.transform;
|
||||
var starGO = new GameObject("Star");
|
||||
starGO.transform.parent = body.transform;
|
||||
|
||||
var sunSurface = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Geometry_SUN/Surface"), sunGO.transform);
|
||||
var sunSurface = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Geometry_SUN/Surface"), starGO.transform);
|
||||
sunSurface.transform.localPosition = Vector3.zero;
|
||||
sunSurface.transform.localScale = Vector3.one;
|
||||
sunSurface.name = "Surface";
|
||||
|
||||
//var sunLight = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight"), sunGO.transform);
|
||||
var sunLight = new GameObject();
|
||||
sunLight.transform.parent = sunGO.transform;
|
||||
sunLight.transform.parent = starGO.transform;
|
||||
sunLight.transform.localPosition = Vector3.zero;
|
||||
sunLight.transform.localScale = Vector3.one;
|
||||
sunLight.name = "StarLight";
|
||||
var light = sunLight.AddComponent<Light>();
|
||||
light.CopyPropertiesFrom(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<Light>());
|
||||
|
||||
light.intensity *= starModule.SolarLuminosity;
|
||||
light.range *= Mathf.Sqrt(starModule.SolarLuminosity);
|
||||
|
||||
var solarFlareEmitter = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SolarFlareEmitter"), sunGO.transform);
|
||||
var faceActiveCamera = sunLight.AddComponent<FaceActiveCamera>();
|
||||
faceActiveCamera.CopyPropertiesFrom(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<FaceActiveCamera>());
|
||||
var csmTextureCacher = sunLight.AddComponent<CSMTextureCacher>();
|
||||
csmTextureCacher.CopyPropertiesFrom(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<CSMTextureCacher>());
|
||||
csmTextureCacher._light = light;
|
||||
var proxyShadowLight = sunLight.AddComponent<ProxyShadowLight>();
|
||||
proxyShadowLight.CopyPropertiesFrom(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<ProxyShadowLight>());
|
||||
proxyShadowLight._light = light;
|
||||
|
||||
var solarFlareEmitter = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SolarFlareEmitter"), starGO.transform);
|
||||
solarFlareEmitter.transform.localPosition = Vector3.zero;
|
||||
solarFlareEmitter.transform.localScale = Vector3.one;
|
||||
solarFlareEmitter.name = "SolarFlareEmitter";
|
||||
|
||||
var sunAudio = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Audio_SUN"), sunGO.transform);
|
||||
var sunAudio = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Audio_SUN"), starGO.transform);
|
||||
sunAudio.transform.localPosition = Vector3.zero;
|
||||
sunAudio.transform.localScale = Vector3.one;
|
||||
sunAudio.transform.Find("SurfaceAudio_Sun").GetComponent<AudioSource>().maxDistance = starModule.Size * 2f;
|
||||
var surfaceAudio = sunAudio.GetComponentInChildren<SunSurfaceAudioController>();
|
||||
surfaceAudio.SetSector(sector);
|
||||
surfaceAudio._sunController = null;
|
||||
|
||||
sunAudio.name = "Audio_Star";
|
||||
|
||||
var sunAtmosphere = GameObject.Instantiate(GameObject.Find("Sun_Body/Atmosphere_SUN"), sunGO.transform);
|
||||
var sunAtmosphere = GameObject.Instantiate(GameObject.Find("Sun_Body/Atmosphere_SUN"), starGO.transform);
|
||||
sunAtmosphere.transform.localPosition = Vector3.zero;
|
||||
sunAtmosphere.transform.localScale = Vector3.one;
|
||||
sunAtmosphere.name = "Atmosphere_Star";
|
||||
|
||||
var ambientLightGO = GameObject.Instantiate(GameObject.Find("Sun_Body/AmbientLight_SUN"), sunGO.transform);
|
||||
var ambientLightGO = GameObject.Instantiate(GameObject.Find("Sun_Body/AmbientLight_SUN"), starGO.transform);
|
||||
ambientLightGO.transform.localPosition = Vector3.zero;
|
||||
ambientLightGO.name = "AmbientLight_Star";
|
||||
|
||||
var heatVolume = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Volumes_SUN/HeatVolume"), sunGO.transform);
|
||||
var heatVolume = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Volumes_SUN/HeatVolume"), starGO.transform);
|
||||
heatVolume.transform.localPosition = Vector3.zero;
|
||||
heatVolume.transform.localScale = Vector3.one;
|
||||
heatVolume.GetComponent<SphereShape>().radius = 1f;
|
||||
heatVolume.name = "HeatVolume";
|
||||
|
||||
var deathVolume = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Volumes_SUN/ScaledVolumesRoot/DestructionFluidVolume"), sunGO.transform);
|
||||
var deathVolume = GameObject.Instantiate(GameObject.Find("Sun_Body/Sector_SUN/Volumes_SUN/ScaledVolumesRoot/DestructionFluidVolume"), starGO.transform);
|
||||
deathVolume.transform.localPosition = Vector3.zero;
|
||||
deathVolume.transform.localScale = Vector3.one;
|
||||
deathVolume.GetComponent<SphereCollider>().radius = 1f;
|
||||
deathVolume.name = "DestructionVolume";
|
||||
|
||||
|
||||
|
||||
PlanetaryFogController fog = sunAtmosphere.transform.Find("FogSphere").GetComponent<PlanetaryFogController>();
|
||||
TessellatedSphereRenderer surface = sunSurface.GetComponent<TessellatedSphereRenderer>();
|
||||
Light ambientLight = ambientLightGO.GetComponent<Light>();
|
||||
|
||||
//GameObject.Destroy(sunLight.GetComponent<FaceActiveCamera>());
|
||||
//GameObject.Destroy(sunLight.GetComponent<CSMTextureCacher>());
|
||||
//GameObject.Destroy(sunLight.GetComponent<ProxyShadowLight>());
|
||||
//SunLightController sunLightController = sunLight.GetComponent<SunLightController>();
|
||||
//GameObject.Destroy(sunLight.GetComponent<SunLightParamUpdater>());
|
||||
//GameObject.Destroy(sunLightController);
|
||||
Color lightColour = light.color;
|
||||
if (starModule.LightTint != null) lightColour = starModule.LightTint.ToColor32();
|
||||
if (lightColour == null && starModule.Tint != null)
|
||||
{
|
||||
// Lighten it a bit
|
||||
var r = Mathf.Clamp01(starModule.Tint.R * 1.5f / 255f);
|
||||
var g = Mathf.Clamp01(starModule.Tint.G * 1.5f / 255f);
|
||||
var b = Mathf.Clamp01(starModule.Tint.B * 1.5f / 255f);
|
||||
lightColour = new Color(r, g, b);
|
||||
}
|
||||
if (lightColour != null) light.color = (Color)lightColour;
|
||||
|
||||
light.color = lightColour;
|
||||
ambientLight.color = lightColour;
|
||||
|
||||
fog.fogRadius = starModule.Size * 1.2f;
|
||||
if(starModule.Tint != null)
|
||||
{
|
||||
var colour = starModule.Tint.ToColor32();
|
||||
//sunLightController.sunColor = colour;
|
||||
//ambientLight.color = colour;
|
||||
fog.fogTint = colour;
|
||||
|
||||
var sun = GameObject.Find("Sun_Body");
|
||||
@ -94,8 +113,9 @@ namespace NewHorizons.Builder.Body
|
||||
var giantMaterial = sun.GetComponent<SunController>().GetValue<Material>("_endSurfaceMaterial");
|
||||
|
||||
surface.sharedMaterial = new Material(starModule.Size >= 3000 ? giantMaterial : mainSequenceMaterial);
|
||||
surface.sharedMaterial.color = new Color(colour.r * 8f / 255f, colour.g * 8f / 255f, colour.b * 8f / 255f);
|
||||
surface.sharedMaterial.SetTexture("_ColorRamp", Utility.ImageUtilities.TintImage(_colorOverTime, colour));
|
||||
var mod = 8f * starModule.SolarLuminosity / 255f;
|
||||
surface.sharedMaterial.color = new Color(colour.r * mod, colour.g * mod, colour.b * mod);
|
||||
surface.sharedMaterial.SetTexture("_ColorRamp", ImageUtilities.TintImage(_colorOverTime, colour));
|
||||
|
||||
sunAtmosphere.transform.Find("AtmoSphere").transform.localScale = Vector3.one * (starModule.Size + 1000)/starModule.Size;
|
||||
foreach (var lod in sunAtmosphere.transform.Find("AtmoSphere").GetComponentsInChildren<MeshRenderer>())
|
||||
@ -109,8 +129,19 @@ namespace NewHorizons.Builder.Body
|
||||
if(starModule.SolarFlareTint != null)
|
||||
solarFlareEmitter.GetComponent<SolarFlareEmitter>().tint = starModule.SolarFlareTint.ToColor32();
|
||||
|
||||
sunGO.transform.localPosition = Vector3.zero;
|
||||
sunGO.transform.localScale = starModule.Size * Vector3.one;
|
||||
starGO.transform.localPosition = Vector3.zero;
|
||||
starGO.transform.localScale = starModule.Size * Vector3.one;
|
||||
|
||||
var starController = body.AddComponent<StarController>();
|
||||
starController.Light = light;
|
||||
starController.AmbientLight = ambientLight;
|
||||
starController.FaceActiveCamera = faceActiveCamera;
|
||||
starController.CSMTextureCacher = csmTextureCacher;
|
||||
starController.ProxyShadowLight = proxyShadowLight;
|
||||
starController.Intensity = starModule.SolarLuminosity;
|
||||
starController.SunColor = lightColour;
|
||||
|
||||
return starController;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
using NewHorizons.External;
|
||||
using NewHorizons.Utility;
|
||||
using OWML.Utils;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using UnityEngine;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
@ -8,8 +10,15 @@ namespace NewHorizons.Builder.General
|
||||
{
|
||||
static class GravityBuilder
|
||||
{
|
||||
public static GravityVolume Make(GameObject body, AstroObject ao, float surfaceAccel, float sphereOfInfluence, float surface, string falloffType)
|
||||
public static GravityVolume Make(GameObject body, AstroObject ao, IPlanetConfig config)
|
||||
{
|
||||
var exponent = config.Base.GravityFallOff.Equals("linear") ? 1f : 2f;
|
||||
var GM = config.Base.SurfaceGravity * Mathf.Pow(config.Base.SurfaceSize, exponent);
|
||||
|
||||
// Gravity limit will be when the acceleration it would cause is less than 0.1 m/s^2
|
||||
var gravityRadius = GM / 0.1f;
|
||||
if (exponent == 2f) gravityRadius = Mathf.Sqrt(gravityRadius);
|
||||
|
||||
GameObject gravityGO = new GameObject("GravityWell");
|
||||
gravityGO.transform.parent = body.transform;
|
||||
gravityGO.transform.localPosition = Vector3.zero;
|
||||
@ -18,7 +27,7 @@ namespace NewHorizons.Builder.General
|
||||
|
||||
SphereCollider SC = gravityGO.AddComponent<SphereCollider>();
|
||||
SC.isTrigger = true;
|
||||
SC.radius = sphereOfInfluence;
|
||||
SC.radius = gravityRadius;
|
||||
|
||||
OWCollider OWC = gravityGO.AddComponent<OWCollider>();
|
||||
OWC.SetLODActivationMask(DynamicOccupant.Player);
|
||||
@ -27,14 +36,20 @@ namespace NewHorizons.Builder.General
|
||||
|
||||
GravityVolume GV = gravityGO.AddComponent<GravityVolume>();
|
||||
GV.SetValue("_cutoffAcceleration", 0.1f);
|
||||
GV.SetValue("_falloffType", GV.GetType().GetNestedType("FalloffType", BindingFlags.NonPublic).GetField(falloffType).GetValue(GV));
|
||||
GV.SetValue("_alignmentRadius", 1.5f * surface);
|
||||
GV.SetValue("_upperSurfaceRadius", surface);
|
||||
|
||||
GravityVolume.FalloffType falloff = GravityVolume.FalloffType.linear;
|
||||
if (config.Base.GravityFallOff.ToUpper().Equals("LINEAR")) falloff = GravityVolume.FalloffType.linear;
|
||||
else if (config.Base.GravityFallOff.ToUpper().Equals("INVERSESQUARED")) falloff = GravityVolume.FalloffType.inverseSquared;
|
||||
else Logger.LogError($"Couldn't set gravity type {config.Base.GravityFallOff}. Must be either \"linear\" or \"inverseSquared\". Defaulting to linear.");
|
||||
GV._falloffType = falloff;
|
||||
|
||||
GV.SetValue("_alignmentRadius", config.Base.SurfaceGravity != 0 ? 1.5f * config.Base.SurfaceSize : 0f);
|
||||
GV.SetValue("_upperSurfaceRadius", config.Base.SurfaceSize);
|
||||
GV.SetValue("_lowerSurfaceRadius", 0);
|
||||
GV.SetValue("_layer", 3);
|
||||
GV.SetValue("_priority", 0);
|
||||
GV.SetValue("_alignmentPriority", 0);
|
||||
GV.SetValue("_surfaceAcceleration", surfaceAccel);
|
||||
GV.SetValue("_surfaceAcceleration", config.Base.SurfaceGravity);
|
||||
GV.SetValue("_inheritable", false);
|
||||
GV.SetValue("_isPlanetGravityVolume", true);
|
||||
GV.SetValue("_cutoffRadius", 0f);
|
||||
|
||||
@ -49,17 +49,17 @@ namespace NewHorizons.Builder.General
|
||||
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.CaveTwin || ao.GetAstroObjectName() == AstroObject.Name.TowerTwin)
|
||||
{
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.TowerTwin)
|
||||
GameObject.Find("TimeLoopRing_Body").SetActive(false);
|
||||
var focalBody = GameObject.Find("FocalBody");
|
||||
if (focalBody != null) focalBody.SetActive(false);
|
||||
}
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.MapSatellite)
|
||||
else 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)
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.ProbeCannon)
|
||||
{
|
||||
GameObject.Find("NomaiProbe_Body").SetActive(false);
|
||||
GameObject.Find("CannonMuzzle_Body").SetActive(false);
|
||||
@ -68,11 +68,11 @@ namespace NewHorizons.Builder.General
|
||||
GameObject.Find("FakeCannonBarrel_Body (1)").SetActive(false);
|
||||
GameObject.Find("Debris_Body (1)").SetActive(false);
|
||||
}
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.SunStation)
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.SunStation)
|
||||
{
|
||||
GameObject.Find("SS_Debris_Body").SetActive(false);
|
||||
}
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.GiantsDeep)
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.GiantsDeep)
|
||||
{
|
||||
GameObject.Find("BrambleIsland_Body").SetActive(false);
|
||||
GameObject.Find("GabbroIsland_Body").SetActive(false);
|
||||
@ -80,15 +80,41 @@ namespace NewHorizons.Builder.General
|
||||
GameObject.Find("StatueIsland_Body").SetActive(false);
|
||||
GameObject.Find("ConstructionYardIsland_Body").SetActive(false);
|
||||
}
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.WhiteHole)
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.WhiteHole)
|
||||
{
|
||||
GameObject.Find("WhiteholeStation_Body").SetActive(false);
|
||||
GameObject.Find("WhiteholeStationSuperstructure_Body").SetActive(false);
|
||||
}
|
||||
if (ao.GetAstroObjectName() == AstroObject.Name.TimberHearth)
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.TimberHearth)
|
||||
{
|
||||
GameObject.Find("MiningRig_Body").SetActive(false);
|
||||
}
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.Sun)
|
||||
{
|
||||
var starController = ao.gameObject.GetComponent<StarController>();
|
||||
Main.Instance.StarLightController.RemoveStar(starController);
|
||||
GameObject.Destroy(starController);
|
||||
|
||||
var audio = ao.GetComponentInChildren<SunSurfaceAudioController>();
|
||||
GameObject.Destroy(audio);
|
||||
|
||||
foreach(var owAudioSource in ao.GetComponentsInChildren<OWAudioSource>())
|
||||
{
|
||||
owAudioSource.Stop();
|
||||
GameObject.Destroy(owAudioSource);
|
||||
}
|
||||
|
||||
foreach (var audioSource in ao.GetComponentsInChildren<AudioSource>())
|
||||
{
|
||||
audioSource.Stop();
|
||||
GameObject.Destroy(audioSource);
|
||||
}
|
||||
}
|
||||
else if(ao.GetAstroObjectName() == AstroObject.Name.DreamWorld)
|
||||
{
|
||||
GameObject.Find("BackRaft_Body").SetActive(false);
|
||||
GameObject.Find("SealRaft_Body").SetActive(false);
|
||||
}
|
||||
|
||||
// Deal with proxies
|
||||
foreach (var p in GameObject.FindObjectsOfType<ProxyOrbiter>())
|
||||
|
||||
@ -8,24 +8,40 @@ using UnityEngine;
|
||||
using Random = UnityEngine.Random;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
using System.Reflection;
|
||||
using NewHorizons.Utility;
|
||||
|
||||
namespace NewHorizons.Builder.Props
|
||||
{
|
||||
public static class PropBuilder
|
||||
{
|
||||
public static void Make(GameObject body, string propToClone, Vector3 position, Sector sector)
|
||||
public static void Make(GameObject go, Sector sector, IPlanetConfig config)
|
||||
{
|
||||
var prefab = GameObject.Find(propToClone);
|
||||
Make(body, prefab, position, sector);
|
||||
if (config.Props.Scatter != null) PropBuilder.Scatter(go, config.Props.Scatter, config.Base.SurfaceSize, sector);
|
||||
if(config.Props.Details != null)
|
||||
{
|
||||
foreach(var detail in config.Props.Details)
|
||||
{
|
||||
MakeDetail(go, sector, detail.path, detail.position, detail.rotation, detail.scale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Make(GameObject body, GameObject prefab, Vector3 position, Sector sector)
|
||||
public static GameObject MakeDetail(GameObject go, Sector sector, string propToClone, MVector3 position, MVector3 rotation, float scale)
|
||||
{
|
||||
if (prefab == null) return;
|
||||
var prefab = GameObject.Find(propToClone);
|
||||
return MakeDetail(go, sector, prefab, position, rotation, scale);
|
||||
}
|
||||
|
||||
public static GameObject MakeDetail(GameObject go, Sector sector, GameObject prefab, MVector3 position, MVector3 rotation, float scale, bool alignWithNormal = false)
|
||||
{
|
||||
if (prefab == null) return null;
|
||||
|
||||
GameObject prop = GameObject.Instantiate(prefab, sector.transform);
|
||||
prop.transform.localPosition = position;
|
||||
prop.transform.rotation = Quaternion.FromToRotation(prop.transform.TransformDirection(Vector3.up), position.normalized);
|
||||
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>();
|
||||
@ -43,7 +59,6 @@ namespace NewHorizons.Builder.Props
|
||||
sector.OnOccupantEnterSector += ((SectorDetector sd) => StreamingManager.LoadStreamingAssets(assetBundle));
|
||||
}
|
||||
|
||||
/*
|
||||
foreach(var component in prop.GetComponentsInChildren<Component>())
|
||||
{
|
||||
try
|
||||
@ -61,40 +76,30 @@ namespace NewHorizons.Builder.Props
|
||||
Logger.Log($"Found a _sector field in {component}");
|
||||
sectorField.SetValue(component, sector);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(component is Campfire)
|
||||
{
|
||||
Logger.Log("CAMPFIRE");
|
||||
Campfire campfire = component as Campfire;
|
||||
if (campfire._sector != null)
|
||||
campfire._sector.OnSectorOccupantsUpdated -= campfire.OnSectorOccupantsUpdated;
|
||||
|
||||
campfire._sector = sector;
|
||||
campfire._sector.OnSectorOccupantsUpdated += campfire.OnSectorOccupantsUpdated;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) { Logger.Log($"{e.Message}, {e.StackTrace}"); }
|
||||
}
|
||||
*/
|
||||
|
||||
prop.SetActive(true);
|
||||
|
||||
return prop;
|
||||
}
|
||||
|
||||
public static void Scatter(GameObject body, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector)
|
||||
private static void Scatter(GameObject go, PropModule.ScatterInfo[] scatterInfo, float radius, Sector sector)
|
||||
{
|
||||
var area = 4f * Mathf.PI * radius * radius;
|
||||
var points = FibonacciSphere((int)area);
|
||||
|
||||
foreach (var scatterer in scatterInfo)
|
||||
foreach (var propInfo in scatterInfo)
|
||||
{
|
||||
var prefab = GameObject.Find(scatterer.path);
|
||||
for(int i = 0; i < scatterer.count; i++)
|
||||
var 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];
|
||||
Make(body, prefab, point.normalized * radius, sector);
|
||||
var prop = MakeDetail(go, sector, prefab, (MVector3)(point.normalized * radius), null, 0f, 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);
|
||||
if (points.Count == 0) return;
|
||||
}
|
||||
|
||||
188
NewHorizons/Builder/Props/SignalBuilder.cs
Normal file
188
NewHorizons/Builder/Props/SignalBuilder.cs
Normal file
@ -0,0 +1,188 @@
|
||||
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.Props
|
||||
{
|
||||
public static class SignalBuilder
|
||||
{
|
||||
private static AnimationCurve _customCurve = null;
|
||||
|
||||
private static Dictionary<SignalName, string> _customSignalNames;
|
||||
private static Stack<SignalName> _availableSignalNames;
|
||||
|
||||
public static Dictionary<SignalFrequency, string> SignalFrequencyOverrides;
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
_customSignalNames = new Dictionary<SignalName, string>();
|
||||
_availableSignalNames = new Stack<SignalName> (new SignalName[]
|
||||
{
|
||||
(SignalName)17,
|
||||
(SignalName)18,
|
||||
(SignalName)19,
|
||||
(SignalName)26,
|
||||
(SignalName)27,
|
||||
(SignalName)28,
|
||||
(SignalName)29,
|
||||
(SignalName)33,
|
||||
(SignalName)34,
|
||||
(SignalName)35,
|
||||
(SignalName)36,
|
||||
(SignalName)37,
|
||||
(SignalName)38,
|
||||
(SignalName)39,
|
||||
(SignalName)50,
|
||||
(SignalName)51,
|
||||
(SignalName)52,
|
||||
(SignalName)53,
|
||||
(SignalName)54,
|
||||
(SignalName)55,
|
||||
(SignalName)56,
|
||||
(SignalName)57,
|
||||
(SignalName)58,
|
||||
(SignalName)59,
|
||||
SignalName.WhiteHole_WH,
|
||||
SignalName.WhiteHole_SS_Receiver,
|
||||
SignalName.WhiteHole_CT_Receiver,
|
||||
SignalName.WhiteHole_CT_Experiment,
|
||||
SignalName.WhiteHole_TT_Receiver,
|
||||
SignalName.WhiteHole_TT_TimeLoopCore,
|
||||
SignalName.WhiteHole_TH_Receiver,
|
||||
SignalName.WhiteHole_BH_NorthPoleReceiver,
|
||||
SignalName.WhiteHole_BH_ForgeReceiver,
|
||||
SignalName.WhiteHole_GD_Receiver,
|
||||
});
|
||||
SignalFrequencyOverrides = new Dictionary<SignalFrequency, string>() {
|
||||
{ SignalFrequency.Statue, "NOMAI STATUE" },
|
||||
{ SignalFrequency.Default, "???" },
|
||||
{ SignalFrequency.WarpCore, "ANTI-GRAVITON FLUX" }
|
||||
};
|
||||
}
|
||||
|
||||
public static SignalName AddSignalName(string str)
|
||||
{
|
||||
if (_availableSignalNames.Count == 0)
|
||||
{
|
||||
Logger.LogWarning($"There are no more available SignalName spots. Cannot use name [{str}].");
|
||||
return SignalName.Default;
|
||||
}
|
||||
|
||||
Logger.Log($"Registering new signal name [{str}]");
|
||||
var newName = _availableSignalNames.Pop();
|
||||
_customSignalNames.Add(newName, str.ToUpper());
|
||||
return newName;
|
||||
}
|
||||
|
||||
public static string GetCustomSignalName(SignalName signalName)
|
||||
{
|
||||
string name = null;
|
||||
_customSignalNames.TryGetValue(signalName, out name);
|
||||
return name;
|
||||
}
|
||||
|
||||
public static void Make(GameObject body, Sector sector, SignalModule module)
|
||||
{
|
||||
foreach(var info in module.Signals)
|
||||
{
|
||||
Make(body, sector, info);
|
||||
}
|
||||
}
|
||||
|
||||
public static void Make(GameObject body, Sector sector, SignalModule.SignalInfo info)
|
||||
{
|
||||
var signalGO = new GameObject($"Signal_{info.Name}");
|
||||
signalGO.SetActive(false);
|
||||
signalGO.transform.parent = body.transform;
|
||||
signalGO.transform.localPosition = info.Position != null ? (Vector3)info.Position : Vector3.zero;
|
||||
signalGO.layer = LayerMask.NameToLayer("AdvancedEffectVolume");
|
||||
|
||||
var source = signalGO.AddComponent<AudioSource>();
|
||||
var owAudioSource = signalGO.AddComponent<OWAudioSource>();
|
||||
|
||||
AudioSignal audioSignal = null;
|
||||
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;
|
||||
|
||||
audioSignal.SetSector(sector);
|
||||
audioSignal._frequency = frequency;
|
||||
if (name == SignalName.Default)
|
||||
{
|
||||
name = AddSignalName(info.Name);
|
||||
if(name == SignalName.Default) audioSignal._preventIdentification = true;
|
||||
}
|
||||
audioSignal._name = name;
|
||||
audioSignal._sourceRadius = info.SourceRadius;
|
||||
audioSignal._onlyAudibleToScope = info.OnlyAudibleToScope;
|
||||
audioSignal._identificationDistance = info.IdentificationRadius;
|
||||
|
||||
source.clip = clip;
|
||||
source.loop = true;
|
||||
source.minDistance = 0;
|
||||
source.maxDistance = 30;
|
||||
source.velocityUpdateMode = AudioVelocityUpdateMode.Fixed;
|
||||
source.rolloffMode = AudioRolloffMode.Custom;
|
||||
|
||||
if(_customCurve == null)
|
||||
_customCurve = GameObject.Find("Moon_Body/Sector_THM/Characters_THM/Villager_HEA_Esker/Signal_Whistling").GetComponent<AudioSource>().GetCustomCurve(AudioSourceCurveType.CustomRolloff);
|
||||
|
||||
source.SetCustomCurve(AudioSourceCurveType.CustomRolloff, _customCurve);
|
||||
source.playOnAwake = false;
|
||||
source.spatialBlend = 1f;
|
||||
source.volume = 0.5f;
|
||||
source.dopplerLevel = 0;
|
||||
|
||||
owAudioSource.SetTrack(OWAudioMixer.TrackName.Signal);
|
||||
|
||||
// Frequency detection trigger volume
|
||||
|
||||
var signalDetectionGO = new GameObject($"SignalDetectionTrigger_{info.Name}");
|
||||
signalDetectionGO.SetActive(false);
|
||||
signalDetectionGO.transform.parent = body.transform;
|
||||
signalDetectionGO.transform.localPosition = info.Position != null ? (Vector3)info.Position : Vector3.zero;
|
||||
signalDetectionGO.layer = LayerMask.NameToLayer("AdvancedEffectVolume");
|
||||
|
||||
var sphereShape = signalDetectionGO.AddComponent<SphereShape>();
|
||||
var owTriggerVolume = signalDetectionGO.AddComponent<OWTriggerVolume>();
|
||||
var audioSignalDetectionTrigger = signalDetectionGO.AddComponent<AudioSignalDetectionTrigger>();
|
||||
|
||||
sphereShape.radius = info.DetectionRadius == 0 ? info.SourceRadius + 30 : info.DetectionRadius;
|
||||
audioSignalDetectionTrigger._signal = audioSignal;
|
||||
audioSignalDetectionTrigger._trigger = owTriggerVolume;
|
||||
|
||||
signalGO.SetActive(true);
|
||||
signalDetectionGO.SetActive(true);
|
||||
}
|
||||
|
||||
private static SignalFrequency StringToFrequency(string str)
|
||||
{
|
||||
foreach(SignalFrequency freq in Enum.GetValues(typeof(SignalFrequency)))
|
||||
{
|
||||
if (str.Equals(freq.ToString())) return freq;
|
||||
}
|
||||
return SignalFrequency.Default;
|
||||
}
|
||||
|
||||
private static SignalName StringToSignalName(string str)
|
||||
{
|
||||
foreach (SignalName name in Enum.GetValues(typeof(SignalName)))
|
||||
{
|
||||
if (str.Equals(name.ToString())) return name;
|
||||
}
|
||||
return SignalName.Default;
|
||||
}
|
||||
}
|
||||
}
|
||||
78
NewHorizons/Components/CloakedAudioSignal.cs
Normal file
78
NewHorizons/Components/CloakedAudioSignal.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Components
|
||||
{
|
||||
public class CloakedAudioSignal : AudioSignal
|
||||
{
|
||||
public new void UpdateSignalStrength(Signalscope scope, float distToClosestScopeObstruction)
|
||||
{
|
||||
this._canBePickedUpByScope = false;
|
||||
if (!PlayerState.InCloakingField())
|
||||
{
|
||||
this._signalStrength = 0f;
|
||||
this._degreesFromScope = 180f;
|
||||
return;
|
||||
}
|
||||
if (this._sunController != null && this._sunController.IsPointInsideSupernova(base.transform.position))
|
||||
{
|
||||
this._signalStrength = 0f;
|
||||
this._degreesFromScope = 180f;
|
||||
return;
|
||||
}
|
||||
if (Locator.GetQuantumMoon() != null && Locator.GetQuantumMoon().IsPlayerInside() && this._name != SignalName.Quantum_QM)
|
||||
{
|
||||
this._signalStrength = 0f;
|
||||
this._degreesFromScope = 180f;
|
||||
return;
|
||||
}
|
||||
if (!this._active || !base.gameObject.activeInHierarchy || this._outerFogWarpVolume != PlayerState.GetOuterFogWarpVolume() || (scope.GetFrequencyFilter() & this._frequency) != this._frequency)
|
||||
{
|
||||
this._signalStrength = 0f;
|
||||
this._degreesFromScope = 180f;
|
||||
return;
|
||||
}
|
||||
this._scopeToSignal = base.transform.position - scope.transform.position;
|
||||
this._distToScope = this._scopeToSignal.magnitude;
|
||||
if (this._outerFogWarpVolume == null && distToClosestScopeObstruction < 1000f && this._distToScope > 1000f)
|
||||
{
|
||||
this._signalStrength = 0f;
|
||||
this._degreesFromScope = 180f;
|
||||
return;
|
||||
}
|
||||
this._canBePickedUpByScope = true;
|
||||
if (this._distToScope < this._sourceRadius)
|
||||
{
|
||||
this._signalStrength = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
this._degreesFromScope = Vector3.Angle(scope.GetScopeDirection(), this._scopeToSignal);
|
||||
float t = Mathf.InverseLerp(2000f, 1000f, this._distToScope);
|
||||
float a = Mathf.Lerp(45f, 90f, t);
|
||||
float a2 = 57.29578f * Mathf.Atan2(this._sourceRadius, this._distToScope);
|
||||
float b = Mathf.Lerp(Mathf.Max(a2, 5f), Mathf.Max(a2, 1f), scope.GetZoomFraction());
|
||||
this._signalStrength = Mathf.Clamp01(Mathf.InverseLerp(a, b, this._degreesFromScope));
|
||||
}
|
||||
if (this._distToScope < this._identificationDistance + this._sourceRadius && this._signalStrength > 0.9f)
|
||||
{
|
||||
if (!PlayerData.KnowsFrequency(this._frequency) && !this._preventIdentification)
|
||||
{
|
||||
this.IdentifyFrequency();
|
||||
}
|
||||
if (!PlayerData.KnowsSignal(this._name) && !this._preventIdentification)
|
||||
{
|
||||
this.IdentifySignal();
|
||||
}
|
||||
if (this._revealFactID.Length > 0)
|
||||
{
|
||||
Locator.GetShipLogManager().RevealFact(this._revealFactID, true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
1
NewHorizons/External/AtmosphereModule.cs
vendored
1
NewHorizons/External/AtmosphereModule.cs
vendored
@ -21,5 +21,6 @@ namespace NewHorizons.External
|
||||
public bool HasSnow { get; set; }
|
||||
public bool HasOxygen { get; set; }
|
||||
public bool HasAtmosphere { get; set; }
|
||||
public MColor32 AtmosphereTint { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
1
NewHorizons/External/IPlanetConfig.cs
vendored
1
NewHorizons/External/IPlanetConfig.cs
vendored
@ -18,5 +18,6 @@ namespace NewHorizons.External
|
||||
FocalPointModule FocalPoint { get; }
|
||||
PropModule Props { get; }
|
||||
SpawnModule Spawn { get; }
|
||||
SignalModule Signal { get; }
|
||||
}
|
||||
}
|
||||
|
||||
123
NewHorizons/External/NewHorizonsData.cs
vendored
Normal file
123
NewHorizons/External/NewHorizonsData.cs
vendored
Normal file
@ -0,0 +1,123 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Logger = NewHorizons.Utility.Logger;
|
||||
|
||||
namespace NewHorizons.External
|
||||
{
|
||||
public static class NewHorizonsData
|
||||
{
|
||||
private static NewHorizonsSaveFile _saveFile;
|
||||
private static NewHorizonsProfile _activeProfile;
|
||||
private static string _activeProfileName;
|
||||
private static string _fileName = "save.json";
|
||||
|
||||
public static void Load()
|
||||
{
|
||||
_activeProfileName = StandaloneProfileManager.SharedInstance.currentProfile.profileName;
|
||||
try
|
||||
{
|
||||
_saveFile = Main.Instance.ModHelper.Storage.Load<NewHorizonsSaveFile>(_fileName);
|
||||
if (!_saveFile.Profiles.ContainsKey(_activeProfileName)) _saveFile.Profiles.Add(_activeProfileName, new NewHorizonsProfile());
|
||||
_activeProfile = _saveFile.Profiles[_activeProfileName];
|
||||
Logger.Log($"Loaded save data for {_activeProfileName}");
|
||||
}
|
||||
catch(Exception)
|
||||
{
|
||||
try
|
||||
{
|
||||
Logger.Log($"Couldn't load save data from {_fileName}, creating a new file");
|
||||
_saveFile = new NewHorizonsSaveFile();
|
||||
_saveFile.Profiles.Add(_activeProfileName, new NewHorizonsProfile());
|
||||
_activeProfile = _saveFile.Profiles[_activeProfileName];
|
||||
Main.Instance.ModHelper.Storage.Save(_saveFile, _fileName);
|
||||
Logger.Log($"Loaded save data for {_activeProfileName}");
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
Logger.LogError($"Couldn't create save data {e.Message}, {e.StackTrace}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void Save()
|
||||
{
|
||||
if (_saveFile == null) return;
|
||||
Main.Instance.ModHelper.Storage.Save(_saveFile, _fileName);
|
||||
}
|
||||
|
||||
public static void Reset()
|
||||
{
|
||||
if (_saveFile == null || _activeProfile == null)
|
||||
{
|
||||
Load();
|
||||
}
|
||||
Logger.Log($"Reseting save data for {_activeProfileName}");
|
||||
_activeProfile = new NewHorizonsProfile();
|
||||
_saveFile.Profiles[_activeProfileName] = _activeProfile;
|
||||
|
||||
Save();
|
||||
}
|
||||
|
||||
public static bool KnowsFrequency(string frequency)
|
||||
{
|
||||
if (_activeProfile == null) return true;
|
||||
return _activeProfile.KnownFrequencies.Contains(frequency);
|
||||
}
|
||||
|
||||
public static void LearnFrequency(string frequency)
|
||||
{
|
||||
if (_activeProfile == null) return;
|
||||
if (!KnowsFrequency(frequency))
|
||||
{
|
||||
_activeProfile.KnownFrequencies.Add(frequency);
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool KnowsSignal(string signal)
|
||||
{
|
||||
if (_activeProfile == null) return true;
|
||||
return _activeProfile.KnownSignals.Contains(signal);
|
||||
}
|
||||
|
||||
public static void LearnSignal(string signal)
|
||||
{
|
||||
if (_activeProfile == null) return;
|
||||
if (!KnowsSignal(signal))
|
||||
{
|
||||
_activeProfile.KnownSignals.Add(signal);
|
||||
Save();
|
||||
}
|
||||
}
|
||||
|
||||
public static bool KnowsMultipleFrequencies()
|
||||
{
|
||||
return (_activeProfile != null && _activeProfile.KnownFrequencies.Count > 0);
|
||||
}
|
||||
|
||||
private class NewHorizonsSaveFile
|
||||
{
|
||||
public NewHorizonsSaveFile()
|
||||
{
|
||||
Profiles = new Dictionary<string, NewHorizonsProfile>();
|
||||
}
|
||||
|
||||
public Dictionary<string, NewHorizonsProfile> Profiles { get; set; }
|
||||
}
|
||||
|
||||
private class NewHorizonsProfile
|
||||
{
|
||||
public NewHorizonsProfile()
|
||||
{
|
||||
KnownFrequencies = new List<string>();
|
||||
KnownSignals = new List<string>();
|
||||
}
|
||||
|
||||
public List<string> KnownFrequencies { get; set; }
|
||||
public List<string> KnownSignals { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
1
NewHorizons/External/PlanetConfig.cs
vendored
1
NewHorizons/External/PlanetConfig.cs
vendored
@ -22,6 +22,7 @@ namespace NewHorizons.External
|
||||
public FocalPointModule FocalPoint { get; set; }
|
||||
public PropModule Props { get; set; }
|
||||
public SpawnModule Spawn { get; set; }
|
||||
public SignalModule Signal { get; set; }
|
||||
|
||||
public PlanetConfig(Dictionary<string, object> dict)
|
||||
{
|
||||
|
||||
11
NewHorizons/External/PropModule.cs
vendored
11
NewHorizons/External/PropModule.cs
vendored
@ -10,12 +10,23 @@ namespace NewHorizons.External
|
||||
public class PropModule : Module
|
||||
{
|
||||
public ScatterInfo[] Scatter;
|
||||
public DetailInfo[] Details;
|
||||
public MVector3[] Rafts;
|
||||
|
||||
public class ScatterInfo
|
||||
{
|
||||
public string path;
|
||||
public int count;
|
||||
public MVector3 offset;
|
||||
public MVector3 rotation;
|
||||
}
|
||||
|
||||
public class DetailInfo
|
||||
{
|
||||
public string path;
|
||||
public MVector3 position;
|
||||
public MVector3 rotation;
|
||||
public float scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
27
NewHorizons/External/SignalModule.cs
vendored
Normal file
27
NewHorizons/External/SignalModule.cs
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
using NewHorizons.Utility;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace NewHorizons.External
|
||||
{
|
||||
public class SignalModule : Module
|
||||
{
|
||||
public SignalInfo[] Signals;
|
||||
|
||||
public class SignalInfo
|
||||
{
|
||||
public MVector3 Position;
|
||||
public string Frequency;
|
||||
public string Name;
|
||||
public string AudioClip;
|
||||
public float SourceRadius = 1f;
|
||||
public float DetectionRadius = 0f;
|
||||
public float IdentificationRadius = 10f;
|
||||
public bool OnlyAudibleToScope = true;
|
||||
public bool InsideCloak = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
6
NewHorizons/External/StarModule.cs
vendored
6
NewHorizons/External/StarModule.cs
vendored
@ -9,10 +9,10 @@ namespace NewHorizons.External
|
||||
{
|
||||
public class StarModule : Module
|
||||
{
|
||||
public float Size { get; set; }
|
||||
public MColor32 Tint { get; set; }
|
||||
public float Size { get; set; } = 2000f;
|
||||
public MColor32 Tint { get; set; }
|
||||
public MColor32 SolarFlareTint { get; set; }
|
||||
public MColor32 LightTint { get; set; }
|
||||
public float SolarLuminosity { get; set; }
|
||||
public float SolarLuminosity { get; set; } = 1f;
|
||||
}
|
||||
}
|
||||
|
||||
@ -30,7 +30,9 @@ namespace NewHorizons
|
||||
public static List<NewHorizonsBody> BodyList = new List<NewHorizonsBody>();
|
||||
public static List<NewHorizonsBody> NextPassBodies = new List<NewHorizonsBody>();
|
||||
|
||||
public static float FurthestOrbit = 50000f;
|
||||
public static float FurthestOrbit { get; set; } = 50000f;
|
||||
|
||||
public StarLightController StarLightController { get; private set; }
|
||||
|
||||
public override object GetApi()
|
||||
{
|
||||
@ -51,7 +53,7 @@ namespace NewHorizons
|
||||
{
|
||||
LoadConfigs(this);
|
||||
}
|
||||
catch(Exception)
|
||||
catch (Exception)
|
||||
{
|
||||
Logger.LogWarning("Couldn't find planets folder");
|
||||
}
|
||||
@ -66,29 +68,65 @@ namespace NewHorizons
|
||||
void OnSceneLoaded(Scene scene, LoadSceneMode mode)
|
||||
{
|
||||
Logger.Log($"Scene Loaded: {scene.name} {mode}");
|
||||
|
||||
HeavenlyBodyBuilder.Reset();
|
||||
|
||||
if (scene.name != "SolarSystem") { return; }
|
||||
|
||||
NewHorizonsData.Load();
|
||||
|
||||
// Need to manage this when there are multiple stars
|
||||
var sun = GameObject.Find("Sun_Body");
|
||||
var starController = sun.AddComponent<StarController>();
|
||||
starController.Light = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<Light>();
|
||||
starController.AmbientLight = GameObject.Find("Sun_Body/AmbientLight_SUN").GetComponent<Light>();
|
||||
starController.FaceActiveCamera = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<FaceActiveCamera>();
|
||||
starController.CSMTextureCacher = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<CSMTextureCacher>();
|
||||
starController.ProxyShadowLight = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<ProxyShadowLight>();
|
||||
starController.Intensity = 0.9859f;
|
||||
starController.SunColor = new Color(1f, 0.8845f, 0.6677f, 1f);
|
||||
|
||||
var starLightGO = GameObject.Instantiate(sun.GetComponentInChildren<SunLightController>().gameObject);
|
||||
foreach(var comp in starLightGO.GetComponents<Component>())
|
||||
{
|
||||
if(!(comp is SunLightController) && !(comp is SunLightParamUpdater) && !(comp is Light) && !(comp is Transform))
|
||||
{
|
||||
GameObject.Destroy(comp);
|
||||
}
|
||||
}
|
||||
GameObject.Destroy(starLightGO.GetComponent<Light>());
|
||||
starLightGO.name = "StarLightController";
|
||||
|
||||
StarLightController = starLightGO.AddComponent<StarLightController>();
|
||||
StarLightController.AddStar(starController);
|
||||
|
||||
starLightGO.SetActive(true);
|
||||
|
||||
// TODO: Make this configurable probably
|
||||
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => Locator.GetPlayerBody().gameObject.AddComponent<DebugRaycaster>());
|
||||
|
||||
// Some builders need to be reset each time
|
||||
SignalBuilder.Reset();
|
||||
|
||||
// We do our own AstroObject tracking
|
||||
AstroObjectLocator.RefreshList();
|
||||
foreach(AstroObject ao in GameObject.FindObjectsOfType<AstroObject>())
|
||||
foreach (AstroObject ao in GameObject.FindObjectsOfType<AstroObject>())
|
||||
{
|
||||
AstroObjectLocator.AddAstroObject(ao);
|
||||
}
|
||||
|
||||
// Stars then planets then moons
|
||||
var toLoad = BodyList.OrderBy(b =>
|
||||
(b.Config.BuildPriority != -1 ? b.Config.BuildPriority :
|
||||
(b.Config.FocalPoint != null ? 0 :
|
||||
// Stars then planets then moons (not necessary but probably speeds things up, maybe)
|
||||
var toLoad = BodyList.OrderBy(b =>
|
||||
(b.Config.BuildPriority != -1 ? b.Config.BuildPriority :
|
||||
(b.Config.FocalPoint != null ? 0 :
|
||||
(b.Config.Star != null) ? 0 :
|
||||
(b.Config.Orbit.IsMoon ? 2 : 1)
|
||||
))).ToList();
|
||||
|
||||
var count = 0;
|
||||
while(toLoad.Count != 0)
|
||||
var passCount = 0;
|
||||
while (toLoad.Count != 0)
|
||||
{
|
||||
Logger.Log($"Starting body loading pass #{++count}");
|
||||
Logger.Log($"Starting body loading pass #{++passCount}");
|
||||
var flagNoneLoadedThisPass = true;
|
||||
foreach (var body in toLoad)
|
||||
{
|
||||
@ -98,7 +136,7 @@ namespace NewHorizons
|
||||
{
|
||||
Logger.LogWarning("No objects were loaded this pass");
|
||||
// Try again but default to sun
|
||||
foreach(var body in toLoad)
|
||||
foreach (var body in toLoad)
|
||||
{
|
||||
if (LoadBody(body, true)) flagNoneLoadedThisPass = false;
|
||||
}
|
||||
@ -114,7 +152,7 @@ namespace NewHorizons
|
||||
NextPassBodies = new List<NewHorizonsBody>();
|
||||
|
||||
// Infinite loop failsafe
|
||||
if (count > 10)
|
||||
if (passCount > 10)
|
||||
{
|
||||
Logger.Log("Something went wrong");
|
||||
break;
|
||||
@ -125,6 +163,15 @@ namespace NewHorizons
|
||||
|
||||
// I don't know what these do but they look really weird from a distance
|
||||
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => PlanetDestroyer.RemoveDistantProxyClones());
|
||||
|
||||
var map = GameObject.FindObjectOfType<MapController>();
|
||||
if (map != null) map._maxPanDistance = FurthestOrbit * 1.5f;
|
||||
/*
|
||||
foreach(var cam in GameObject.FindObjectsOfType<OWCamera>())
|
||||
{
|
||||
cam.farClipPlane = FurthestOrbit * 3f;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
private bool LoadBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
|
||||
@ -136,15 +183,15 @@ namespace NewHorizons
|
||||
if (stringID.Equals("EMBER_TWIN")) stringID = "CAVE_TWIN";
|
||||
if (stringID.Equals("INTERLOPER")) stringID = "COMET";
|
||||
|
||||
AstroObject existingPlanet = null;
|
||||
GameObject existingPlanet = null;
|
||||
try
|
||||
{
|
||||
existingPlanet = AstroObjectLocator.GetAstroObject(stringID);
|
||||
if (existingPlanet == null) existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.Name.Replace(" ", ""));
|
||||
existingPlanet = AstroObjectLocator.GetAstroObject(stringID).gameObject;
|
||||
if (existingPlanet == null) existingPlanet = AstroObjectLocator.GetAstroObject(body.Config.Name.Replace(" ", "")).gameObject;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogWarning($"Error when looking for {body.Config.Name}: {e.Message}, {e.StackTrace}");
|
||||
existingPlanet = GameObject.Find(body.Config.Name.Replace(" ", "") + "_Body");
|
||||
}
|
||||
|
||||
if (existingPlanet != null)
|
||||
@ -153,7 +200,9 @@ namespace NewHorizons
|
||||
{
|
||||
if (body.Config.Destroy)
|
||||
{
|
||||
Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveBody(existingPlanet), 2);
|
||||
var ao = existingPlanet.GetComponent<AstroObject>();
|
||||
if (ao != null) Instance.ModHelper.Events.Unity.FireInNUpdates(() => PlanetDestroyer.RemoveBody(ao), 2);
|
||||
else Instance.ModHelper.Events.Unity.FireInNUpdates(() => existingPlanet.SetActive(false), 2);
|
||||
}
|
||||
else UpdateBody(body, existingPlanet);
|
||||
}
|
||||
@ -180,7 +229,6 @@ namespace NewHorizons
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
public void LoadConfigs(IModBehaviour mod)
|
||||
{
|
||||
var folder = mod.ModHelper.Manifest.ModFolderPath;
|
||||
@ -199,23 +247,21 @@ namespace NewHorizons
|
||||
}
|
||||
}
|
||||
|
||||
public static GameObject UpdateBody(NewHorizonsBody body, AstroObject ao)
|
||||
public GameObject UpdateBody(NewHorizonsBody body, GameObject go)
|
||||
{
|
||||
Logger.Log($"Updating existing AstroObject {ao}");
|
||||
|
||||
var go = ao.gameObject;
|
||||
Logger.Log($"Updating existing Object {go.name}");
|
||||
|
||||
var sector = go.GetComponentInChildren<Sector>();
|
||||
var rb = go.GetAttachedOWRigidbody();
|
||||
|
||||
// Do stuff that's shared between generating new planets and updating old ones
|
||||
return SharedGenerateBody(body, go, sector, rb, ao);
|
||||
return SharedGenerateBody(body, go, sector, rb);
|
||||
}
|
||||
|
||||
public static GameObject GenerateBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
|
||||
public GameObject GenerateBody(NewHorizonsBody body, bool defaultPrimaryToSun = false)
|
||||
{
|
||||
AstroObject primaryBody;
|
||||
if(body.Config.Orbit.PrimaryBody != null)
|
||||
if (body.Config.Orbit.PrimaryBody != null)
|
||||
{
|
||||
primaryBody = AstroObjectLocator.GetAstroObject(body.Config.Orbit.PrimaryBody);
|
||||
if (primaryBody == null)
|
||||
@ -242,7 +288,7 @@ namespace NewHorizons
|
||||
var go = new GameObject(body.Config.Name.Replace(" ", "").Replace("'", "") + "_Body");
|
||||
go.SetActive(false);
|
||||
|
||||
if(body.Config.Base.GroundSize != 0) GeometryBuilder.Make(go, body.Config.Base.GroundSize);
|
||||
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);
|
||||
@ -253,9 +299,9 @@ namespace NewHorizons
|
||||
|
||||
GravityVolume gv = null;
|
||||
if (body.Config.Base.SurfaceGravity != 0)
|
||||
gv = GravityBuilder.Make(go, ao, body.Config.Base.SurfaceGravity, sphereOfInfluence * (body.Config.Star != null ? 10f : 1f), body.Config.Base.SurfaceSize, body.Config.Base.GravityFallOff);
|
||||
|
||||
if(body.Config.Base.HasReferenceFrame)
|
||||
gv = GravityBuilder.Make(go, ao, body.Config);
|
||||
|
||||
if (body.Config.Base.HasReferenceFrame)
|
||||
RFVolumeBuilder.Make(go, owRigidBody, sphereOfInfluence);
|
||||
|
||||
if (body.Config.Base.HasMapMarker)
|
||||
@ -278,20 +324,18 @@ namespace NewHorizons
|
||||
if (body.Config.Base.BlackHoleSize != 0)
|
||||
BlackHoleBuilder.Make(go, body.Config.Base, sector);
|
||||
|
||||
if (body.Config.Star != null)
|
||||
StarBuilder.Make(go, sector, body.Config.Star);
|
||||
if (body.Config.Star != null) StarLightController.AddStar(StarBuilder.Make(go, sector, body.Config.Star));
|
||||
|
||||
if (body.Config.FocalPoint != null)
|
||||
FocalPointBuilder.Make(go, body.Config.FocalPoint);
|
||||
|
||||
// Do stuff that's shared between generating new planets and updating old ones
|
||||
go = SharedGenerateBody(body, go, sector, owRigidBody, ao);
|
||||
go = SharedGenerateBody(body, go, sector, owRigidBody);
|
||||
|
||||
body.Object = go;
|
||||
|
||||
// Now that we're done move the planet into place
|
||||
go.transform.parent = Locator.GetRootTransform();
|
||||
|
||||
go.transform.position = OrbitalHelper.GetCartesian(new OrbitalHelper.Gravity(1, 100), body.Config.Orbit).Item1 + (primaryBody == null ? Vector3.zero : primaryBody.transform.position);
|
||||
|
||||
if (go.transform.position.magnitude > FurthestOrbit)
|
||||
@ -319,7 +363,7 @@ namespace NewHorizons
|
||||
return go;
|
||||
}
|
||||
|
||||
private static GameObject SharedGenerateBody(NewHorizonsBody body, GameObject go, Sector sector, OWRigidbody rb, AstroObject ao)
|
||||
private GameObject SharedGenerateBody(NewHorizonsBody body, GameObject go, Sector sector, OWRigidbody rb)
|
||||
{
|
||||
if (body.Config.Ring != null)
|
||||
RingBuilder.Make(go, body.Config.Ring, body.Assets);
|
||||
@ -329,14 +373,11 @@ namespace NewHorizons
|
||||
|
||||
if (body.Config.Base.HasCometTail)
|
||||
CometTailBuilder.Make(go, body.Config.Base, go.GetComponent<AstroObject>().GetPrimaryBody());
|
||||
|
||||
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.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)
|
||||
{
|
||||
@ -354,22 +395,14 @@ namespace NewHorizons
|
||||
if (body.Config.Atmosphere.FogSize != 0)
|
||||
FogBuilder.Make(go, sector, body.Config.Atmosphere);
|
||||
|
||||
AtmosphereBuilder.Make(go, body.Config.Atmosphere);
|
||||
AtmosphereBuilder.Make(go, body.Config.Atmosphere, body.Config.Base.SurfaceSize);
|
||||
}
|
||||
|
||||
if (body.Config.Props != null)
|
||||
{
|
||||
if (body.Config.Props.Scatter != null) PropBuilder.Scatter(go, body.Config.Props.Scatter, body.Config.Base.SurfaceSize, sector);
|
||||
/*
|
||||
if (body.Config.Props.Rafts != null)
|
||||
{
|
||||
foreach(var v in body.Config.Props.Rafts)
|
||||
{
|
||||
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => RaftBuilder.Make(go, v, sector, rb, ao));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
PropBuilder.Make(go, sector, body.Config);
|
||||
|
||||
if (body.Config.Signal != null)
|
||||
SignalBuilder.Make(go, sector, body.Config.Signal);
|
||||
|
||||
return go;
|
||||
}
|
||||
|
||||
@ -7,12 +7,12 @@ using UnityEngine;
|
||||
|
||||
namespace NewHorizons.OrbitalPhysics
|
||||
{
|
||||
public class TrackingOrbitLine : OrbitLine
|
||||
{
|
||||
public class TrackingOrbitLine : OrbitLine
|
||||
{
|
||||
private Vector3[] _vertices;
|
||||
private float _timer;
|
||||
private bool _firstTimeEnabled = true;
|
||||
|
||||
|
||||
public float TrailTime = 120f;
|
||||
|
||||
|
||||
@ -44,7 +44,7 @@ namespace NewHorizons.OrbitalPhysics
|
||||
|
||||
public override void OnEnterMapView()
|
||||
{
|
||||
if (_firstTimeEnabled)
|
||||
if (_firstTimeEnabled)
|
||||
{
|
||||
ResetLineVertices();
|
||||
_firstTimeEnabled = false;
|
||||
@ -65,8 +65,8 @@ namespace NewHorizons.OrbitalPhysics
|
||||
_timer += Time.deltaTime;
|
||||
var updateTime = (TrailTime / (float)_numVerts);
|
||||
|
||||
if(_timer > updateTime)
|
||||
{
|
||||
if (_timer > updateTime)
|
||||
{
|
||||
for (int i = _numVerts - 1; i > 0; i--)
|
||||
{
|
||||
var v = _vertices[i - 1];
|
||||
@ -95,12 +95,12 @@ namespace NewHorizons.OrbitalPhysics
|
||||
var dist1 = Vector3.Distance(point, _vertices[0]);
|
||||
var dist2 = Vector3.Distance(point, _vertices[(int)(_numVerts / 2)]);
|
||||
var dist3 = Vector3.Distance(point, _vertices[_numVerts - 1]);
|
||||
|
||||
|
||||
return Mathf.Min(new float[] { dist1, dist2, dist3 });
|
||||
}
|
||||
|
||||
public void ResetLineVertices()
|
||||
{
|
||||
{
|
||||
var primary = _astroObject.GetPrimaryBody();
|
||||
Vector3 origin = primary == null ? Locator.GetRootTransform().position : primary.transform.position;
|
||||
|
||||
@ -114,4 +114,4 @@ namespace NewHorizons.OrbitalPhysics
|
||||
_lineRenderer.SetPositions(_vertices);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,7 +29,8 @@ namespace NewHorizons.Utility
|
||||
var direction = Locator.GetActiveCamera().transform.TransformDirection(Vector3.forward);
|
||||
if (Physics.Raycast(origin, direction, out RaycastHit hitInfo, 100f, layerMask))
|
||||
{
|
||||
Logger.Log($"Raycast hit [{hitInfo.transform.InverseTransformPoint(hitInfo.point)}] on [{hitInfo.transform.gameObject.name}]");
|
||||
var pos = hitInfo.transform.InverseTransformPoint(hitInfo.point);
|
||||
Logger.Log($"Raycast hit {{\"x\": {pos.x}, \"y\": {pos.y}, \"z\": {pos.z}}} on [{hitInfo.transform.gameObject.name}]");
|
||||
}
|
||||
_rb.EnableCollisionDetection();
|
||||
}
|
||||
|
||||
@ -90,7 +90,14 @@ namespace NewHorizons.Utility
|
||||
continue;
|
||||
}
|
||||
|
||||
targetProperty.SetValue(destination, srcProp.GetValue(source, null), null);
|
||||
try
|
||||
{
|
||||
targetProperty.SetValue(destination, srcProp.GetValue(source, null), null);
|
||||
} catch(Exception)
|
||||
{
|
||||
Logger.LogWarning($"Couldn't copy property {targetProperty.Name} from {source} to {destination}");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
using OWML.Common;
|
||||
using NewHorizons.Builder.Props;
|
||||
using NewHorizons.Components;
|
||||
using NewHorizons.External;
|
||||
using OWML.Common;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@ -12,9 +15,35 @@ namespace NewHorizons.Utility
|
||||
{
|
||||
public static void Apply()
|
||||
{
|
||||
// Prefixes
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<ReferenceFrame>("GetHUDDisplayName", typeof(Patches), nameof(Patches.GetHUDDisplayName));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<PlayerState>("CheckShipOutsideSolarSystem", typeof(Patches), nameof(Patches.CheckShipOutersideSolarSystem));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix<EllipticOrbitLine>("Start", typeof(Patches), nameof(Patches.OnEllipticOrbitLineStart));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<SunLightParamUpdater>("LateUpdate", typeof(Patches), nameof(Patches.OnSunLightParamUpdaterLateUpdate));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<SunSurfaceAudioController>("Update", typeof(Patches), nameof(Patches.OnSunSurfaceAudioControllerUpdate));
|
||||
|
||||
// Lot of audio signal stuff
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<AudioSignal>("SignalNameToString", typeof(Patches), nameof(Patches.OnAudioSignalSignalNameToString));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<AudioSignal>("IndexToFrequency", typeof(Patches), nameof(Patches.OnAudioSignalIndexToFrequency));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<AudioSignal>("FrequencyToIndex", typeof(Patches), nameof(Patches.OnAudioSignalFrequencyToIndex));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<AudioSignal>("FrequencyToString", typeof(Patches), nameof(Patches.OnAudioSignalFrequencyToString));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<Signalscope>("Awake", typeof(Patches), nameof(Patches.OnSignalscopeAwake));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<Signalscope>("SwitchFrequencyFilter", typeof(Patches), nameof(Patches.OnSignalscopeSwitchFrequencyFilter));
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix<AudioSignal>("UpdateSignalStrength", typeof(Patches), nameof(Patches.OnAudioSignalUpdateSignalStrength));
|
||||
|
||||
var playerDataKnowsSignal = typeof(PlayerData).GetMethod("KnowsSignal");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataKnowsSignal, typeof(Patches), nameof(Patches.OnPlayerDataKnowsSignal));
|
||||
var playerDataLearnSignal = typeof(PlayerData).GetMethod("LearnSignal");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataLearnSignal, typeof(Patches), nameof(Patches.OnPlayerDataLearnSignal));
|
||||
var playerDataKnowsFrequency = typeof(PlayerData).GetMethod("KnowsFrequency");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataKnowsFrequency, typeof(Patches), nameof(Patches.OnPlayerDataKnowsFrequency));
|
||||
var playerDataLearnFrequency = typeof(PlayerData).GetMethod("LearnFrequency");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataLearnFrequency, typeof(Patches), nameof(Patches.OnPlayerDataLearnFrequency));
|
||||
var playerDataKnowsMultipleFrequencies = typeof(PlayerData).GetMethod("KnowsMultipleFrequencies");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPrefix(playerDataKnowsMultipleFrequencies, typeof(Patches), nameof(Patches.OnPlayerDataKnowsMultipleFrequencies));
|
||||
var playerDataResetGame = typeof(PlayerData).GetMethod("ResetGame");
|
||||
Main.Instance.ModHelper.HarmonyHelper.AddPostfix(playerDataResetGame, typeof(Patches), nameof(Patches.OnPlayerDataResetGame));
|
||||
|
||||
// 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));
|
||||
}
|
||||
@ -30,31 +59,252 @@ namespace NewHorizons.Utility
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool CheckShipOutersideSolarSystem(PlayerState __instance, bool __result)
|
||||
public static bool CheckShipOutersideSolarSystem(PlayerState __instance, ref bool __result)
|
||||
{
|
||||
__result = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void OnEllipticOrbitLineStart(EllipticOrbitLine __instance, ref Vector3 ____upAxisDir, AstroObject ____astroObject)
|
||||
{
|
||||
if (____astroObject.GetAstroObjectName() == AstroObject.Name.Comet) return;
|
||||
|
||||
// For some reason other planets do this idk
|
||||
____upAxisDir *= -1f;
|
||||
}
|
||||
|
||||
public static void OnMapControllerAwake(MapController __instance, ref float ____maxPanDistance, ref float ____maxZoomDistance, ref float ____minPitchAngle, ref float ____zoomSpeed)
|
||||
{
|
||||
____maxPanDistance *= 4f;
|
||||
____maxPanDistance = Main.FurthestOrbit * 1.5f;
|
||||
____maxZoomDistance *= 6f;
|
||||
____minPitchAngle = -90f;
|
||||
____zoomSpeed *= 4f;
|
||||
__instance._mapCamera.farClipPlane = Main.FurthestOrbit * 3f;
|
||||
}
|
||||
|
||||
public static void OnOWCameraAwake(OWCamera __instance)
|
||||
{
|
||||
__instance.farClipPlane *= 4f;
|
||||
}
|
||||
|
||||
public static bool OnSunLightParamUpdaterLateUpdate(SunLightParamUpdater __instance)
|
||||
{
|
||||
if (__instance.sunLight)
|
||||
{
|
||||
Vector3 position = __instance.transform.position;
|
||||
float w = 2000f;
|
||||
if (__instance._sunController != null)
|
||||
{
|
||||
w = (__instance._sunController.HasSupernovaStarted() ? __instance._sunController.GetSupernovaRadius() : __instance._sunController.GetSurfaceRadius());
|
||||
}
|
||||
float range = __instance.sunLight.range;
|
||||
Color color = (__instance._sunLightController != null) ? __instance._sunLightController.sunColor : __instance.sunLight.color;
|
||||
float w2 = (__instance._sunLightController != null) ? __instance._sunLightController.sunIntensity : __instance.sunLight.intensity;
|
||||
Shader.SetGlobalVector(__instance._propID_SunPosition, new Vector4(position.x, position.y, position.z, w));
|
||||
Shader.SetGlobalVector(__instance._propID_OWSunPositionRange, new Vector4(position.x, position.y, position.z, 1f / (range * range)));
|
||||
Shader.SetGlobalVector(__instance._propID_OWSunColorIntensity, new Vector4(color.r, color.g, color.b, w2));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool OnSunSurfaceAudioControllerUpdate(SunSurfaceAudioController __instance)
|
||||
{
|
||||
if (__instance._sunController != null) return true;
|
||||
|
||||
var surfaceRadius = __instance.transform.parent.parent.localScale.magnitude;
|
||||
float value = Mathf.Max(0f, Vector3.Distance(Locator.GetPlayerCamera().transform.position, __instance.transform.position) - surfaceRadius);
|
||||
float num = Mathf.InverseLerp(1600f, 100f, value);
|
||||
__instance._audioSource.SetLocalVolume(num * num * __instance._fade);
|
||||
return false;
|
||||
}
|
||||
|
||||
#region AudioSignal
|
||||
|
||||
public static bool OnAudioSignalSignalNameToString(SignalName __0, ref string __result)
|
||||
{
|
||||
var customSignalName = SignalBuilder.GetCustomSignalName(__0);
|
||||
if (customSignalName == null) return true;
|
||||
else
|
||||
{
|
||||
__result = customSignalName;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool OnAudioSignalIndexToFrequency(int __0, ref SignalFrequency __result) {
|
||||
switch (__0)
|
||||
{
|
||||
case 1:
|
||||
__result = SignalFrequency.Traveler;
|
||||
break;
|
||||
case 2:
|
||||
__result = SignalFrequency.Quantum;
|
||||
break;
|
||||
case 3:
|
||||
__result = SignalFrequency.EscapePod;
|
||||
break;
|
||||
case 4:
|
||||
__result = SignalFrequency.WarpCore;
|
||||
break;
|
||||
case 5:
|
||||
__result = SignalFrequency.HideAndSeek;
|
||||
break;
|
||||
case 6:
|
||||
__result = SignalFrequency.Radio;
|
||||
break;
|
||||
case 7:
|
||||
__result = SignalFrequency.Statue;
|
||||
break;
|
||||
default:
|
||||
__result = SignalFrequency.Default;
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool OnAudioSignalFrequencyToIndex(SignalFrequency __0, ref int __result)
|
||||
{
|
||||
var frequency = __0;
|
||||
if (frequency <= SignalFrequency.EscapePod)
|
||||
{
|
||||
if(frequency == SignalFrequency.Default)
|
||||
{
|
||||
__result = 0;
|
||||
}
|
||||
else if (frequency == SignalFrequency.Traveler)
|
||||
{
|
||||
__result = 1;
|
||||
}
|
||||
else if (frequency == SignalFrequency.Quantum)
|
||||
{
|
||||
__result = 2;
|
||||
}
|
||||
else if (frequency == SignalFrequency.EscapePod)
|
||||
{
|
||||
__result = 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (frequency == SignalFrequency.WarpCore)
|
||||
{
|
||||
__result = 4;
|
||||
}
|
||||
else if (frequency == SignalFrequency.HideAndSeek)
|
||||
{
|
||||
__result = 5;
|
||||
}
|
||||
else if (frequency == SignalFrequency.Radio)
|
||||
{
|
||||
__result = 6;
|
||||
}
|
||||
else if (frequency == SignalFrequency.Statue)
|
||||
{
|
||||
__result = 7;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool OnAudioSignalFrequencyToString(SignalFrequency __0, ref string __result)
|
||||
{
|
||||
SignalBuilder.SignalFrequencyOverrides.TryGetValue(__0, out string customName);
|
||||
if (customName != null)
|
||||
{
|
||||
if (NewHorizonsData.KnowsFrequency(customName)) __result = customName;
|
||||
else __result = UITextLibrary.GetString(UITextType.SignalFreqUnidentified);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnAudioSignalUpdateSignalStrength(AudioSignal __instance, Signalscope __0, float __1)
|
||||
{
|
||||
// I hate this
|
||||
if(__instance is CloakedAudioSignal)
|
||||
{
|
||||
((CloakedAudioSignal)__instance).UpdateSignalStrength(__0, __1);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Signalscope
|
||||
public static bool OnSignalscopeAwake(Signalscope __instance, ref AudioSignal[] ____strongestSignals)
|
||||
{
|
||||
____strongestSignals = new AudioSignal[8];
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnSignalscopeSwitchFrequencyFilter(Signalscope __instance, int __0)
|
||||
{
|
||||
var increment = __0;
|
||||
var count = Enum.GetValues(typeof(SignalFrequency)).Length;
|
||||
__instance._frequencyFilterIndex += increment;
|
||||
__instance._frequencyFilterIndex = ((__instance._frequencyFilterIndex >= count) ? 0 : __instance._frequencyFilterIndex);
|
||||
__instance._frequencyFilterIndex = ((__instance._frequencyFilterIndex < 0) ? count - 1 : __instance._frequencyFilterIndex);
|
||||
SignalFrequency signalFrequency = AudioSignal.IndexToFrequency(__instance._frequencyFilterIndex);
|
||||
if (!PlayerData.KnowsFrequency(signalFrequency) && (!__instance._isUnknownFreqNearby || __instance._unknownFrequency != signalFrequency))
|
||||
{
|
||||
__instance.SwitchFrequencyFilter(increment);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region PlayerData
|
||||
public static bool OnPlayerDataKnowsFrequency(SignalFrequency __0, ref bool __result)
|
||||
{
|
||||
SignalBuilder.SignalFrequencyOverrides.TryGetValue(__0, out string freqString);
|
||||
if (freqString != null)
|
||||
{
|
||||
__result = NewHorizonsData.KnowsFrequency(freqString);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnPlayerDataLearnFrequency(SignalFrequency __0)
|
||||
{
|
||||
SignalBuilder.SignalFrequencyOverrides.TryGetValue(__0, out string freqString);
|
||||
if (freqString != null)
|
||||
{
|
||||
NewHorizonsData.LearnFrequency(freqString);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnPlayerDataKnowsSignal(SignalName __0, ref bool __result)
|
||||
{
|
||||
var customSignalName = SignalBuilder.GetCustomSignalName(__0);
|
||||
if (customSignalName != null)
|
||||
{
|
||||
__result = NewHorizonsData.KnowsSignal(customSignalName);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnPlayerDataLearnSignal(SignalName __0)
|
||||
{
|
||||
var customSignalName = SignalBuilder.GetCustomSignalName(__0);
|
||||
if (customSignalName != null)
|
||||
{
|
||||
if (!NewHorizonsData.KnowsSignal(customSignalName)) NewHorizonsData.LearnSignal(customSignalName);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool OnPlayerDataKnowsMultipleFrequencies(ref bool __result)
|
||||
{
|
||||
if (NewHorizonsData.KnowsMultipleFrequencies())
|
||||
{
|
||||
__result = true;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public static void OnPlayerDataResetGame()
|
||||
{
|
||||
NewHorizonsData.Reset();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
60
NewHorizons/Utility/SearchUtilities.cs
Normal file
60
NewHorizons/Utility/SearchUtilities.cs
Normal file
@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace NewHorizons.Utility
|
||||
{
|
||||
public static class SearchUtilities
|
||||
{
|
||||
public static List<T> FindObjectsOfTypeAndName<T>(string name) where T : MonoBehaviour
|
||||
{
|
||||
T[] firstList = GameObject.FindObjectsOfType<T>();
|
||||
List<T> finalList = new List<T>();
|
||||
|
||||
for (var i = 0; i < firstList.Length; i++)
|
||||
{
|
||||
if (firstList[i].name == name)
|
||||
{
|
||||
finalList.Add(firstList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return finalList;
|
||||
}
|
||||
|
||||
public static List<T> FindResourcesOfTypeAndName<T>(string name) where T : Object
|
||||
{
|
||||
T[] firstList = Resources.FindObjectsOfTypeAll<T>();
|
||||
List<T> finalList = new List<T>();
|
||||
|
||||
for (var i = 0; i < firstList.Length; i++)
|
||||
{
|
||||
if (firstList[i].name == name)
|
||||
{
|
||||
finalList.Add(firstList[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return finalList;
|
||||
}
|
||||
|
||||
public static T FindResourceOfTypeAndName<T>(string name) where T : Object
|
||||
{
|
||||
T[] firstList = Resources.FindObjectsOfTypeAll<T>();
|
||||
|
||||
for (var i = 0; i < firstList.Length; i++)
|
||||
{
|
||||
if (firstList[i].name == name)
|
||||
{
|
||||
return firstList[i];
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
39
NewHorizons/Utility/StarController.cs
Normal file
39
NewHorizons/Utility/StarController.cs
Normal file
@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
|
||||
namespace NewHorizons.Utility
|
||||
{
|
||||
public class StarController : MonoBehaviour
|
||||
{
|
||||
public Light Light;
|
||||
public Light AmbientLight;
|
||||
public FaceActiveCamera FaceActiveCamera;
|
||||
public CSMTextureCacher CSMTextureCacher;
|
||||
public ProxyShadowLight ProxyShadowLight;
|
||||
public float Intensity;
|
||||
public Color SunColor;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
Disable();
|
||||
}
|
||||
|
||||
public void Disable()
|
||||
{
|
||||
if (FaceActiveCamera != null) FaceActiveCamera.enabled = false;
|
||||
if (CSMTextureCacher != null) CSMTextureCacher.enabled = false;
|
||||
if (ProxyShadowLight != null) ProxyShadowLight.enabled = false;
|
||||
}
|
||||
|
||||
public void Enable()
|
||||
{
|
||||
if (FaceActiveCamera != null) FaceActiveCamera.enabled = true;
|
||||
if (CSMTextureCacher != null) CSMTextureCacher.enabled = true;
|
||||
if (ProxyShadowLight != null) ProxyShadowLight.enabled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
102
NewHorizons/Utility/StarLightController.cs
Normal file
102
NewHorizons/Utility/StarLightController.cs
Normal file
@ -0,0 +1,102 @@
|
||||
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.Utility
|
||||
{
|
||||
[RequireComponent(typeof(SunLightController))]
|
||||
[RequireComponent(typeof(SunLightParamUpdater))]
|
||||
public class StarLightController : MonoBehaviour
|
||||
{
|
||||
private List<StarController> _stars = new List<StarController>();
|
||||
private StarController _activeStar;
|
||||
|
||||
private SunLightController _sunLightController;
|
||||
private SunLightParamUpdater _sunLightParamUpdater;
|
||||
|
||||
public void Awake()
|
||||
{
|
||||
_sunLightController = GetComponent<SunLightController>();
|
||||
_sunLightController.enabled = true;
|
||||
_sunLightParamUpdater = GetComponent<SunLightParamUpdater>();
|
||||
_sunLightParamUpdater._sunLightController = _sunLightController;
|
||||
}
|
||||
|
||||
public void AddStar(StarController star)
|
||||
{
|
||||
Logger.Log($"Adding new star to list: {star.gameObject.name}");
|
||||
_stars.Add(star);
|
||||
}
|
||||
|
||||
public void RemoveStar(StarController star)
|
||||
{
|
||||
if (_stars.Contains(star))
|
||||
{
|
||||
if (_activeStar.Equals(star)) _activeStar = null;
|
||||
_stars.Remove(star);
|
||||
}
|
||||
}
|
||||
|
||||
public void Update()
|
||||
{
|
||||
if (_activeStar == null || !_activeStar.gameObject.activeInHierarchy)
|
||||
{
|
||||
if (_stars.Contains(_activeStar)) _stars.Remove(_activeStar);
|
||||
if (_stars.Count > 0) ChangeActiveStar(_stars[0]);
|
||||
else gameObject.SetActive(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
foreach(var star in _stars)
|
||||
{
|
||||
if (star == null) continue;
|
||||
|
||||
// Player is always at 0,0,0 more or less so if they arent using the map camera then wtv
|
||||
var origin = Vector3.zero;
|
||||
if (PlayerState.InMapView())
|
||||
{
|
||||
origin = Locator.GetActiveCamera().transform.position;
|
||||
}
|
||||
|
||||
if (star.Intensity * (star.transform.position - origin).sqrMagnitude < star.Intensity * (_activeStar.transform.position - origin).sqrMagnitude)
|
||||
{
|
||||
ChangeActiveStar(star);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ChangeActiveStar(StarController star)
|
||||
{
|
||||
if (_sunLightController == null || _sunLightParamUpdater == null) return;
|
||||
|
||||
if(_activeStar != null) _activeStar.Disable();
|
||||
|
||||
Logger.Log($"Switching active star: {star.gameObject.name}");
|
||||
|
||||
_activeStar = star;
|
||||
|
||||
star.Enable();
|
||||
|
||||
_sunLightController._sunBaseColor = star.SunColor;
|
||||
_sunLightController._sunBaseIntensity = star.Intensity;
|
||||
_sunLightController._sunLight = star.Light;
|
||||
_sunLightController._ambientLight = star.AmbientLight;
|
||||
|
||||
_sunLightParamUpdater.sunLight = star.Light;
|
||||
_sunLightParamUpdater._sunController = star.transform.GetComponent<SunController>();
|
||||
_sunLightParamUpdater._propID_SunPosition = Shader.PropertyToID("_SunPosition");
|
||||
_sunLightParamUpdater._propID_OWSunPositionRange = Shader.PropertyToID("_OWSunPositionRange");
|
||||
_sunLightParamUpdater._propID_OWSunColorIntensity = Shader.PropertyToID("_OWSunColorIntensity");
|
||||
|
||||
// For the param thing to work it wants this to be on the star idk
|
||||
this.transform.parent = star.transform;
|
||||
this.transform.localPosition = Vector3.zero;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3,7 +3,6 @@
|
||||
"author": "xen",
|
||||
"name": "New Horizons",
|
||||
"uniqueName": "xen.NewHorizons",
|
||||
"version": "0.2.0",
|
||||
"owmlVersion": "2.1.0",
|
||||
"dependencies": [ "PacificEngine.OW_CommonResources" ]
|
||||
"version": "0.3.1",
|
||||
"owmlVersion": "2.1.0"
|
||||
}
|
||||
|
||||
16
README.md
16
README.md
@ -24,19 +24,29 @@ Planets are created using a JSON file format structure, and placed in the `plane
|
||||
<!-- /TOC -->
|
||||
|
||||
## Roadmap
|
||||
- Heightmaps/texturemaps (Done)
|
||||
- Remove existing planets (Done)
|
||||
- Stars (Done)
|
||||
- Binary orbits (Done)
|
||||
- Comets (Done)
|
||||
- Signalscope signals (Done)
|
||||
- Asteroid belts (Done)
|
||||
- Procedurally terrain generation (started)
|
||||
- Asteroid belts (started, needs more customization)
|
||||
- "Quantum" orbits
|
||||
- Better terrain and water LOD
|
||||
- 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
|
||||
- Sand funnels (water? lava? star?)
|
||||
- Variable surface height (sand/water/lava/star)
|
||||
- Let any star go supernova
|
||||
- Geysers
|
||||
- Meteors
|
||||
|
||||
## How to create your own planets using configs
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user