## Major features
- Added support for `Extras` in your planet configs. This allows for
other mods to extend planet and system configs with new features.
- Added new volumes to configs under the `Volumes` module:
   - Hazard volumes
   - Notification volumes
- Implemented a transparent `cloudsPrefab`. It works mostly the same as
normal clouds except that it allows a transparent texture.

## Minor features
- Can now toggle atmospheric shock layers with `hasShockLayer`.
- Addons can now define `popupMessage` in their addon-manifest. This
will show a one time pop-up when the mod is first installed. Use this
for story mods to give the user a prompt to go in the right direction
with the mod. Means NH now requires [Menu
Framework](https://outerwildsmods.com/mods/menuframework/).
- `Ring` module now replaced with `Rings` module (can have multiple
rings per planet)
- Can override the far clip plane for a system from the star system
config (you're welcome Jammer)

## Improvements
- Various improvements for upcoming Quantum Space Buddies compatibility
mod.
- Made rain/snow heights more robust for larger planets.
- Improved Discord Rich Presence support (icons should show for more
addons)
- Proxies now have atmospheres and fog
- Ship log entry location marking now works in Bramble dimensions.
- If the user has an outdated version of Outer Wilds, a warning popup
will display.
- Adds disabling of renderers/colliders/shapes/lights when you're not at
the planet (can be disabled with `keepLoaded`).
- Allow ship log details to be added to vanilla planets
- Nomai shuttle landing radius is now properly set
- Added on screen button prompts when in debug mode
- Potentially fixes some threading issues when loading slides
- Improved scatter build time by not calling detail builder over and
over
- Added `preventOverlap` option to scatter. Is on by default but can be
disabled to increase performance. Useful when there is low change
anything will overlap (prop low density).
- Nomai remote cameras (projection pools) display the right camera
layers, and better show the protagonist. Uses
[CommonCameraUtility](https://github.com/xen-42/ow-common-camera-util)

## Bug fixes
- **Addons should now work properly on Linux**
- Only autosave debug mode configs if the save button is unlocked.
Prevents overwriting your configs unintentionally.
- Bramble dimensions will hide Bramble nodes inside then when you're
outside.
- Translation keys containing < or > or CDATA now work.
- Translated ship log facts no longer have the entry ID slapped in front
of them
- Fix a vanilla bug where being in a conversation and then getting
attached to something traps you in dialogue.
- Fixed a translation bug that affected Secret Worlds
- Does not fix the vision torch bug affecting "The Vision", but will at
least log an error when it happens now
- Fixed a translation bug where translations for NH itself weren't
reloaded when reloading configs
This commit is contained in:
Nick 2022-09-16 00:06:31 -04:00 committed by GitHub
commit b5d499b2dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
145 changed files with 3925 additions and 1142 deletions

5
.gitignore vendored
View File

@ -417,4 +417,9 @@ docs/.m_cache/**
# Unity project
new-horizons-unity
new-horizons-unity/**
nh-unity
nh-unity/**
NewHorizons/Assets/Assets
NewHorizons/Assets/Assets.manifest
docs/.env

View File

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"$schema": "https://raw.githubusercontent.com/outer-wilds-new-horizons/new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"DialogueDictionary": {
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_1": "Your ship is now equiped with a warp drive!",
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_2": "You can use the new \"Interstellar Mode\" page in the ship log to lock-on your autopilot to another star system.",
@ -14,7 +14,14 @@
"WARP_LOCKED": "AUTOPILOT LOCKED TO:\n{0}",
"LOCK_AUTOPILOT_WARP": "Lock Autopilot to Star System",
"RICH_PRESENCE_EXPLORING": "Exploring {0}.",
"RICH_PRESENCE_WARPING": "Warping to {0}."
"RICH_PRESENCE_WARPING": "Warping to {0}.",
"OUTDATED_VERSION_WARNING": "WARNING\n\nNew Horizons only works on version {0} or higher. You're on version {1}.\n\nPlease update your game or uninstall NH.",
"JSON_FAILED_TO_LOAD": "Invalid file(s): {0}",
"DEBUG_RAYCAST": "Raycast",
"DEBUG_PLACE": "Place Object",
"DEBUG_PLACE_TEXT": "Place Nomai Text",
"DEBUG_UNDO": "Undo",
"DEBUG_REDO": "Redo"
},
"AchievementTranslations": {
"NH_EATEN_OUTSIDE_BRAMBLE": {

View File

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"$schema": "https://raw.githubusercontent.com/outer-wilds-new-horizons/new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"DialogueDictionary": {
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_1": "Votre fusée est maintenant équipé d'un moteur de distorsion!",
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_2": "Vous pouvez utiliser la nouvelle page \"Mode Interstellaire\" dans le journal de bord pour diriger votre pilote automatique vers un autre système solaire",
@ -14,7 +14,9 @@
"WARP_LOCKED": "PILOTE AUTOMATIQUE VISÉ SUR:\n{0}",
"LOCK_AUTOPILOT_WARP": "Visez le pilote automatique",
"RICH_PRESENCE_EXPLORING": "En explorant {0}.",
"RICH_PRESENCE_WARPING": "En route vers {0}."
"RICH_PRESENCE_WARPING": "En route vers {0}.",
"OUTDATED_VERSION_WARNING": "AVERTISSEMENT\n\nNew Horizons fonctionne seulement sur la version {0} ou plus récente. Vous êtes sur la version {1}.\n\nVeuillez mettre à jour votre jeu ou désinstaller NH.",
"JSON_FAILED_TO_LOAD": "Fichier(s) invalide(s): {0}"
},
"AchievementTranslations": {
"NH_EATEN_OUTSIDE_BRAMBLE": {

View File

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"$schema": "https://raw.githubusercontent.com/outer-wilds-new-horizons/new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"DialogueDictionary": {
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_1": "Dein Schiff ist nun mit einem Warpantrieb ausgestattet!",
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_2": "Du kannst den neuen \"Interstellar Modus\" aus dem Schiffslogbuch auswählen um mit dem Autopilot in andere Sternensysteme zu reisen.",

View File

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"$schema": "https://raw.githubusercontent.com/outer-wilds-new-horizons/new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"DialogueDictionary": {
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_1": "Твой корабль теперь экипирован варп-двигателем!",
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_2": "Ты можешь использовать новый \"Режим Interstellar\" на своем корабле, что-бы закрепить автопилот на выбранную звёздную систему.",

View File

@ -1,5 +1,5 @@
{
"$schema": "https://raw.githubusercontent.com/xen-42/outer-wilds-new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"$schema": "https://raw.githubusercontent.com/outer-wilds-new-horizons/new-horizons/main/NewHorizons/Schemas/translation_schema.json",
"DialogueDictionary": {
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_1": "¡Tu nave ahora tiene un motor de curvatura!",
"NEW_HORIZONS_WARP_DRIVE_DIALOGUE_2": "Puedes usar la nueva página de \"modo interestelar\" en el registro de la nave para fijar el piloto automático a otro sistema solar.",

Binary file not shown.

View File

@ -0,0 +1,26 @@
ManifestFileVersion: 0
CRC: 2022446871
Hashes:
AssetFileHash:
serializedVersion: 2
Hash: 083882699617744b8fc49234bb8cb795
TypeTreeHash:
serializedVersion: 2
Hash: 10a6a558690295dadb3dd990eda0821a
HashAppended: 0
ClassTypes:
- Class: 21
Script: {instanceID: 0}
- Class: 48
Script: {instanceID: 0}
SerializeReferenceClassIdentifiers: []
Assets:
- Assets/Shaders/SphereTextureWrapper.shader
- Assets/Shaders/Ring.shader
- Assets/Shaders/SphereTextureWrapperNormal.shader
- Assets/Shaders/UnlitRing1Pixel.shader
- Assets/Shaders/UnlitTransparent.shader
- Assets/Resources/TransparentCloud.mat
- Assets/Shaders/StandardCullOFF.shader
- Assets/Shaders/Ring1Pixel.shader
Dependencies: []

View File

@ -23,28 +23,31 @@ namespace NewHorizons.Builder.Atmosphere
sfv._allowShipAutoroll = true;
sfv._disableOnStart = false;
// Try to parent it to the same as other rulesets to match vanilla but if its null put it on the root object
var ruleSetGO = planetGO.GetComponentInChildren<PlanetoidRuleset>()?.gameObject;
if (ruleSetGO == null) ruleSetGO = planetGO;
var shockLayerRuleset = ruleSetGO.AddComponent<ShockLayerRuleset>();
shockLayerRuleset._type = ShockLayerRuleset.ShockType.Atmospheric;
shockLayerRuleset._radialCenter = airGO.transform;
shockLayerRuleset._minShockSpeed = config.Atmosphere.minShockSpeed;
shockLayerRuleset._maxShockSpeed = config.Atmosphere.maxShockSpeed;
if (config.Atmosphere.clouds != null)
if (config.Atmosphere.hasShockLayer)
{
shockLayerRuleset._innerRadius = config.Atmosphere.clouds.innerCloudRadius;
shockLayerRuleset._outerRadius = config.Atmosphere.clouds.outerCloudRadius;
}
else
{
var bottom = config.Base.surfaceSize;
var top = config.Atmosphere.size;
// Try to parent it to the same as other rulesets to match vanilla but if its null put it on the root object
var ruleSetGO = planetGO.GetComponentInChildren<PlanetoidRuleset>()?.gameObject;
if (ruleSetGO == null) ruleSetGO = planetGO;
shockLayerRuleset._innerRadius = (bottom + top) / 2f;
shockLayerRuleset._outerRadius = top;
var shockLayerRuleset = ruleSetGO.AddComponent<ShockLayerRuleset>();
shockLayerRuleset._type = ShockLayerRuleset.ShockType.Atmospheric;
shockLayerRuleset._radialCenter = airGO.transform;
shockLayerRuleset._minShockSpeed = config.Atmosphere.minShockSpeed;
shockLayerRuleset._maxShockSpeed = config.Atmosphere.maxShockSpeed;
if (config.Atmosphere.clouds != null)
{
shockLayerRuleset._innerRadius = config.Atmosphere.clouds.innerCloudRadius;
shockLayerRuleset._outerRadius = config.Atmosphere.clouds.outerCloudRadius;
}
else
{
var bottom = config.Base.surfaceSize;
var top = config.Atmosphere.size;
shockLayerRuleset._innerRadius = (bottom + top) / 2f;
shockLayerRuleset._outerRadius = top;
}
}
if (config.Atmosphere.hasOxygen)

View File

@ -59,7 +59,7 @@ namespace NewHorizons.Builder.Atmosphere
}
}
material.SetFloat(InnerRadius, atmosphereModule.clouds != null ? atmosphereModule.size : surfaceSize);
material.SetFloat(InnerRadius, (atmosphereModule.clouds != null && atmosphereModule.clouds.cloudsPrefab != CloudPrefabType.Transparent) ? atmosphereModule.size : surfaceSize);
material.SetFloat(OuterRadius, atmosphereModule.size * 1.2f);
if (atmosphereModule.atmosphereTint != null) material.SetColor(SkyColor, atmosphereModule.atmosphereTint.ToColor());

View File

@ -9,9 +9,9 @@ namespace NewHorizons.Builder.Atmosphere
{
public static class CloudsBuilder
{
private static Shader _sphereShader = null;
private static Material[] _gdCloudMaterials;
private static Material[] _qmCloudMaterials;
private static Material _transparentCloud;
private static GameObject _lightningPrefab;
private static Texture2D _colorRamp;
private static readonly int Color = Shader.PropertyToID("_Color");
@ -19,6 +19,7 @@ namespace NewHorizons.Builder.Atmosphere
private static readonly int MainTex = Shader.PropertyToID("_MainTex");
private static readonly int RampTex = Shader.PropertyToID("_RampTex");
private static readonly int CapTex = Shader.PropertyToID("_CapTex");
private static readonly int Smoothness = Shader.PropertyToID("_Glossiness");
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo, bool cloaked, IModBehaviour mod)
{
@ -29,7 +30,15 @@ namespace NewHorizons.Builder.Atmosphere
cloudsMainGO.SetActive(false);
cloudsMainGO.transform.parent = sector?.transform ?? planetGO.transform;
MakeTopClouds(cloudsMainGO, atmo, mod);
if (atmo.clouds.cloudsPrefab != CloudPrefabType.Transparent) MakeTopClouds(cloudsMainGO, atmo, mod);
else
{
MakeTransparentClouds(cloudsMainGO, atmo, mod);
if (atmo.clouds.hasLightning) MakeLightning(cloudsMainGO, sector, atmo);
cloudsMainGO.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
cloudsMainGO.SetActive(true);
return;
}
GameObject cloudsBottomGO = new GameObject("BottomClouds");
cloudsBottomGO.SetActive(false);
@ -91,8 +100,6 @@ namespace NewHorizons.Builder.Atmosphere
// Fix the rotations once the rest is done
cloudsMainGO.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(0, 0, 0));
// For the base shader it has to be rotated idk
if (atmo.clouds.cloudsPrefab == CloudPrefabType.Basic) cloudsMainGO.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(90, 0, 0));
// Lightning
if (atmo.clouds.hasLightning)
@ -117,7 +124,7 @@ namespace NewHorizons.Builder.Atmosphere
lightning.transform.localPosition = Vector3.zero;
var lightningGenerator = lightning.GetComponent<CloudLightningGenerator>();
lightningGenerator._altitude = (atmo.clouds.outerCloudRadius + atmo.clouds.innerCloudRadius) / 2f;
lightningGenerator._altitude = atmo.clouds.cloudsPrefab != CloudPrefabType.Transparent ? (atmo.clouds.outerCloudRadius + atmo.clouds.innerCloudRadius) / 2f : atmo.clouds.outerCloudRadius;
if (noAudio)
{
lightningGenerator._audioPrefab = null;
@ -170,7 +177,6 @@ namespace NewHorizons.Builder.Atmosphere
MeshRenderer topMR = cloudsTopGO.AddComponent<MeshRenderer>();
if (_sphereShader == null) _sphereShader = Main.NHAssetBundle.LoadAsset<Shader>("Assets/Shaders/SphereTextureWrapper.shader");
if (_gdCloudMaterials == null) _gdCloudMaterials = SearchUtilities.Find("CloudsTopLayer_GD").GetComponent<MeshRenderer>().sharedMaterials;
if (_qmCloudMaterials == null) _qmCloudMaterials = SearchUtilities.Find("CloudsTopLayer_QM").GetComponent<MeshRenderer>().sharedMaterials;
Material[] prefabMaterials = atmo.clouds.cloudsPrefab == CloudPrefabType.GiantsDeep ? _gdCloudMaterials : _qmCloudMaterials;
@ -178,10 +184,10 @@ namespace NewHorizons.Builder.Atmosphere
if (atmo.clouds.cloudsPrefab == CloudPrefabType.Basic)
{
var material = new Material(_sphereShader);
var material = new Material(Shader.Find("Standard"));
if (atmo.clouds.unlit) material.renderQueue = 3000;
material.name = atmo.clouds.unlit ? "BasicCloud" : "BasicShadowCloud";
material.SetFloat(Smoothness, 0f);
tempArray[0] = material;
}
else
@ -211,8 +217,7 @@ namespace NewHorizons.Builder.Atmosphere
if (atmo.clouds.rotationSpeed != 0f)
{
var topRT = cloudsTopGO.AddComponent<RotateTransform>();
// Idk why but the axis is weird
topRT._localAxis = atmo.clouds.cloudsPrefab == CloudPrefabType.Basic ? Vector3.forward : Vector3.up;
topRT._localAxis = Vector3.up;
topRT._degreesPerSecond = atmo.clouds.rotationSpeed;
topRT._randomizeRotationRate = false;
}
@ -223,5 +228,65 @@ namespace NewHorizons.Builder.Atmosphere
return cloudsTopGO;
}
public static GameObject MakeTransparentClouds(GameObject rootObject, AtmosphereModule atmo, IModBehaviour mod, bool isProxy = false)
{
Texture2D image;
try
{
image = ImageUtilities.GetTexture(mod, atmo.clouds.texturePath);
}
catch (Exception e)
{
Logger.LogError($"Couldn't load Cloud texture for [{atmo.clouds.texturePath}]:\n{e}");
return null;
}
GameObject cloudsTransparentGO = new GameObject("TransparentClouds");
cloudsTransparentGO.SetActive(false);
cloudsTransparentGO.transform.parent = rootObject.transform;
cloudsTransparentGO.transform.localScale = Vector3.one * atmo.clouds.outerCloudRadius;
MeshFilter filter = cloudsTransparentGO.AddComponent<MeshFilter>();
filter.mesh = SearchUtilities.Find("CloudsTopLayer_GD").GetComponent<MeshFilter>().mesh;
MeshRenderer renderer = cloudsTransparentGO.AddComponent<MeshRenderer>();
if (_transparentCloud == null) _transparentCloud = Main.NHAssetBundle.LoadAsset<Material>("Assets/Resources/TransparentCloud.mat");
var material = new Material(_transparentCloud);
material.name = "TransparentClouds_" + image.name;
material.SetTexture(MainTex, image);
renderer.sharedMaterial = material;
if (!isProxy)
{
GameObject tcrqcGO = new GameObject("TransparentCloudRenderQueueController");
tcrqcGO.transform.SetParent(cloudsTransparentGO.transform, false);
tcrqcGO.layer = LayerMask.NameToLayer("BasicEffectVolume");
var shape = tcrqcGO.AddComponent<SphereShape>();
shape.radius = 1;
var owTriggerVolume = tcrqcGO.AddComponent<OWTriggerVolume>();
owTriggerVolume._shape = shape;
TransparentCloudRenderQueueController tcrqc = tcrqcGO.AddComponent<TransparentCloudRenderQueueController>();
tcrqc.renderer = renderer;
}
if (atmo.clouds.rotationSpeed != 0f)
{
var rt = cloudsTransparentGO.AddComponent<RotateTransform>();
rt._localAxis = Vector3.up;
rt._degreesPerSecond = atmo.clouds.rotationSpeed;
rt._randomizeRotationRate = false;
}
cloudsTransparentGO.transform.localPosition = Vector3.zero;
cloudsTransparentGO.SetActive(true);
return cloudsTransparentGO;
}
}
}

View File

@ -20,6 +20,18 @@ namespace NewHorizons.Builder.Atmosphere
SCG._dynamicCullingBounds = false;
SCG._waitForStreaming = false;
var minHeight = surfaceSize;
if (config.HeightMap?.minHeight != null)
{
if (config.Water?.size >= config.HeightMap.minHeight) minHeight = config.Water.size; // use sea level if its higher
else minHeight = config.HeightMap.minHeight;
}
else if (config.Water?.size != null) minHeight = config.Water.size;
else if (config.Lava?.size != null) minHeight = config.Lava.size;
var maxHeight = config.Atmosphere.size;
if (config.Atmosphere.clouds?.outerCloudRadius != null) maxHeight = config.Atmosphere.clouds.outerCloudRadius;
if (config.Atmosphere.hasRain)
{
var rainGO = GameObject.Instantiate(SearchUtilities.Find("GiantsDeep_Body/Sector_GD/Sector_GDInterior/Effects_GDInterior/Effects_GD_Rain"), effectsGO.transform);
@ -29,9 +41,9 @@ namespace NewHorizons.Builder.Atmosphere
var pvc = rainGO.GetComponent<PlanetaryVectionController>();
pvc._densityByHeight = new AnimationCurve(new Keyframe[]
{
new Keyframe(surfaceSize - 0.5f, 0),
new Keyframe(surfaceSize, 10f),
new Keyframe(config.Atmosphere.size, 0f)
new Keyframe(minHeight - 0.5f, 0),
new Keyframe(minHeight, 10f),
new Keyframe(maxHeight, 0f)
});
rainGO.GetComponent<PlanetaryVectionController>()._activeInSector = sector;
@ -53,9 +65,9 @@ namespace NewHorizons.Builder.Atmosphere
var pvc = snowEmitter.GetComponent<PlanetaryVectionController>();
pvc._densityByHeight = new AnimationCurve(new Keyframe[]
{
new Keyframe(surfaceSize - 0.5f, 0),
new Keyframe(surfaceSize, 10f),
new Keyframe(config.Atmosphere.size, 0f)
new Keyframe(minHeight - 0.5f, 0),
new Keyframe(minHeight, 10f),
new Keyframe(maxHeight, 0f)
});
snowEmitter.GetComponent<PlanetaryVectionController>()._activeInSector = sector;

View File

@ -31,6 +31,7 @@ namespace NewHorizons.Builder.Atmosphere
PlanetoidRuleset PR = rulesetGO.AddComponent<PlanetoidRuleset>();
PR._altitudeFloor = innerRadius;
PR._altitudeCeiling = sphereOfInfluence;
PR._shuttleLandingRadius = sphereOfInfluence;
PR._useMinimap = config.Base.showMinimap;
PR._useAltimeter = config.Base.showMinimap;

View File

@ -192,8 +192,12 @@ namespace NewHorizons.Builder.Body
cloak.GetComponent<Renderer>().enabled = true;
// Cull stuff
var cullController = go.AddComponent<BrambleSectorController>();
cullController.SetSector(sector);
// Do next update so other nodes can be built first
Delay.FireOnNextUpdate(() =>
{
var cullController = go.AddComponent<BrambleSectorController>();
cullController.SetSector(sector);
});
// finalize
atmo.SetActive(true);

View File

@ -54,7 +54,7 @@ namespace NewHorizons.Builder.Body
remnantGO.transform.parent = proxy.transform;
remnantGO.transform.localPosition = Vector3.zero;
SharedMake(planetGO, remnantGO, proxyController, remnant);
SharedMake(planetGO, remnantGO, null, remnant);
proxyController.stellarRemnantGO = remnantGO;
}
@ -111,7 +111,8 @@ namespace NewHorizons.Builder.Body
if (body.Config.Atmosphere.clouds != null)
{
topClouds = CloudsBuilder.MakeTopClouds(proxy, body.Config.Atmosphere, body.Mod).GetComponent<MeshRenderer>();
if (body.Config.Atmosphere.clouds.cloudsPrefab != External.Modules.CloudPrefabType.Transparent) topClouds = CloudsBuilder.MakeTopClouds(proxy, body.Config.Atmosphere, body.Mod).GetComponent<MeshRenderer>();
else topClouds = CloudsBuilder.MakeTransparentClouds(proxy, body.Config.Atmosphere, body.Mod, true).GetAddComponent<MeshRenderer>();
if (body.Config.Atmosphere.clouds.hasLightning) lightningGenerator = CloudsBuilder.MakeLightning(proxy, null, body.Config.Atmosphere, true);
@ -119,15 +120,20 @@ namespace NewHorizons.Builder.Body
}
}
if (body.Config.Ring != null)
if (body.Config.Rings != null)
{
RingBuilder.MakeRingGraphics(proxy, null, body.Config.Ring, body.Mod);
if (realSize < body.Config.Ring.outerRadius) realSize = body.Config.Ring.outerRadius;
foreach (var ring in body.Config.Rings)
{
RingBuilder.MakeRingGraphics(proxy, null, ring, body.Mod);
if (realSize < ring.outerRadius) realSize = ring.outerRadius;
}
}
Renderer starAtmosphere = null;
Renderer starFog = null;
if (body.Config.Star != null)
{
StarBuilder.MakeStarProxy(planetGO, proxy, body.Config.Star, body.Mod, body.Config.isStellarRemnant);
(_, starAtmosphere, starFog) = StarBuilder.MakeStarProxy(planetGO, proxy, body.Config.Star, body.Mod, body.Config.isStellarRemnant);
if (realSize < body.Config.Star.size) realSize = body.Config.Star.size;
}
@ -217,9 +223,17 @@ namespace NewHorizons.Builder.Body
if (proxyController != null)
{
proxyController._atmosphere = atmosphere;
proxyController._fog = fog;
proxyController._fogCurveMaxVal = fogCurveMaxVal;
proxyController._atmosphere = atmosphere ?? starAtmosphere;
if (fog != null)
{
proxyController._fog = fog;
proxyController._fogCurveMaxVal = fogCurveMaxVal;
}
else if (starFog != null)
{
proxyController._fog = starFog;
proxyController._fogCurveMaxVal = 0.05f;
}
proxyController.topClouds = topClouds;
proxyController.lightningGenerator = lightningGenerator;
proxyController.supernovaPlanetEffectController = supernovaPlanetEffect;

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using NewHorizons.External.Modules;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
using NewHorizons.Components.Volumes;
namespace NewHorizons.Builder.Body
{
@ -73,7 +74,7 @@ namespace NewHorizons.Builder.Body
return null;
}
var ringGO = new GameObject("Ring");
var ringGO = new GameObject(!string.IsNullOrEmpty(ring.rename) ? ring.rename : "Ring");
ringGO.transform.parent = sector?.transform ?? rootObject.transform;
ringGO.transform.position = rootObject.transform.position;
ringGO.transform.rotation = rootObject.transform.rotation;

View File

@ -1,4 +1,3 @@
using NewHorizons.Components;
using NewHorizons.External.Configs;
using NewHorizons.Utility;
using System;
@ -10,6 +9,7 @@ using System.Linq;
using NewHorizons.Components.SizeControllers;
using System.Drawing;
using Color = UnityEngine.Color;
using NewHorizons.Components.Volumes;
namespace NewHorizons.Builder.Body
{

View File

@ -1,4 +1,3 @@
using NewHorizons.Components;
using NewHorizons.Components.SizeControllers;
using NewHorizons.Utility;
using OWML.Utils;
@ -9,6 +8,7 @@ using OWML.ModHelper;
using OWML.Common;
using UnityEngine.InputSystem.XR;
using System.Linq;
using NewHorizons.Components.Stars;
namespace NewHorizons.Builder.Body
{
@ -46,23 +46,29 @@ namespace NewHorizons.Builder.Body
sunAtmosphere.transform.position = planetGO.transform.position;
sunAtmosphere.transform.localScale = Vector3.one * OuterRadiusRatio;
sunAtmosphere.name = "Atmosphere_Star";
var atmospheres = sunAtmosphere.transform.Find("AtmoSphere");
atmospheres.transform.localScale = Vector3.one;
var lods = atmospheres.GetComponentsInChildren<MeshRenderer>();
foreach (var lod in lods)
{
lod.material.SetFloat(InnerRadius, starModule.size);
lod.material.SetFloat(OuterRadius, starModule.size * OuterRadiusRatio);
}
var fog = sunAtmosphere.transform.Find("FogSphere").GetComponent<PlanetaryFogController>();
fog.transform.localScale = Vector3.one;
fog.fogRadius = starModule.size * OuterRadiusRatio;
fog.lodFadeDistance = fog.fogRadius * (StarBuilder.OuterRadiusRatio - 1f);
fog.fogImpostor.material.SetFloat(Radius, starModule.size * OuterRadiusRatio);
if (starModule.tint != null)
{
fog.fogTint = starModule.tint.ToColor();
fog.fogImpostor.material.SetColor(Tint, starModule.tint.ToColor());
sunAtmosphere.transform.Find("AtmoSphere").transform.localScale = Vector3.one;
foreach (var lod in sunAtmosphere.transform.Find("AtmoSphere").GetComponentsInChildren<MeshRenderer>())
{
foreach (var lod in lods)
lod.material.SetColor(SkyColor, starModule.tint.ToColor());
lod.material.SetFloat(InnerRadius, starModule.size);
lod.material.SetFloat(OuterRadius, starModule.size * OuterRadiusRatio);
}
}
fog.transform.localScale = Vector3.one;
fog.fogRadius = starModule.size * OuterRadiusRatio;
fog.lodFadeDistance = fog.fogRadius * (StarBuilder.OuterRadiusRatio - 1f);
fog.fogImpostor.material.SetFloat(Radius, starModule.size * OuterRadiusRatio);
}
var ambientLightGO = Object.Instantiate(SearchUtilities.Find("Sun_Body/AmbientLight_SUN"), starGO.transform);
@ -120,7 +126,6 @@ namespace NewHorizons.Builder.Body
light.CopyPropertiesFrom(SearchUtilities.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<Light>());
light.intensity *= starModule.solarLuminosity;
light.range = starModule.lightRadius;
light.range *= Mathf.Sqrt(starModule.solarLuminosity);
Color lightColour = light.color;
if (starModule.lightTint != null) lightColour = starModule.lightTint.ToColor();
@ -179,10 +184,37 @@ namespace NewHorizons.Builder.Body
return (starGO, starController, starEvolutionController);
}
public static GameObject MakeStarProxy(GameObject planet, GameObject proxyGO, StarModule starModule, IModBehaviour mod, bool isStellarRemnant)
public static (GameObject, Renderer, Renderer) MakeStarProxy(GameObject planet, GameObject proxyGO, StarModule starModule, IModBehaviour mod, bool isStellarRemnant)
{
var (starGO, controller, supernova) = SharedStarGeneration(proxyGO, null, mod, starModule, isStellarRemnant);
Renderer atmosphere = null;
Renderer fog = null;
if (starModule.hasAtmosphere)
{
GameObject sunAtmosphere = Object.Instantiate(SearchUtilities.Find("SunProxy/Sun_Proxy_Body/Atmosphere_SUN", false) ?? SearchUtilities.Find("SunProxy(Clone)/Sun_Proxy_Body/Atmosphere_SUN"), starGO.transform);
sunAtmosphere.transform.position = proxyGO.transform.position;
sunAtmosphere.transform.localScale = Vector3.one * OuterRadiusRatio;
sunAtmosphere.name = "Atmosphere_Star";
atmosphere = sunAtmosphere.transform.Find("Atmosphere_LOD2").GetComponent<MeshRenderer>();
atmosphere.transform.localScale = Vector3.one;
atmosphere.material.SetFloat(InnerRadius, starModule.size);
atmosphere.material.SetFloat(OuterRadius, starModule.size * OuterRadiusRatio);
fog = sunAtmosphere.transform.Find("FogSphere").GetComponent<MeshRenderer>();
fog.transform.localScale = Vector3.one;
fog.material.SetFloat(Radius, starModule.size * OuterRadiusRatio);
if (starModule.tint != null)
{
fog.material.SetColor(Tint, starModule.tint.ToColor());
atmosphere.material.SetColor(SkyColor, starModule.tint.ToColor());
}
controller.atmosphere = sunAtmosphere;
}
controller.isProxy = true;
// Planet can have multiple stars on them, so find the one that is also a remnant / not a remnant
@ -198,7 +230,7 @@ namespace NewHorizons.Builder.Body
supernova.mainStellerDeathController = mainController.supernova;
}
return starGO;
return (starGO, atmosphere, fog);
}
private static (GameObject, StarEvolutionController, StellarDeathController) SharedStarGeneration(GameObject planetGO, Sector sector, IModBehaviour mod, StarModule starModule, bool isStellarRemnant)

View File

@ -88,7 +88,7 @@ namespace NewHorizons.Builder.Body
lightRadius = 10000,
solarLuminosity = 0.5f
};
if (proxy != null) return StarBuilder.MakeStarProxy(planetGO, proxy, whiteDwarfModule, mod, true);
if (proxy != null) return StarBuilder.MakeStarProxy(planetGO, proxy, whiteDwarfModule, mod, true).Item1;
else return StarBuilder.Make(planetGO, sector, whiteDwarfModule, mod, true).Item1;
}
@ -107,7 +107,7 @@ namespace NewHorizons.Builder.Body
// Instead of showing the typical star surface we use a tinted singularity
GameObject neutronStar;
if (proxy != null) neutronStar = StarBuilder.MakeStarProxy(planetGO, proxy, neutronStarModule, mod, true);
if (proxy != null) neutronStar = StarBuilder.MakeStarProxy(planetGO, proxy, neutronStarModule, mod, true).Item1;
else (neutronStar, _, _) = StarBuilder.Make(planetGO, sector, neutronStarModule, mod, true);
neutronStar.FindChild("Surface").SetActive(false);

View File

@ -1,9 +1,9 @@
using NewHorizons.Components;
using NewHorizons.Components.SizeControllers;
using NewHorizons.Utility;
using UnityEngine;
using NewHorizons.External.Modules.VariableSize;
using Tessellation;
using NewHorizons.Components.Volumes;
namespace NewHorizons.Builder.Body
{

View File

@ -0,0 +1,29 @@
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.General;
public static class GroupsBuilder
{
/// <summary>
/// puts groups on an object, activated by sector.
/// run this before the gameobject is active.
/// </summary>
public static void Make(GameObject go, Sector sector)
{
if (!sector)
{
Logger.LogWarning($"tried to put groups on {go.name} when sector is null");
return;
}
if (go.activeInHierarchy)
{
Logger.LogWarning($"tried to put groups on an active gameobject {go.name}");
return;
}
go.GetAddComponent<SectorCullGroup>()._sector = sector;
go.GetAddComponent<SectorCollisionGroup>()._sector = sector;
go.GetAddComponent<SectorLightsCullGroup>()._sector = sector;
}
}

View File

@ -1,5 +1,7 @@
using NewHorizons.External.Modules;
using NewHorizons.Utility;
using System;
using System.Reflection;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.General
@ -89,38 +91,28 @@ namespace NewHorizons.Builder.General
public static void SuitUp()
{
suitUpQueued = false;
if (Locator.GetPlayerController()._isWearingSuit) return;
Locator.GetPlayerTransform().GetComponent<PlayerSpacesuit>().SuitUp(false, true, true);
// Make the ship act as if the player took the suit
var spv = SearchUtilities.Find("Ship_Body/Module_Supplies/Systems_Supplies/ExpeditionGear")?.GetComponent<SuitPickupVolume>();
if (spv == null) return;
spv._containsSuit = false;
if (spv._allowSuitReturn)
if (!Locator.GetPlayerController()._isWearingSuit)
{
spv._interactVolume.ChangePrompt(UITextType.ReturnSuitPrompt, spv._pickupSuitCommandIndex);
var spv = SearchUtilities.Find("Ship_Body/Module_Supplies/Systems_Supplies/ExpeditionGear")?.GetComponent<SuitPickupVolume>();
if (spv != null)
{
var command = spv._interactVolume.GetInteractionAt(spv._pickupSuitCommandIndex).inputCommand;
// Make the ship act as if the player took the suit
var eventDelegate = (MulticastDelegate)typeof(MultipleInteractionVolume).GetField(
nameof(MultipleInteractionVolume.OnPressInteract),
BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(spv._interactVolume);
foreach (var handler in eventDelegate.GetInvocationList())
{
handler.Method.Invoke(handler.Target, new object[] { command });
}
}
else
{
Locator.GetPlayerTransform().GetComponent<PlayerSpacesuit>().SuitUp(false, true, true);
}
}
else
{
spv._interactVolume.EnableSingleInteraction(false, spv._pickupSuitCommandIndex);
}
spv._timer = 0f;
spv._index = 0;
spv.OnSuitUp();
GameObject suitGeometry = spv._suitGeometry;
if (suitGeometry != null) suitGeometry.SetActive(false);
OWCollider suitOWCollider = spv._suitOWCollider;
if (suitOWCollider != null) suitOWCollider.SetActivation(false);
spv.enabled = true;
}
}
}

View File

@ -79,7 +79,7 @@ namespace NewHorizons.Builder.Props
}
else FixSectoredComponent(component, sector, isTorch);
FixComponent(component, go, prefab.name);
FixComponent(component, go);
}
prop.transform.position = detail.position == null ? go.transform.position : go.transform.TransformPoint(detail.position);
@ -222,11 +222,11 @@ namespace NewHorizons.Builder.Props
return false;
}
private static void FixComponent(Component component, GameObject planetGO, string prefab)
private static void FixComponent(Component component, GameObject planetGO)
{
// Fix other components
// I forget why this is here
if (component is GhostIK || component is GhostEffects)
if (component is GhostIK or GhostEffects)
{
Component.DestroyImmediate(component);
return;
@ -278,43 +278,52 @@ namespace NewHorizons.Builder.Props
torchItem.mindSlideProjector._mindProjectorImageEffect = SearchUtilities.Find("Player_Body/PlayerCamera").GetComponent<MindProjectorImageEffect>();
}
// Fix a bunch of stuff when done loading
Delay.RunWhen(() => Main.IsSystemReady, () =>
if (component is Animator animator) animator.enabled = true;
if (component is Collider collider) collider.enabled = true;
if (component is Renderer renderer) renderer.enabled = true;
if (component is Shape shape) shape.enabled = true;
// fixes sector cull group deactivating renderers on map view enter and fast foward
// TODO: does this actually work? what? how?
if (component is SectorCullGroup sectorCullGroup)
{
try
sectorCullGroup._inMapView = false;
sectorCullGroup._isFastForwarding = false;
sectorCullGroup.SetVisible(sectorCullGroup.ShouldBeVisible(), true, false);
}
// If it's not a moving anglerfish make sure the anim controller is regular
if (component is AnglerfishAnimController && component.GetComponentInParent<AnglerfishController>() == null)
component.gameObject.AddComponent<AnglerAnimFixer>();
}
/// <summary>
/// Has to happen after AnglerfishAnimController awake to remove the events it has set up.
/// Otherwise results in the anglerfish 1) having its animations controlled by an actual fish 2) randomly having different animations on solarsystem load
/// Can't do delay because it needs to work with scatter (copies a prefab made using MakeDetail).
/// </summary>
[RequireComponent(typeof(AnglerfishAnimController))]
private class AnglerAnimFixer : MonoBehaviour
{
private void Start()
{
var angler = GetComponent<AnglerfishAnimController>();
Logger.LogVerbose("Fixing anglerfish animation");
// Remove any event reference to its angler
if (angler._anglerfishController)
{
if (component == null) return;
if (component is Animator animator) animator.enabled = true;
else if (component is Collider collider) collider.enabled = true;
else if (component is Renderer renderer) renderer.enabled = true;
else if (component is Shape shape) shape.enabled = true;
else if (component is SectorCullGroup sectorCullGroup)
{
sectorCullGroup._inMapView = false;
sectorCullGroup._isFastForwarding = false;
sectorCullGroup.SetVisible(sectorCullGroup.ShouldBeVisible(), true, false);
}
// If it's not a moving anglerfish make sure the anim controller is regular
else if (component is AnglerfishAnimController angler && angler.GetComponentInParent<AnglerfishController>() == null)
{
Logger.LogVerbose("Enabling anglerfish animation");
// Remove any reference to its angler
if (angler._anglerfishController)
{
angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState;
angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn;
angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended;
angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended;
}
angler.enabled = true;
angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking);
}
angler._anglerfishController.OnChangeAnglerState -= angler.OnChangeAnglerState;
angler._anglerfishController.OnAnglerTurn -= angler.OnAnglerTurn;
angler._anglerfishController.OnAnglerSuspended -= angler.OnAnglerSuspended;
angler._anglerfishController.OnAnglerUnsuspended -= angler.OnAnglerUnsuspended;
}
catch (Exception e)
{
Logger.LogWarning($"Exception when modifying component [{component.GetType().Name}] on [{planetGO.name}] for prop [{prefab}]:\n{e}");
}
});
angler.enabled = true;
angler.OnChangeAnglerState(AnglerfishController.AnglerState.Lurking);
Destroy(this);
}
}
}
}

View File

@ -87,7 +87,7 @@ namespace NewHorizons.Builder.Props
var dialogueTree = conversationZone.AddComponent<CharacterDialogueTree>();
var xml = File.ReadAllText(mod.Manifest.ModFolderPath + info.xmlFile);
var xml = File.ReadAllText(Path.Combine(mod.Manifest.ModFolderPath, info.xmlFile));
var text = new TextAsset(xml);
// Text assets need a name to be used with VoiceMod
@ -207,19 +207,21 @@ namespace NewHorizons.Builder.Props
var name = xmlNode2.SelectSingleNode("Name").InnerText;
XmlNodeList xmlText = xmlNode2.SelectNodes("Dialogue/Page");
foreach (object Page in xmlText)
foreach (object page in xmlText)
{
XmlNode pageData = (XmlNode)Page;
XmlNode pageData = (XmlNode)page;
var text = pageData.InnerText;
TranslationHandler.AddDialogue(text, name);
// The text is trimmed in DialogueText constructor (_listTextBlocks), so we also need to trim it for the key
TranslationHandler.AddDialogue(text, true, name);
}
xmlText = xmlNode2.SelectNodes("DialogueOptionsList/DialogueOption/Text");
foreach (object Page in xmlText)
foreach (object option in xmlText)
{
XmlNode pageData = (XmlNode)Page;
var text = pageData.InnerText;
TranslationHandler.AddDialogue(text, characterName, name);
XmlNode optionData = (XmlNode)option;
var text = optionData.InnerText;
// The text is trimmed in CharacterDialogueTree.LoadXml, so we also need to trim it for the key
TranslationHandler.AddDialogue(text, true, characterName, name);
}
}
}

View File

@ -2,12 +2,12 @@ using NewHorizons.External.Modules;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using OWML.Common;
using Enum = System.Enum;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Xml;
using UnityEngine;
using Enum = System.Enum;
using Logger = NewHorizons.Utility.Logger;
using Random = UnityEngine.Random;
namespace NewHorizons.Builder.Props
@ -99,7 +99,7 @@ namespace NewHorizons.Builder.Props
_preCrashRecorderPrefab.name = "Prefab_NOM_Recorder_Vessel";
_preCrashRecorderPrefab.transform.rotation = Quaternion.identity;
_trailmarkerPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/Prefab_NOM_Sign");
_trailmarkerPrefab = SearchUtilities.Find("BrittleHollow_Body/Sector_BH/Sector_NorthHemisphere/Sector_NorthPole/Sector_HangingCity/Sector_HangingCity_District2/Interactables_HangingCity_District2/Prefab_NOM_Sign").InstantiateInactive();
_trailmarkerPrefab.name = "Prefab_NOM_Trailmarker";
_trailmarkerPrefab.transform.rotation = Quaternion.identity;
}
@ -108,7 +108,7 @@ namespace NewHorizons.Builder.Props
{
if (_scrollPrefab == null) InitPrefabs();
var xmlPath = File.ReadAllText(mod.ModHelper.Manifest.ModFolderPath + info.xmlFile);
var xmlPath = File.ReadAllText(Path.Combine(mod.ModHelper.Manifest.ModFolderPath, info.xmlFile));
switch (info.type)
{
@ -492,6 +492,9 @@ namespace NewHorizons.Builder.Props
trailmarkerObject.transform.position = planetGO.transform.TransformPoint(info?.position ?? Vector3.zero);
// shrink because that is what mobius does on all trailmarkers or else they are the size of the player
trailmarkerObject.transform.localScale = Vector3.one * 0.75f;
if (info.rotation != null)
{
trailmarkerObject.transform.rotation = planetGO.transform.TransformRotation(Quaternion.Euler(info.rotation));

View File

@ -4,9 +4,12 @@ using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using UnityEngine;
using static NewHorizons.External.Modules.PropModule;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Props
{
public static class ProjectionBuilder
@ -89,19 +92,8 @@ namespace NewHorizons.Builder.Props
// The base game ones only have 15 slides max
var textures = new Texture2D[slidesCount >= 15 ? 15 : slidesCount];
var imageLoader = slideReelObj.AddComponent<ImageUtilities.AsyncImageLoader>();
for (int i = 0; i < slidesCount; i++)
{
var slide = new Slide();
var slideInfo = info.slides[i];
var imageLoader = AddAsyncLoader(slideReelObj, mod, info.slides, ref slideCollection);
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod);
slideCollection.slides[i] = slide;
}
// this variable just lets us track how many of the first 15 slides have been loaded.
// this way as soon as the last one is loaded (due to async loading, this may be
// slide 7, or slide 3, or whatever), we can build the slide reel texture. This allows us
@ -113,24 +105,22 @@ namespace NewHorizons.Builder.Props
slideCollection.slides[index]._image = ImageUtilities.Invert(tex);
// Track the first 15 to put on the slide reel object
if (index < 15)
if (index < textures.Length)
{
textures[index] = tex;
displaySlidesLoaded++; // threading moment
}
if (Interlocked.Increment(ref displaySlidesLoaded) == textures.Length)
{
// all textures required to build the reel's textures have been loaded
var slidesBack = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Back").GetComponent<MeshRenderer>();
var slidesFront = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Front").GetComponent<MeshRenderer>();
if (displaySlidesLoaded >= textures.Length)
{
// all textures required to build the reel's textures have been loaded
var slidesBack = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Back").GetComponent<MeshRenderer>();
var slidesFront = slideReelObj.transform.Find("Props_IP_SlideReel_7/Slides_Front").GetComponent<MeshRenderer>();
// Now put together the textures into a 4x4 thing for the materials
var reelTexture = ImageUtilities.MakeReelTexture(textures);
slidesBack.material.mainTexture = reelTexture;
slidesBack.material.SetTexture(EmissionMap, reelTexture);
slidesFront.material.mainTexture = reelTexture;
slidesFront.material.SetTexture(EmissionMap, reelTexture);
// Now put together the textures into a 4x4 thing for the materials
var reelTexture = ImageUtilities.MakeReelTexture(textures);
slidesBack.material.mainTexture = reelTexture;
slidesBack.material.SetTexture(EmissionMap, reelTexture);
slidesFront.material.mainTexture = reelTexture;
slidesFront.material.SetTexture(EmissionMap, reelTexture);
}
}
}
);
@ -191,18 +181,7 @@ namespace NewHorizons.Builder.Props
int slidesCount = info.slides.Length;
var slideCollection = new SlideCollection(slidesCount);
var imageLoader = projectorObj.AddComponent<ImageUtilities.AsyncImageLoader>();
for (int i = 0; i < slidesCount; i++)
{
var slide = new Slide();
var slideInfo = info.slides[i];
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod);
slideCollection.slides[i] = slide;
}
var imageLoader = AddAsyncLoader(projectorObj, mod, info.slides, ref slideCollection);
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index]._image = ImageUtilities.Invert(tex); });
slideCollectionContainer.slideCollection = slideCollection;
@ -256,19 +235,7 @@ namespace NewHorizons.Builder.Props
var slidesCount = slides.Length;
var slideCollection = new SlideCollection(slidesCount);
var imageLoader = g.AddComponent<ImageUtilities.AsyncImageLoader>();
for (int i = 0; i < slidesCount; i++)
{
var slide = new Slide();
var slideInfo = slides[i];
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod);
slideCollection.slides[i] = slide;
}
var imageLoader = AddAsyncLoader(g, mod, info.slides, ref slideCollection);
imageLoader.imageLoadedEvent.AddListener((Texture2D tex, int index) => { slideCollection.slides[index]._image = tex; });
// attach a component to store all the data for the slides that play when a vision torch scans this target
@ -330,19 +297,8 @@ namespace NewHorizons.Builder.Props
var slidesCount = slides.Length;
var slideCollection = new SlideCollection(slidesCount);
var imageLoader = standingTorch.AddComponent<ImageUtilities.AsyncImageLoader>();
for (int i = 0; i < slidesCount; i++)
{
var slide = new Slide();
var slideInfo = slides[i];
var imageLoader = AddAsyncLoader(standingTorch, mod, slides, ref slideCollection);
imageLoader.pathsToLoad.Add(mod.ModHelper.Manifest.ModFolderPath + slideInfo.imagePath);
AddModules(slideInfo, ref slide, mod);
slideCollection.slides[i] = slide;
}
// This variable just lets us track how many of the slides have been loaded.
// This way as soon as the last one is loaded (due to async loading, this may be
// slide 7, or slide 3, or whatever), we can enable the vision torch. This allows us
@ -352,9 +308,8 @@ namespace NewHorizons.Builder.Props
(Texture2D tex, int index) =>
{
slideCollection.slides[index]._image = tex;
displaySlidesLoaded++; // threading moment
if (displaySlidesLoaded >= slides.Length)
if (Interlocked.Increment(ref displaySlidesLoaded) == slides.Length)
{
mindSlideProjector.enabled = true;
visionBeamEffect.SetActive(true);
@ -378,6 +333,31 @@ namespace NewHorizons.Builder.Props
return standingTorch;
}
private static ImageUtilities.AsyncImageLoader AddAsyncLoader(GameObject gameObject, IModBehaviour mod, SlideInfo[] slides, ref SlideCollection slideCollection)
{
var imageLoader = gameObject.AddComponent<ImageUtilities.AsyncImageLoader>();
for (int i = 0; i < slides.Length; i++)
{
var slide = new Slide();
var slideInfo = slides[i];
if (string.IsNullOrEmpty(slideInfo.imagePath))
{
imageLoader.imageLoadedEvent?.Invoke(Texture2D.blackTexture, i);
}
else
{
imageLoader.PathsToLoad.Add((i, Path.Combine(mod.ModHelper.Manifest.ModFolderPath, slideInfo.imagePath)));
}
AddModules(slideInfo, ref slide, mod);
slideCollection.slides[i] = slide;
}
return imageLoader;
}
private static void AddModules(PropModule.SlideInfo slideInfo, ref Slide slide, IModBehaviour mod)
{
var modules = new List<SlideFunctionModule>();

View File

@ -109,20 +109,6 @@ namespace NewHorizons.Builder.Props
}
}
}
if (config.Props.reveal != null)
{
foreach (var revealInfo in config.Props.reveal)
{
try
{
RevealBuilder.Make(go, sector, revealInfo, mod);
}
catch (Exception ex)
{
Logger.LogError($"Couldn't make reveal location [{revealInfo.reveals}] for [{go.name}]:\n{ex}");
}
}
}
if (config.Props.entryLocation != null)
{
foreach (var entryLocationInfo in config.Props.entryLocation)
@ -207,13 +193,6 @@ namespace NewHorizons.Builder.Props
}
}
}
if (config.Props.audioVolumes != null)
{
foreach (var audioVolume in config.Props.audioVolumes)
{
AudioVolumeBuilder.Make(go, sector, audioVolume, mod);
}
}
if (config.Props.signals != null)
{
foreach (var signal in config.Props.signals)

View File

@ -1,5 +1,5 @@
using HarmonyLib;
using NewHorizons.Components;
using NewHorizons.Components.Quantum;
using NewHorizons.External.Configs;
using NewHorizons.External.Modules;
using NewHorizons.Utility;

View File

@ -1,4 +1,4 @@
using NewHorizons.Components;
using NewHorizons.Components.Volumes;
using NewHorizons.External.Modules;
using NewHorizons.Handlers;
using NewHorizons.Utility;

View File

@ -3,6 +3,8 @@ using NewHorizons.External.Modules;
using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Object = UnityEngine.Object;
using Random = UnityEngine.Random;
@ -19,13 +21,20 @@ namespace NewHorizons.Builder.Props
{
var heightMap = config.HeightMap;
var area = 4f * Mathf.PI * radius * radius;
var makeFibonacciSphere = scatterInfo.Any(x => x.preventOverlap);
// To not use more than 0.5GB of RAM while doing this
// Works up to planets with 575 radius before capping
var numPoints = Math.Min((int)(area * 10), 41666666);
List<Vector3> points = new();
var points = RandomUtility.FibonacciSphere(numPoints);
if (makeFibonacciSphere)
{
var area = 4f * Mathf.PI * radius * radius;
// To not use more than 0.5GB of RAM while doing this
// Works up to planets with 575 radius before capping
var numPoints = Math.Min((int)(area * 10), 41666666);
points = RandomUtility.FibonacciSphere(numPoints);
}
Texture2D heightMapTexture = null;
if (heightMap != null)
@ -55,13 +64,29 @@ namespace NewHorizons.Builder.Props
GameObject prefab;
if (propInfo.assetBundle != null) prefab = AssetBundleUtilities.LoadPrefab(propInfo.assetBundle, propInfo.path, mod);
else prefab = SearchUtilities.Find(propInfo.path);
// Run all the make detail stuff on it early and just copy it over and over instead
var detailInfo = new PropModule.DetailInfo()
{
scale = propInfo.scale,
keepLoaded = propInfo.keepLoaded
};
var scatterPrefab = DetailBuilder.Make(go, sector, prefab, detailInfo);
for (int i = 0; i < propInfo.count; i++)
{
// Failsafe
if (points.Count == 0) break;
var randomInd = (int)Random.Range(0, points.Count - 1);
var point = points[randomInd];
Vector3 point;
if (propInfo.preventOverlap)
{
if (points.Count == 0) break;
var randomInd = Random.Range(0, points.Count - 1);
point = points[randomInd];
points.QuickRemoveAt(randomInd);
}
else
{
point = Random.onUnitSphere;
}
var height = radius;
if (heightMapTexture != null)
@ -92,13 +117,11 @@ namespace NewHorizons.Builder.Props
point = Quaternion.Euler(90, 0, 0) * point;
}
var detailInfo = new PropModule.DetailInfo()
{
position = point.normalized * height,
scale = propInfo.scale,
alignToNormal = true
};
var prop = DetailBuilder.Make(go, sector, prefab, detailInfo);
var prop = scatterPrefab.InstantiateInactive();
prop.transform.SetParent(sector?.transform ?? go.transform);
prop.transform.localPosition = go.transform.TransformPoint(point * height);
var up = go.transform.InverseTransformPoint(prop.transform.position).normalized;
prop.transform.rotation = Quaternion.FromToRotation(Vector3.up, up);
if (propInfo.offset != null) prop.transform.localPosition += prop.transform.TransformVector(propInfo.offset);
if (propInfo.rotation != null) prop.transform.rotation *= Quaternion.Euler(propInfo.rotation);
@ -106,9 +129,10 @@ namespace NewHorizons.Builder.Props
// Rotate around normal
prop.transform.localRotation *= Quaternion.AngleAxis(Random.Range(0, 360), Vector3.up);
points.QuickRemoveAt(randomInd);
if (points.Count == 0) return;
prop.SetActive(true);
}
GameObject.Destroy(scatterPrefab);
}
}
}

View File

@ -1,4 +1,4 @@
using NewHorizons.External.Modules;
using NewHorizons.External.Modules;
using OWML.Common;
using System.Collections.Generic;
using UnityEngine;
@ -15,6 +15,7 @@ namespace NewHorizons.Builder.ShipLog
entryLocationGameObject.transform.position = go.transform.TransformPoint(info.position ?? Vector3.zero);
ShipLogEntryLocation newLocation = entryLocationGameObject.AddComponent<ShipLogEntryLocation>();
newLocation._entryID = info.id;
newLocation._outerFogWarpVolume = go.GetComponentInChildren<OuterFogWarpVolume>();
newLocation._isWithinCloakField = info.cloaked;
_locationsToInitialize.Add(newLocation);
entryLocationGameObject.SetActive(true);

View File

@ -1,4 +1,3 @@
using NewHorizons.Components;
using NewHorizons.External.Modules;
using NewHorizons.Handlers;
using NewHorizons.Utility;
@ -9,6 +8,8 @@ using NewHorizons.External.Modules.VariableSize;
using UnityEngine;
using UnityEngine.UI;
using Logger = NewHorizons.Utility.Logger;
using NewHorizons.Components.ShipLog;
namespace NewHorizons.Builder.ShipLog
{
public static class MapModeBuilder
@ -219,7 +220,7 @@ namespace NewHorizons.Builder.ShipLog
foreach (NewHorizonsBody body in bodies)
{
if (body.Config.ShipLog?.mapMode?.manualNavigationPosition == null) continue;
if (body.Config.ShipLog?.mapMode?.manualNavigationPosition == null && body.Config.ShipLog?.mapMode?.details == null) continue;
// Sometimes they got other names idk
var name = body.Config.name.Replace(" ", "");
@ -283,6 +284,7 @@ namespace NewHorizons.Builder.ShipLog
{
gameObject.transform.localScale = Vector3.one * body.Config.ShipLog.mapMode.scale;
}
MakeDetails(body, gameObject.transform, greyScaleMaterial);
}
}
}

View File

@ -7,18 +7,18 @@ namespace NewHorizons.Builder.ShipLog
{
public static class RevealBuilder
{
public static void Make(GameObject go, Sector sector, PropModule.RevealInfo info, IModBehaviour mod)
public static void Make(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod)
{
var newRevealGO = MakeGameObject(go, sector, info, mod);
switch (info.revealOn)
{
case PropModule.RevealInfo.RevealVolumeType.Enter:
case VolumesModule.RevealVolumeInfo.RevealVolumeType.Enter:
MakeTrigger(newRevealGO, sector, info, mod);
break;
case PropModule.RevealInfo.RevealVolumeType.Observe:
case VolumesModule.RevealVolumeInfo.RevealVolumeType.Observe:
MakeObservable(newRevealGO, sector, info, mod);
break;
case PropModule.RevealInfo.RevealVolumeType.Snapshot:
case VolumesModule.RevealVolumeInfo.RevealVolumeType.Snapshot:
MakeSnapshot(newRevealGO, sector, info, mod);
break;
default:
@ -28,7 +28,7 @@ namespace NewHorizons.Builder.ShipLog
newRevealGO.SetActive(true);
}
private static SphereShape MakeShape(GameObject go, PropModule.RevealInfo info, Shape.CollisionMode collisionMode)
private static SphereShape MakeShape(GameObject go, VolumesModule.RevealVolumeInfo info, Shape.CollisionMode collisionMode)
{
SphereShape newShape = go.AddComponent<SphereShape>();
newShape.radius = info.radius;
@ -36,16 +36,36 @@ namespace NewHorizons.Builder.ShipLog
return newShape;
}
private static GameObject MakeGameObject(GameObject planetGO, Sector sector, PropModule.RevealInfo info, IModBehaviour mod)
private static GameObject MakeGameObject(GameObject planetGO, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod)
{
GameObject revealTriggerVolume = new GameObject("Reveal Volume (" + info.revealOn + ")");
revealTriggerVolume.SetActive(false);
revealTriggerVolume.transform.parent = sector?.transform ?? planetGO.transform;
if (!string.IsNullOrEmpty(info.rename))
{
revealTriggerVolume.name = info.rename;
}
if (!string.IsNullOrEmpty(info.parentPath))
{
var newParent = planetGO.transform.Find(info.parentPath);
if (newParent != null)
{
revealTriggerVolume.transform.parent = newParent;
}
else
{
Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}");
}
}
revealTriggerVolume.transform.position = planetGO.transform.TransformPoint(info.position ?? Vector3.zero);
return revealTriggerVolume;
}
private static void MakeTrigger(GameObject go, Sector sector, PropModule.RevealInfo info, IModBehaviour mod)
private static void MakeTrigger(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod)
{
var shape = MakeShape(go, info, Shape.CollisionMode.Volume);
@ -65,7 +85,7 @@ namespace NewHorizons.Builder.ShipLog
}
}
private static void MakeObservable(GameObject go, Sector sector, PropModule.RevealInfo info, IModBehaviour mod)
private static void MakeObservable(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod)
{
go.layer = LayerMask.NameToLayer("Interactible");
@ -96,7 +116,7 @@ namespace NewHorizons.Builder.ShipLog
}
}
private static void MakeSnapshot(GameObject go, Sector sector, PropModule.RevealInfo info, IModBehaviour mod)
private static void MakeSnapshot(GameObject go, Sector sector, VolumesModule.RevealVolumeInfo info, IModBehaviour mod)
{
var shape = MakeShape(go, info, Shape.CollisionMode.Manual);

View File

@ -4,6 +4,7 @@ using NewHorizons.Handlers;
using NewHorizons.Utility;
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
@ -53,7 +54,7 @@ namespace NewHorizons.Builder.ShipLog
public static void AddBodyToShipLog(ShipLogManager manager, NewHorizonsBody body)
{
string systemName = body.Config.starSystem;
XElement astroBodyFile = XElement.Load(body.Mod.ModHelper.Manifest.ModFolderPath + "/" + body.Config.ShipLog.xmlFile);
XElement astroBodyFile = XElement.Load(Path.Combine(body.Mod.ModHelper.Manifest.ModFolderPath, body.Config.ShipLog.xmlFile));
XElement astroBodyId = astroBodyFile.Element("ID");
if (astroBodyId == null)
{

View File

@ -9,16 +9,35 @@ using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Props
namespace NewHorizons.Builder.Volumes
{
public static class AudioVolumeBuilder
{
public static AudioVolume Make(GameObject planetGO, Sector sector, PropModule.AudioVolumeInfo info, IModBehaviour mod)
public static AudioVolume Make(GameObject planetGO, Sector sector, VolumesModule.AudioVolumeInfo info, IModBehaviour mod)
{
var go = new GameObject("AudioVolume");
go.SetActive(false);
go.transform.parent = sector?.transform ?? planetGO.transform;
if (!string.IsNullOrEmpty(info.rename))
{
go.name = info.rename;
}
if (!string.IsNullOrEmpty(info.parentPath))
{
var newParent = planetGO.transform.Find(info.parentPath);
if (newParent != null)
{
go.transform.parent = newParent;
}
else
{
Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}");
}
}
go.transform.position = planetGO.transform.TransformPoint(info.position != null ? (Vector3)info.position : Vector3.zero);
go.layer = LayerMask.NameToLayer("AdvancedEffectVolume");
@ -26,7 +45,7 @@ namespace NewHorizons.Builder.Props
var owAudioSource = go.AddComponent<OWAudioSource>();
owAudioSource._audioSource = audioSource;
owAudioSource.loop = true;
owAudioSource.loop = info.loop;
owAudioSource.SetTrack((OWAudioMixer.TrackName)Enum.Parse(typeof(OWAudioMixer.TrackName), Enum.GetName(typeof(AudioMixerTrackName), info.track)));
AudioUtilities.SetAudioClip(owAudioSource, info.audio, mod);

View File

@ -0,0 +1,60 @@
using NewHorizons.External.Modules;
using OWML.Common;
using OWML.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Volumes
{
public static class HazardVolumeBuilder
{
public static HazardVolume Make(GameObject planetGO, Sector sector, OWRigidbody owrb, VolumesModule.HazardVolumeInfo info, IModBehaviour mod)
{
var go = new GameObject("HazardVolume");
go.SetActive(false);
go.transform.parent = sector?.transform ?? planetGO.transform;
if (!string.IsNullOrEmpty(info.rename))
{
go.name = info.rename;
}
if (!string.IsNullOrEmpty(info.parentPath))
{
var newParent = planetGO.transform.Find(info.parentPath);
if (newParent != null)
{
go.transform.parent = newParent;
}
else
{
Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}");
}
}
go.transform.position = planetGO.transform.TransformPoint(info.position != null ? (Vector3)info.position : Vector3.zero);
go.layer = LayerMask.NameToLayer("BasicEffectVolume");
var shape = go.AddComponent<SphereShape>();
shape.radius = info.radius;
var owTriggerVolume = go.AddComponent<OWTriggerVolume>();
owTriggerVolume._shape = shape;
var hazardVolume = go.AddComponent<SimpleHazardVolume>();
hazardVolume._attachedBody = owrb;
hazardVolume._type = EnumUtils.Parse<HazardVolume.HazardType>(info.type.ToString(), HazardVolume.HazardType.GENERAL);
hazardVolume._damagePerSecond = info.damagePerSecond;
hazardVolume._firstContactDamageType = EnumUtils.Parse<InstantDamageType>(info.firstContactDamageType.ToString(), InstantDamageType.Impact);
hazardVolume._firstContactDamage = info.firstContactDamage;
go.SetActive(true);
return hazardVolume;
}
}
}

View File

@ -0,0 +1,61 @@
using NewHorizons.External.Modules;
using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
using NHNotificationVolume = NewHorizons.Components.Volumes.NotificationVolume;
namespace NewHorizons.Builder.Volumes
{
public static class NotificationVolumeBuilder
{
public static NHNotificationVolume Make(GameObject planetGO, Sector sector, VolumesModule.NotificationVolumeInfo info, IModBehaviour mod)
{
var go = new GameObject("NotificationVolume");
go.SetActive(false);
go.transform.parent = sector?.transform ?? planetGO.transform;
if (!string.IsNullOrEmpty(info.rename))
{
go.name = info.rename;
}
if (!string.IsNullOrEmpty(info.parentPath))
{
var newParent = planetGO.transform.Find(info.parentPath);
if (newParent != null)
{
go.transform.parent = newParent;
}
else
{
Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}");
}
}
go.transform.position = planetGO.transform.TransformPoint(info.position != null ? (Vector3)info.position : Vector3.zero);
go.layer = LayerMask.NameToLayer("BasicEffectVolume");
var shape = go.AddComponent<SphereShape>();
shape.radius = info.radius;
var owTriggerVolume = go.AddComponent<OWTriggerVolume>();
owTriggerVolume._shape = shape;
var notificationVolume = go.AddComponent<NHNotificationVolume>();
notificationVolume.SetTarget(info.target);
if (info.entryNotification != null) notificationVolume.SetEntryNotification(info.entryNotification.displayMessage, info.entryNotification.duration);
if (info.exitNotification != null) notificationVolume.SetExitNotification(info.exitNotification.displayMessage, info.exitNotification.duration);
go.SetActive(true);
return notificationVolume;
}
}
}

View File

@ -0,0 +1,51 @@
using NewHorizons.Components;
using NewHorizons.External.Modules;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Volumes
{
public static class VolumeBuilder
{
public static TVolume Make<TVolume>(GameObject planetGO, Sector sector, VolumesModule.VolumeInfo info) where TVolume : MonoBehaviour //Could be BaseVolume but I need to create vanilla volumes too.
{
var go = new GameObject(typeof(TVolume).Name);
go.SetActive(false);
go.transform.parent = sector?.transform ?? planetGO.transform;
if (!string.IsNullOrEmpty(info.rename))
{
go.name = info.rename;
}
if (!string.IsNullOrEmpty(info.parentPath))
{
var newParent = planetGO.transform.Find(info.parentPath);
if (newParent != null)
{
go.transform.parent = newParent;
}
else
{
Logger.LogWarning($"Cannot find parent object at path: {planetGO.name}/{info.parentPath}");
}
}
go.transform.position = planetGO.transform.TransformPoint(info.position != null ? (Vector3)info.position : Vector3.zero);
go.layer = LayerMask.NameToLayer("BasicEffectVolume");
var shape = go.AddComponent<SphereShape>();
shape.radius = info.radius;
var owTriggerVolume = go.AddComponent<OWTriggerVolume>();
owTriggerVolume._shape = shape;
var volume = go.AddComponent<TVolume>();
go.SetActive(true);
return volume;
}
}
}

View File

@ -0,0 +1,83 @@
using NewHorizons.Builder.Body;
using NewHorizons.Builder.ShipLog;
using NewHorizons.Builder.Volumes;
using NewHorizons.Components.Volumes;
using NewHorizons.External.Configs;
using OWML.Common;
using System;
using System.Collections.Generic;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Builder.Volumes
{
public static class VolumesBuildManager
{
public static void Make(GameObject go, Sector sector, OWRigidbody planetBody, PlanetConfig config, IModBehaviour mod)
{
if (config.Volumes.revealVolumes != null)
{
foreach (var revealInfo in config.Volumes.revealVolumes)
{
try
{
RevealBuilder.Make(go, sector, revealInfo, mod);
}
catch (Exception ex)
{
Logger.LogError($"Couldn't make reveal location [{revealInfo.reveals}] for [{go.name}]:\n{ex}");
}
}
}
if (config.Volumes.audioVolumes != null)
{
foreach (var audioVolume in config.Volumes.audioVolumes)
{
AudioVolumeBuilder.Make(go, sector, audioVolume, mod);
}
}
if (config.Volumes.notificationVolumes != null)
{
foreach (var notificationVolume in config.Volumes.notificationVolumes)
{
NotificationVolumeBuilder.Make(go, sector, notificationVolume, mod);
}
}
if (config.Volumes.hazardVolumes != null)
{
foreach (var hazardVolume in config.Volumes.hazardVolumes)
{
HazardVolumeBuilder.Make(go, sector, planetBody, hazardVolume, mod);
}
}
if (config.Volumes.mapRestrictionVolumes != null)
{
foreach (var mapRestrictionVolume in config.Volumes.mapRestrictionVolumes)
{
VolumeBuilder.Make<MapRestrictionVolume>(go, sector, mapRestrictionVolume);
}
}
if (config.Volumes.interferenceVolumes != null)
{
foreach (var interferenceVolume in config.Volumes.interferenceVolumes)
{
VolumeBuilder.Make<Components.Volumes.InterferenceVolume>(go, sector, interferenceVolume);
}
}
if (config.Volumes.reverbVolumes != null)
{
foreach (var reverbVolume in config.Volumes.reverbVolumes)
{
VolumeBuilder.Make<ReverbTriggerVolume>(go, sector, reverbVolume);
}
}
if (config.Volumes.insulatingVolumes != null)
{
foreach (var insulatingVolume in config.Volumes.insulatingVolumes)
{
VolumeBuilder.Make<InsulatingVolume>(go, sector, insulatingVolume);
}
}
}
}
}

View File

@ -1,7 +1,7 @@
using NewHorizons.Builder.General;
using NewHorizons.External.Configs;
using UnityEngine;
namespace NewHorizons.Components
namespace NewHorizons.Components.Fixers
{
public class MapSatelliteOrbitFix : MonoBehaviour
{

View File

@ -7,60 +7,60 @@ using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
namespace NewHorizons.Components.Quantum
{
public class NHMultiStateQuantumObject : MultiStateQuantumObject
{
public override bool ChangeQuantumState(bool skipInstantVisibilityCheck)
{
for (int i = 0; i < _prerequisiteObjects.Length; i++)
{
if (!_prerequisiteObjects[i].HasCollapsed())
{
return false;
}
}
int stateIndex = _stateIndex;
if (_stateIndex == -1 && _initialState != -1)
{
_stateIndex = _initialState;
}
else if (_sequential)
{
_stateIndex = (_reverse ? (_stateIndex - 1) : (_stateIndex + 1));
if (_loop)
{
if (_stateIndex < 0)
{
_stateIndex = _states.Length - 1;
}
else if (_stateIndex > _states.Length - 1)
{
_stateIndex = 0;
}
}
else
{
_stateIndex = Mathf.Clamp(_stateIndex, 0, _states.Length - 1);
}
}
else
{
public override bool ChangeQuantumState(bool skipInstantVisibilityCheck)
{
for (int i = 0; i < _prerequisiteObjects.Length; i++)
{
if (!_prerequisiteObjects[i].HasCollapsed())
{
return false;
}
}
int stateIndex = _stateIndex;
if (_stateIndex == -1 && _initialState != -1)
{
_stateIndex = _initialState;
}
else if (_sequential)
{
_stateIndex = _reverse ? _stateIndex - 1 : _stateIndex + 1;
if (_loop)
{
if (_stateIndex < 0)
{
_stateIndex = _states.Length - 1;
}
else if (_stateIndex > _states.Length - 1)
{
_stateIndex = 0;
}
}
else
{
_stateIndex = Mathf.Clamp(_stateIndex, 0, _states.Length - 1);
}
}
else
{
// TODO: perform this roll for number of states, each time adding the selected state to the end of a list and removing it from the source list
// this gets us a randomly ordered list that respects states' probability
// then we can sequentially attempt collapsing to them, checking at each state whether the new state is invalid due to the player being able to see it, according to this:
//
// if (!((!IsPlayerEntangled()) ? (CheckIllumination() ? CheckVisibilityInstantly() : CheckPointInside(Locator.GetPlayerCamera().transform.position)) : CheckIllumination()))
// {
// return true; // this is a valid state
// }
// {
// return true; // this is a valid state
// }
//
List<int> indices = new List<int>();
for (var i = 0; i < _states.Length; i++) if (i != stateIndex) indices.Add(i);
var previousIndex = stateIndex;
do
@ -69,31 +69,31 @@ namespace NewHorizons.Components
_stateIndex = RollState(stateIndex, indices);
if (previousIndex >= 0 && previousIndex < _states.Length) _states[previousIndex].SetVisible(visible: false);
_states[_stateIndex].SetVisible(visible: true);
Logger.LogVerbose($"MultiStateQuantumObject - Trying to change state {_stateIndex}");
indices.Remove(_stateIndex);
} while (!CurrentStateIsValid() && indices.Count > 0);
}
}
var stateIndexIsValid = stateIndex >= 0 && stateIndex < _states.Length;
if (stateIndexIsValid) _states[stateIndex].SetVisible(visible: false);
if (stateIndexIsValid) _states[stateIndex].SetVisible(visible: false);
_states[_stateIndex].SetVisible(visible: true);
_states[_stateIndex].SetVisible(visible: true);
if (!CurrentStateIsValid() && stateIndexIsValid)
{
_states[_stateIndex].SetVisible(visible: false);
_states[stateIndex] .SetVisible(visible: true);
_stateIndex = stateIndex;
_states[_stateIndex].SetVisible(visible: false);
_states[stateIndex].SetVisible(visible: true);
_stateIndex = stateIndex;
return false;
}
if (_sequential && !_loop && _stateIndex == _states.Length - 1)
{
SetActivation(active: false);
}
return true;
}
if (_sequential && !_loop && _stateIndex == _states.Length - 1)
{
SetActivation(active: false);
}
return true;
}
public bool CurrentStateIsValid()
{
@ -102,20 +102,20 @@ namespace NewHorizons.Components
var visibility = CheckVisibilityInstantly();
var playerInside = CheckPointInside(Locator.GetPlayerCamera().transform.position);
var isVisible =
var isVisible =
isPlayerEntangled
? illumination
: (
illumination
:
illumination
? visibility
: playerInside
);
;
return !isVisible;
}
public int RollState(int excludeIndex, List<int> indices)
{
{
var stateIndex = excludeIndex;
// this function constructs a sort of segmented range:
@ -132,32 +132,32 @@ namespace NewHorizons.Components
//
// the second for looop uses num3 and num4 to figure out which segment num2 landed in
int num = 0;
foreach (int j in indices)
{
if (j != stateIndex)
{
_probabilities[j] = _states[j].GetProbability();
num += _probabilities[j];
}
}
int num2 = UnityEngine.Random.Range(0, num);
int num3 = 0;
int num4 = 0;
foreach (int k in indices)
{
if (k != stateIndex)
{
num3 = num4;
num4 += _probabilities[k];
if (_probabilities[k] > 0 && num2 >= num3 && num2 < num4)
{
return k;
}
}
}
int num = 0;
foreach (int j in indices)
{
if (j != stateIndex)
{
_probabilities[j] = _states[j].GetProbability();
num += _probabilities[j];
}
}
int num2 = UnityEngine.Random.Range(0, num);
int num3 = 0;
int num4 = 0;
foreach (int k in indices)
{
if (k != stateIndex)
{
num3 = num4;
num4 += _probabilities[k];
if (_probabilities[k] > 0 && num2 >= num3 && num2 < num4)
{
return k;
}
}
}
return indices[indices.Count-1];
return indices[indices.Count - 1];
}
}
}

View File

@ -9,7 +9,7 @@ using System.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
using Random = UnityEngine.Random;
namespace NewHorizons.Components
namespace NewHorizons.Components.Quantum
{
public class QuantumPlanet : QuantumObject
{
@ -162,9 +162,9 @@ namespace NewHorizons.Components
private void OnPlayerBlink()
{
if (base.IsVisible())
if (IsVisible())
{
base.Collapse(true);
Collapse(true);
}
}

View File

@ -1,3 +1,4 @@
using NewHorizons.Components.Volumes;
using NewHorizons.External.Modules.VariableSize;
using NewHorizons.Utility;
using UnityEngine;

View File

@ -1,8 +1,8 @@
using NewHorizons.External.Modules;
using NewHorizons.External.Modules;
using UnityEngine;
using UnityEngine.UI;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
namespace NewHorizons.Components.ShipLog
{
public class ShipLogDetail : MonoBehaviour
{
@ -51,7 +51,7 @@ namespace NewHorizons.Components
private void SetGreyScale(bool greyScale)
{
_revealedImage.material = (greyScale ? _greyScaleMaterial : null);
_revealedImage.material = greyScale ? _greyScaleMaterial : null;
}
}
}

View File

@ -6,7 +6,7 @@ using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
namespace NewHorizons.Components.ShipLog
{
public class ShipLogStarChartMode : ShipLogMode
{
@ -41,7 +41,7 @@ namespace NewHorizons.Components
public override void Initialize(ScreenPromptList centerPromptList, ScreenPromptList upperRightPromptList, OWAudioSource oneShotSource)
{
root = base.transform.Find("ScaleRoot/PanRoot");
root = transform.Find("ScaleRoot/PanRoot");
_oneShotSource = oneShotSource;
_centerPromptList = centerPromptList;
@ -101,11 +101,11 @@ namespace NewHorizons.Components
if (_cardTemplate == null)
{
var panRoot = SearchUtilities.Find("Ship_Body/Module_Cabin/Systems_Cabin/ShipLogPivot/ShipLog/ShipLogPivot/ShipLogCanvas/DetectiveMode/ScaleRoot/PanRoot");
_cardTemplate = GameObject.Instantiate(panRoot.GetComponentInChildren<ShipLogEntryCard>().gameObject);
_cardTemplate = Instantiate(panRoot.GetComponentInChildren<ShipLogEntryCard>().gameObject);
_cardTemplate.SetActive(false);
}
var newCard = GameObject.Instantiate(_cardTemplate, parent);
var newCard = Instantiate(_cardTemplate, parent);
var textComponent = newCard.transform.Find("EntryCardRoot/NameBackground/Name").GetComponent<Text>();
var name = UniqueIDToName(uniqueID);
@ -164,7 +164,7 @@ namespace NewHorizons.Components
public override void EnterMode(string entryID = "", List<ShipLogFact> revealQueue = null)
{
base.gameObject.SetActive(true);
gameObject.SetActive(true);
Locator.GetPromptManager().AddScreenPrompt(_detectiveModePrompt, _upperRightPromptList, TextAnchor.MiddleRight, -1, true);
Locator.GetPromptManager().AddScreenPrompt(_targetSystemPrompt, _centerPromptList, TextAnchor.MiddleCenter, -1, true);
@ -172,7 +172,7 @@ namespace NewHorizons.Components
public override void ExitMode()
{
base.gameObject.SetActive(false);
gameObject.SetActive(false);
Locator.GetPromptManager().RemoveScreenPrompt(_detectiveModePrompt);
Locator.GetPromptManager().RemoveScreenPrompt(_targetSystemPrompt);
@ -223,7 +223,7 @@ namespace NewHorizons.Components
if (oldIndex != _cardIndex)
{
_oneShotSource.PlayOneShot(global::AudioType.ShipLogMoveBetweenPlanets, 1f);
_oneShotSource.PlayOneShot(AudioType.ShipLogMoveBetweenPlanets, 1f);
_startPanTime = Time.unscaledTime;
_startPanPos = _panRootPos;
_panDuration = 0.25f;
@ -297,7 +297,7 @@ namespace NewHorizons.Components
{
if (_warpNotificationData != null) NotificationManager.SharedInstance.UnpinNotification(_warpNotificationData);
if (_target == null) return;
if (playSound) _oneShotSource.PlayOneShot(global::AudioType.ShipLogMarkLocation, 1f);
if (playSound) _oneShotSource.PlayOneShot(AudioType.ShipLogMarkLocation, 1f);
_target.SetMarkedOnHUD(false);
_target = null;
}

View File

@ -1,5 +1,6 @@
using NewHorizons.Builder.Body;
using NewHorizons.Components.Orbital;
using NewHorizons.Components.Stars;
using NewHorizons.External.Modules.VariableSize;
using NewHorizons.Handlers;
using NewHorizons.Utility;
@ -286,7 +287,9 @@ namespace NewHorizons.Components.SizeControllers
{
_stellarRemnant.SetActive(true);
var remnantStarController = _stellarRemnant.GetComponentInChildren<StarController>();
if (remnantStarController != null) StarLightController.AddStar(remnantStarController);
if (remnantStarController != null) SunLightEffectsController.AddStar(remnantStarController);
var remnantStarLight = _stellarRemnant.FindChild("SunLight");
if (remnantStarLight != null) SunLightEffectsController.AddStarLight(remnantStarLight.GetComponent<Light>());
}
if (Time.time > _supernovaStartTime + supernovaTime)
@ -299,7 +302,8 @@ namespace NewHorizons.Components.SizeControllers
private void DisableStar(bool start = false)
{
if (controller != null) StarLightController.RemoveStar(controller);
if (controller != null) SunLightEffectsController.RemoveStar(controller);
if (!isProxy) SunLightEffectsController.RemoveStarLight(gameObject.FindChild("SunLight").GetComponent<Light>());
if (_stellarRemnant != null)
{

View File

@ -1,129 +0,0 @@
using NewHorizons.Builder.Atmosphere;
using System.Collections.Generic;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components
{
[RequireComponent(typeof(SunLightController))]
[RequireComponent(typeof(SunLightParamUpdater))]
public class StarLightController : MonoBehaviour
{
private static readonly int SunIntensity = Shader.PropertyToID("_SunIntensity");
private static readonly float hearthSunDistanceSqr = 8593 * 8593;
public static StarLightController Instance { get; private set; }
private List<StarController> _stars = new List<StarController>();
private StarController _activeStar;
private SunLightController _sunLightController;
private SunLightParamUpdater _sunLightParamUpdater;
public void Awake()
{
Instance = this;
_sunLightController = GetComponent<SunLightController>();
_sunLightController.enabled = true;
_sunLightParamUpdater = GetComponent<SunLightParamUpdater>();
_sunLightParamUpdater._sunLightController = _sunLightController;
}
public static void AddStar(StarController star)
{
if (star == null) return;
Logger.LogVerbose($"Adding new star to list: {star.gameObject.name}");
Instance._stars.Add(star);
}
public static void RemoveStar(StarController star)
{
Logger.LogVerbose($"Removing star from list: {star?.gameObject?.name}");
if (Instance._stars.Contains(star))
{
if (Instance._activeStar != null && Instance._activeStar.Equals(star))
{
Instance._stars.Remove(star);
if (Instance._stars.Count > 0) Instance.ChangeActiveStar(Instance._stars[0]);
}
else
{
Instance._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);
foreach (var (_, material) in AtmosphereBuilder.Skys)
{
material.SetFloat(SunIntensity, 0);
}
return;
}
// Update atmo shaders
foreach (var (planet, material) in AtmosphereBuilder.Skys)
{
var sqrDist = (planet.transform.position - _activeStar.transform.position).sqrMagnitude;
var intensity = Mathf.Min(_activeStar.Intensity / (sqrDist / hearthSunDistanceSqr), 1f);
material.SetFloat(SunIntensity, intensity);
}
foreach (var star in _stars)
{
if (star == null) continue;
if (!(star.gameObject.activeSelf && star.gameObject.activeInHierarchy)) 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 < _activeStar.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.LogVerbose($"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;
}
}
}

View File

@ -1,5 +1,5 @@
using UnityEngine;
namespace NewHorizons.Components
using UnityEngine;
namespace NewHorizons.Components.Stars
{
public class StarController : MonoBehaviour
{

View File

@ -5,7 +5,7 @@ using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Components
namespace NewHorizons.Components.Stars
{
public class StarDestructionVolume : DestructionVolume
{

View File

@ -1,6 +1,6 @@
using NewHorizons.Components.SizeControllers;
using UnityEngine;
namespace NewHorizons.Components
namespace NewHorizons.Components.Stars
{
public class StarFluidVolume : SimpleFluidVolume
{

View File

@ -1,7 +1,7 @@
using UnityEngine;
using NewHorizons.Components.SizeControllers;
namespace NewHorizons.Components
namespace NewHorizons.Components.Stars
{
[RequireComponent(typeof(OWAudioSource))]
public class StarSurfaceAudioController : SectoredMonoBehaviour
@ -34,7 +34,7 @@ namespace NewHorizons.Components
public void Update()
{
_fade = Mathf.MoveTowards(_fade, 1, Time.deltaTime * 0.2f);
float value = Mathf.Max(0.0f, Vector3.Distance(Locator.GetPlayerCamera().transform.position, this.transform.position) - (_starEvolutionController != null ? _starEvolutionController.CurrentScale : _size));
float value = Mathf.Max(0.0f, Vector3.Distance(Locator.GetPlayerCamera().transform.position, transform.position) - (_starEvolutionController != null ? _starEvolutionController.CurrentScale : _size));
float num = Mathf.InverseLerp(1600f, 100f, value);
_audioSource.SetLocalVolume(num * num * _fade);
}

View File

@ -1,6 +1,6 @@
using UnityEngine;
namespace NewHorizons.Components
namespace NewHorizons.Components.Stars
{
public class StellarDeathController : MonoBehaviour
{
@ -22,6 +22,7 @@ namespace NewHorizons.Components
private float _currentSupernovaScale;
private Material _localSupernovaMat;
private bool _isProxy;
private bool _renderingEnabled = true;
private ParticleSystemRenderer[] _cachedParticleRenderers;
public void Awake()
@ -34,8 +35,12 @@ namespace NewHorizons.Components
public void Activate()
{
enabled = true;
shockwave.enabled = true;
foreach (var particle in explosionParticles) particle.Play();
shockwave.enabled = _renderingEnabled;
for (int i = 0; i < explosionParticles.Length; i++)
{
explosionParticles[i].Play();
_cachedParticleRenderers[i].enabled = _renderingEnabled;
}
_time = 0.0f;
_currentSupernovaScale = supernovaScale.Evaluate(0.0f);
_localSupernovaMat = new Material(supernovaMaterial);
@ -71,7 +76,7 @@ namespace NewHorizons.Components
surface.transform.localScale = Vector3.one * _currentSupernovaScale;
_localSupernovaMat.color = Color.Lerp(Color.black, supernovaMaterial.color, supernovaAlpha.Evaluate(_time));
float distanceToPlayer = PlayerState.InDreamWorld() ? 20000f : (Vector3.Distance(transform.position, Locator.GetPlayerCamera().transform.position) - GetSupernovaRadius());
float distanceToPlayer = PlayerState.InDreamWorld() ? 20000f : Vector3.Distance(transform.position, Locator.GetPlayerCamera().transform.position) - GetSupernovaRadius();
if (_isProxy) return;
@ -97,6 +102,7 @@ namespace NewHorizons.Components
public void SetRenderingEnabled(bool renderingEnabled)
{
_renderingEnabled = renderingEnabled;
if (!enabled) return;
shockwave.enabled = renderingEnabled;
SetParticlesVisibility(renderingEnabled);

View File

@ -0,0 +1,191 @@
using NewHorizons.Builder.Atmosphere;
using NewHorizons.Utility;
using System.Collections.Generic;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.Components.Stars
{
[RequireComponent(typeof(SunLightController))]
[RequireComponent(typeof(SunLightParamUpdater))]
public class SunLightEffectsController : MonoBehaviour
{
private static readonly int SunIntensity = Shader.PropertyToID("_SunIntensity");
private static readonly float hearthSunDistanceSqr = 8593 * 8593;
public static SunLightEffectsController Instance { get; private set; }
private readonly List<StarController> _stars = new();
private readonly List<Light> _lights = new();
private StarController _activeStar;
private SunLightController _sunLightController;
private SunLightParamUpdater _sunLightParamUpdater;
public void Awake()
{
Instance = this;
_sunLightController = GetComponent<SunLightController>();
_sunLightController.enabled = true;
_sunLightParamUpdater = GetComponent<SunLightParamUpdater>();
_sunLightParamUpdater._sunLightController = _sunLightController;
}
public void Start()
{
// Using GameObject.Find here so that if its null we just dont find it
var sunlight = GameObject.Find("Sun_Body/Sector_SUN/Effects_SUN/SunLight").GetComponent<Light>();
if (sunlight != null) AddStarLight(sunlight);
}
public static void AddStar(StarController star)
{
if (star == null) return;
Logger.LogVerbose($"Adding new star to list: {star.gameObject.name}");
Instance._stars.Add(star);
}
public static void RemoveStar(StarController star)
{
Logger.LogVerbose($"Removing star from list: {star?.gameObject?.name}");
if (Instance._stars.Contains(star))
{
if (Instance._activeStar != null && Instance._activeStar.Equals(star))
{
Instance._stars.Remove(star);
if (Instance._stars.Count > 0) Instance.ChangeActiveStar(Instance._stars[0]);
}
else
{
Instance._stars.Remove(star);
}
}
}
public static void AddStarLight(Light light)
{
if (light != null)
{
Instance._lights.SafeAdd(light);
}
}
public static void RemoveStarLight(Light light)
{
if (light != null && Instance._lights.Contains(light))
{
Instance._lights.Remove(light);
}
}
public void Update()
{
// 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;
// Keep all star lights on in map
foreach (var light in _lights)
{
light.enabled = true;
}
}
else
{
// Outside map, only show lights within 50km range or light.range
// For some reason outside of the actual range of the lights they still show reflection effects on water and glass
foreach (var light in _lights)
{
// Minimum 50km range so it's not badly noticeable for dim stars
if ((light.transform.position - origin).sqrMagnitude <= Mathf.Max(light.range * light.range, 2500000000))
{
light.enabled = true;
}
else
{
light.enabled = false;
}
}
}
if (_stars.Count > 0)
{
if (_activeStar == null || !_activeStar.gameObject.activeInHierarchy)
{
if (_stars.Contains(_activeStar))
{
_stars.Remove(_activeStar);
}
if (_stars.Count > 0)
{
ChangeActiveStar(_stars[0]);
}
else
{
foreach (var (_, material) in AtmosphereBuilder.Skys)
{
material.SetFloat(SunIntensity, 0);
}
}
}
else
{
// Update atmo shaders
foreach (var (planet, material) in AtmosphereBuilder.Skys)
{
var sqrDist = (planet.transform.position - _activeStar.transform.position).sqrMagnitude;
var intensity = Mathf.Min(_activeStar.Intensity / (sqrDist / hearthSunDistanceSqr), 1f);
material.SetFloat(SunIntensity, intensity);
}
foreach (var star in _stars)
{
if (star == null) continue;
if (!(star.gameObject.activeSelf && star.gameObject.activeInHierarchy)) continue;
if (star.Intensity * (star.transform.position - origin).sqrMagnitude < _activeStar.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.LogVerbose($"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
transform.parent = star.transform;
transform.localPosition = Vector3.zero;
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NewHorizons.Components
{
[RequireComponent(typeof(OWTriggerVolume))]
public class TransparentCloudRenderQueueController : MonoBehaviour
{
public int insideQueue = 3001;
public int outsideQueue = 2999;
private OWTriggerVolume _triggerVolume;
public Renderer renderer;
public void Awake()
{
_triggerVolume = this.GetRequiredComponent<OWTriggerVolume>();
if (_triggerVolume == null) return;
_triggerVolume.OnEntry += OnTriggerVolumeEntry;
_triggerVolume.OnExit += OnTriggerVolumeExit;
}
public void OnDestroy()
{
if (_triggerVolume == null) return;
_triggerVolume.OnEntry -= OnTriggerVolumeEntry;
_triggerVolume.OnExit -= OnTriggerVolumeExit;
}
public void OnTriggerVolumeEntry(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector")) SetQueueToInside();
}
public void OnTriggerVolumeExit(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector")) SetQueueToOutside();
}
public void SetQueueToInside()
{
if (renderer == null) return;
renderer.sharedMaterial.renderQueue = insideQueue;
}
public void SetQueueToOutside()
{
if (renderer == null) return;
renderer.sharedMaterial.renderQueue = outsideQueue;
}
}
}

View File

@ -0,0 +1,28 @@
using UnityEngine;
namespace NewHorizons.Components.Volumes
{
[RequireComponent(typeof(OWTriggerVolume))]
public abstract class BaseVolume : MonoBehaviour
{
private OWTriggerVolume _triggerVolume;
public virtual void Awake()
{
_triggerVolume = this.GetRequiredComponent<OWTriggerVolume>();
_triggerVolume.OnEntry += OnTriggerVolumeEntry;
_triggerVolume.OnExit += OnTriggerVolumeExit;
}
public virtual void OnDestroy()
{
if (_triggerVolume == null) return;
_triggerVolume.OnEntry -= OnTriggerVolumeEntry;
_triggerVolume.OnExit -= OnTriggerVolumeExit;
}
public abstract void OnTriggerVolumeEntry(GameObject hitObj);
public abstract void OnTriggerVolumeExit(GameObject hitObj);
}
}

View File

@ -1,6 +1,6 @@
using NewHorizons.OtherMods.AchievementsPlus.NH;
namespace NewHorizons.Components
namespace NewHorizons.Components.Volumes
{
public class BlackHoleDestructionVolume : DestructionVolume
{
@ -15,7 +15,7 @@ namespace NewHorizons.Components
SurveyorProbe requiredComponent = probeBody.GetRequiredComponent<SurveyorProbe>();
if (requiredComponent.IsLaunched())
{
UnityEngine.Object.Destroy(requiredComponent.gameObject);
Destroy(requiredComponent.gameObject);
ProbeLostAchievement.Earn();
}
}

View File

@ -1,4 +1,4 @@
namespace NewHorizons.Components
namespace NewHorizons.Components.Volumes
{
public class ChangeStarSystemVolume : BlackHoleDestructionVolume
{

View File

@ -0,0 +1,54 @@
using NewHorizons.Handlers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
namespace NewHorizons.Components.Volumes
{
public class InterferenceVolume : BaseVolume
{
public override void OnTriggerVolumeEntry(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
{
OnPlayerEnter();
}
else if (hitObj.CompareTag("ProbeDetector"))
{
OnProbeEnter();
}
else if (hitObj.CompareTag("ShipDetector"))
{
OnShipEnter();
}
}
public override void OnTriggerVolumeExit(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
{
OnPlayerExit();
}
else if (hitObj.CompareTag("ProbeDetector"))
{
OnProbeExit();
}
else if (hitObj.CompareTag("ShipDetector"))
{
OnShipExit();
}
}
public void OnPlayerEnter() => InterferenceHandler.OnPlayerEnterInterferenceVolume(this);
public void OnPlayerExit() => InterferenceHandler.OnPlayerExitInterferenceVolume(this);
public void OnProbeEnter() => InterferenceHandler.OnProbeEnterInterferenceVolume(this);
public void OnProbeExit() => InterferenceHandler.OnProbeExitInterferenceVolume(this);
public void OnShipEnter() => InterferenceHandler.OnShipEnterInterferenceVolume(this);
public void OnShipExit() => InterferenceHandler.OnShipExitInterferenceVolume(this);
}
}

View File

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NewHorizons.Components.Volumes
{
public class MapRestrictionVolume : BaseVolume
{
public override void OnTriggerVolumeEntry(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
{
Locator.GetMapController()?.OnPlayerEnterMapRestriction();
}
}
public override void OnTriggerVolumeExit(GameObject hitObj)
{
if (hitObj.CompareTag("PlayerDetector"))
{
Locator.GetMapController()?.OnPlayerExitMapRestriction();
}
}
}
}

View File

@ -1,5 +1,5 @@
using UnityEngine;
namespace NewHorizons.Components
using UnityEngine;
namespace NewHorizons.Components.Volumes
{
public class NHFluidVolume : RadialFluidVolume
{

View File

@ -1,4 +1,4 @@
namespace NewHorizons.Components
namespace NewHorizons.Components.Volumes
{
public class NHInnerFogWarpVolume : InnerFogWarpVolume
{

View File

@ -0,0 +1,113 @@
using NewHorizons.Handlers;
using OWML.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NewHorizons.Components.Volumes
{
public class NotificationVolume : BaseVolume
{
private NotificationTarget _target = NotificationTarget.All;
private bool _pin = false;
private NotificationData _entryNotification;
private NotificationData _exitNotification;
public void SetPinned(bool pin) => _pin = pin;
public void SetTarget(External.Modules.VolumesModule.NotificationVolumeInfo.NotificationTarget target) => SetTarget(EnumUtils.Parse(target.ToString(), NotificationTarget.All));
public void SetTarget(NotificationTarget target) => _target = target;
public void SetEntryNotification(string displayMessage, float duration = 5)
{
_entryNotification = new NotificationData(_target, TranslationHandler.GetTranslation(displayMessage, TranslationHandler.TextType.UI), duration);
}
public void SetExitNotification(string displayMessage, float duration = 5)
{
_exitNotification = new NotificationData(_target, TranslationHandler.GetTranslation(displayMessage, TranslationHandler.TextType.UI), duration);
}
public override void OnTriggerVolumeEntry(GameObject hitObj)
{
if (_target == NotificationTarget.All)
{
if (hitObj.CompareTag("PlayerDetector") || hitObj.CompareTag("ShipDetector"))
{
PostEntryNotification();
}
}
else if (_target == NotificationTarget.Player)
{
if (hitObj.CompareTag("PlayerDetector"))
{
PostEntryNotification();
}
}
else if (_target == NotificationTarget.Ship)
{
if (hitObj.CompareTag("ShipDetector"))
{
PostEntryNotification();
}
}
}
public override void OnTriggerVolumeExit(GameObject hitObj)
{
if (_target == NotificationTarget.All)
{
if (hitObj.CompareTag("PlayerDetector") || hitObj.CompareTag("ShipDetector"))
{
PostExitNotification();
}
}
else if (_target == NotificationTarget.Player)
{
if (hitObj.CompareTag("PlayerDetector"))
{
PostExitNotification();
}
}
else if (_target == NotificationTarget.Ship)
{
if (hitObj.CompareTag("ShipDetector"))
{
PostExitNotification();
}
}
}
public void PostEntryNotification()
{
if (_entryNotification == null) return;
NotificationManager.SharedInstance.PostNotification(_entryNotification, _pin);
}
public void PostExitNotification()
{
if (_exitNotification == null) return;
NotificationManager.SharedInstance.PostNotification(_exitNotification, _pin);
}
public void UnpinEntryNotification()
{
if (_entryNotification == null) return;
if (NotificationManager.SharedInstance.IsPinnedNotification(_entryNotification))
{
NotificationManager.SharedInstance.UnpinNotification(_entryNotification);
}
}
public void UnpinExitNotification()
{
if (_exitNotification == null) return;
if (NotificationManager.SharedInstance.IsPinnedNotification(_exitNotification))
{
NotificationManager.SharedInstance.UnpinNotification(_exitNotification);
}
}
}
}

View File

@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using UnityEngine;
namespace NewHorizons.Components
namespace NewHorizons.Components.Volumes
{
public class RingFluidVolume : SimpleFluidVolume
{
@ -14,7 +14,7 @@ namespace NewHorizons.Components
ForceDetector forceDetector = hitObj.GetComponent<ForceDetector>();
if (forceDetector != null && forceDetector._activeVolumes != null && forceDetector._activeVolumes.Count > 0 && forceDetector._activeVolumes.Where(activeVolume => activeVolume is ForceVolume).Select(activeVolume => activeVolume as ForceVolume).Any(activeVolume => activeVolume.GetAffectsAlignment(forceDetector._attachedBody))) return;
fluidDetector.AddVolume(this);
}

View File

@ -28,5 +28,10 @@ namespace NewHorizons.External.Configs
/// Credits info for this mod. A list of contributors and their roles separated by #. For example: xen#New Horizons dev.
/// </summary>
public string[] credits;
/// <summary>
/// A pop-up message for the first time a user runs the add-on
/// </summary>
public string popupMessage;
}
}

View File

@ -67,6 +67,10 @@ namespace NewHorizons.External.Configs
[Obsolete("Signal is deprecated, please use Props->signals")]
public SignalModule Signal;
[Obsolete("Ring is deprecated, please use Rings")]
public RingModule Ring;
#endregion Obsolete
/// <summary>
@ -135,9 +139,9 @@ namespace NewHorizons.External.Configs
public string[] removeChildren;
/// <summary>
/// Creates a ring around the planet
/// Create rings around the planet
/// </summary>
public RingModule Ring;
public RingModule[] Rings;
/// <summary>
/// Add sand to this planet
@ -169,6 +173,16 @@ namespace NewHorizons.External.Configs
/// </summary>
public WaterModule Water;
/// <summary>
/// Add various volumes on this body
/// </summary>
public VolumesModule Volumes;
/// <summary>
/// Extra data that may be used by extension mods
/// </summary>
public object extras;
public PlanetConfig()
{
// Always have to have a base module
@ -312,6 +326,20 @@ namespace NewHorizons.External.Configs
if (tornado.downwards)
tornado.type = PropModule.TornadoInfo.TornadoType.Downwards;
if (Props?.audioVolumes != null)
{
if (Volumes == null) Volumes = new VolumesModule();
if (Volumes.audioVolumes == null) Volumes.audioVolumes = new VolumesModule.AudioVolumeInfo[0];
Volumes.audioVolumes = Volumes.audioVolumes.Concat(Props.audioVolumes).ToArray();
}
if (Props?.reveal != null)
{
if (Volumes == null) Volumes = new VolumesModule();
if (Volumes.revealVolumes == null) Volumes.revealVolumes = new VolumesModule.RevealVolumeInfo[0];
Volumes.revealVolumes = Volumes.revealVolumes.Concat(Props.reveal).ToArray();
}
if (Base.sphereOfInfluence != 0f) Base.soiOverride = Base.sphereOfInfluence;
// Moved a bunch of stuff off of shiplog module to star system module because it didnt exist when we made this
@ -377,10 +405,20 @@ namespace NewHorizons.External.Configs
if (!string.IsNullOrEmpty(Cloak.audioFilePath)) Cloak.audio = Cloak.audioFilePath;
}
// Rings are no longer variable size module
// Ring is now a list so you can have many per planet
if (Ring != null)
{
if (Ring.curve != null) Ring.scaleCurve = Ring.curve;
if (Rings == null) Rings = new RingModule[0];
Rings = Rings.Append(Ring).ToArray();
}
// Rings are no longer variable size module
if (Rings != null)
{
foreach (var ring in Rings)
{
if (ring.curve != null) ring.scaleCurve = ring.curve;
}
}
}
}

View File

@ -14,6 +14,11 @@ namespace NewHorizons.External.Configs
[JsonObject]
public class StarSystemConfig
{
/// <summary>
/// An override value for the far clip plane. Allows you to see farther.
/// </summary>
public float farClipPlaneOverride;
/// <summary>
/// Whether this system can be warped to via the warp drive. If you set factRequiredForWarp, this will be true.
/// </summary>
@ -102,6 +107,11 @@ namespace NewHorizons.External.Configs
/// </summary>
public CuriosityColorInfo[] curiosities;
/// <summary>
/// Extra data that may be used by extension mods
/// </summary>
public object extras;
public class NomaiCoordinates
{
[MinLength(2)]

View File

@ -30,6 +30,8 @@ namespace NewHorizons.External.Modules
[EnumMember(Value = @"quantumMoon")] QuantumMoon = 1,
[EnumMember(Value = @"basic")] Basic = 2,
[EnumMember(Value = @"transparent")] Transparent = 3,
}
[JsonObject]
@ -100,6 +102,11 @@ namespace NewHorizons.External.Modules
/// </summary>
public bool useAtmosphereShader;
/// <summary>
/// Whether this atmosphere will have flames appear when your ship goes a certain speed.
/// </summary>
[DefaultValue(true)] public bool hasShockLayer = true;
/// <summary>
/// Minimum speed that your ship can go in the atmosphere where flames will appear.
/// </summary>

View File

@ -48,11 +48,6 @@ namespace NewHorizons.External.Modules
/// </summary>
public RaftInfo[] rafts;
/// <summary>
/// Add triggers that reveal parts of the ship log on this planet
/// </summary>
public RevealInfo[] reveal;
/// <summary>
/// Scatter props around this planet's surface
/// </summary>
@ -83,11 +78,6 @@ namespace NewHorizons.External.Modules
/// </summary>
public SingularityModule[] singularities;
/// <summary>
/// Add audio volumes to this planet
/// </summary>
public AudioVolumeInfo[] audioVolumes;
/// <summary>
/// Add signalscope signals to this planet
/// </summary>
@ -98,6 +88,10 @@ namespace NewHorizons.External.Modules
/// </summary>
public RemoteInfo[] remotes;
[Obsolete("reveal is deprecated. Use Volumes->revealVolumes instead.")] public VolumesModule.RevealVolumeInfo[] reveal;
[Obsolete("audioVolumes is deprecated. Use Volumes->audioVolumes instead.")] public VolumesModule.AudioVolumeInfo[] audioVolumes;
[JsonObject]
public class ScatterInfo
{
@ -145,6 +139,16 @@ namespace NewHorizons.External.Modules
/// The highest height that these objects will be placed at (only relevant if there's a heightmap)
/// </summary>
public float? maxHeight;
/// <summary>
/// Should we try to prevent overlap between the scattered details? True by default. If it's affecting load times turn it off.
/// </summary>
[DefaultValue(true)] public bool preventOverlap = true;
/// <summary>
/// Should this detail stay loaded even if you're outside the sector (good for very large props)
/// </summary>
public bool keepLoaded;
}
[JsonObject]
@ -433,55 +437,6 @@ namespace NewHorizons.External.Modules
public string xmlFile;
}
[JsonObject]
public class RevealInfo
{
[JsonConverter(typeof(StringEnumConverter))]
public enum RevealVolumeType
{
[EnumMember(Value = @"enter")] Enter = 0,
[EnumMember(Value = @"observe")] Observe = 1,
[EnumMember(Value = @"snapshot")] Snapshot = 2
}
/// <summary>
/// The max view angle (in degrees) the player can see the volume with to unlock the fact (`observe` only)
/// </summary>
public float maxAngle = 180f; // Observe Only
/// <summary>
/// The max distance the user can be away from the volume to reveal the fact (`snapshot` and `observe` only)
/// </summary>
public float maxDistance = -1f; // Snapshot & Observe Only
/// <summary>
/// The position to place this volume at
/// </summary>
public MVector3 position;
/// <summary>
/// The radius of this reveal volume
/// </summary>
public float radius = 1f;
/// <summary>
/// What needs to be done to the volume to unlock the facts
/// </summary>
[DefaultValue("enter")] public RevealVolumeType revealOn = RevealVolumeType.Enter;
/// <summary>
/// A list of facts to reveal
/// </summary>
public string[] reveals;
/// <summary>
/// An achievement to unlock. Optional.
/// </summary>
public string achievementID;
}
[JsonObject]
public class EntryLocationInfo
{
@ -818,30 +773,6 @@ namespace NewHorizons.External.Modules
[DefaultValue(1f)] public float probability = 1f;
}
[JsonObject]
public class AudioVolumeInfo
{
/// <summary>
/// The location of this audio volume. Optional (will default to 0,0,0).
/// </summary>
public MVector3 position;
/// <summary>
/// The radius of this audio volume
/// </summary>
public float radius;
/// <summary>
/// The audio to use. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list.
/// </summary>
public string audio;
/// <summary>
/// The audio track of this audio volume
/// </summary>
[DefaultValue("environment")] public AudioMixerTrackName track = AudioMixerTrackName.Environment;
}
[JsonObject]
public class RemoteInfo
{
@ -1002,25 +933,4 @@ namespace NewHorizons.External.Modules
}
}
}
[JsonConverter(typeof(StringEnumConverter))]
public enum AudioMixerTrackName
{
[EnumMember(Value = @"undefined")] Undefined = 0,
[EnumMember(Value = @"menu")] Menu = 1,
[EnumMember(Value = @"music")] Music = 2,
[EnumMember(Value = @"environment")] Environment = 4,
[EnumMember(Value = @"environmentUnfiltered")] Environment_Unfiltered = 5,
[EnumMember(Value = @"endTimesSfx")] EndTimes_SFX = 8,
[EnumMember(Value = @"signal")] Signal = 16,
[EnumMember(Value = @"death")] Death = 32,
[EnumMember(Value = @"player")] Player = 64,
[EnumMember(Value = @"playerExternal")] Player_External = 65,
[EnumMember(Value = @"ship")] Ship = 128,
[EnumMember(Value = @"map")] Map = 256,
[EnumMember(Value = @"endTimesMusic")] EndTimes_Music = 512,
[EnumMember(Value = @"muffleWhileRafting")] MuffleWhileRafting = 1024,
[EnumMember(Value = @"muffleIndoors")] MuffleIndoors = 2048,
[EnumMember(Value = @"slideReelMusic")] SlideReelMusic = 4096,
}
}

View File

@ -62,5 +62,10 @@ namespace NewHorizons.External.Modules
/// Fade rings in/out over time. Optional. Value between 0-1, time is in minutes.
/// </summary>
public TimeValuePair[] opacityCurve;
/// <summary>
/// An optional rename of this object
/// </summary>
public string rename;
}
}

View File

@ -0,0 +1,247 @@
using NewHorizons.Utility;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.External.Modules
{
[JsonObject]
public class VolumesModule
{
/// <summary>
/// Add audio volumes to this planet.
/// </summary>
public AudioVolumeInfo[] audioVolumes;
/// <summary>
/// Add hazard volumes to this planet.
/// </summary>
public HazardVolumeInfo[] hazardVolumes;
/// <summary>
/// Add interference volumes to this planet.
/// </summary>
public VolumeInfo[] interferenceVolumes;
/// <summary>
/// Add insulating volumes to this planet. These will stop electricty hazard volumes from affecting you (just like the jellyfish).
/// </summary>
public VolumeInfo[] insulatingVolumes;
/// <summary>
/// Add map restriction volumes to this planet.
/// </summary>
public VolumeInfo[] mapRestrictionVolumes;
/// <summary>
/// Add notification volumes to this planet.
/// </summary>
public NotificationVolumeInfo[] notificationVolumes;
/// <summary>
/// Add triggers that reveal parts of the ship log on this planet.
/// </summary>
public RevealVolumeInfo[] revealVolumes;
/// <summary>
/// Add reverb volumes to this planet. Great for echoes in caves.
/// </summary>
public VolumeInfo[] reverbVolumes;
[JsonObject]
public class VolumeInfo
{
/// <summary>
/// The location of this volume. Optional (will default to 0,0,0).
/// </summary>
public MVector3 position;
/// <summary>
/// The radius of this volume.
/// </summary>
public float radius = 1f;
/// <summary>
/// The relative path from the planet to the parent of this object. Optional (will default to the root sector).
/// </summary>
public string parentPath;
/// <summary>
/// An optional rename of this volume.
/// </summary>
public string rename;
}
[JsonObject]
public class RevealVolumeInfo : VolumeInfo
{
[JsonConverter(typeof(StringEnumConverter))]
public enum RevealVolumeType
{
[EnumMember(Value = @"enter")] Enter = 0,
[EnumMember(Value = @"observe")] Observe = 1,
[EnumMember(Value = @"snapshot")] Snapshot = 2
}
/// <summary>
/// The max view angle (in degrees) the player can see the volume with to unlock the fact (`observe` only)
/// </summary>
public float maxAngle = 180f; // Observe Only
/// <summary>
/// The max distance the user can be away from the volume to reveal the fact (`snapshot` and `observe` only)
/// </summary>
public float maxDistance = -1f; // Snapshot & Observe Only
/// <summary>
/// What needs to be done to the volume to unlock the facts
/// </summary>
[DefaultValue("enter")] public RevealVolumeType revealOn = RevealVolumeType.Enter;
/// <summary>
/// A list of facts to reveal
/// </summary>
public string[] reveals;
/// <summary>
/// An achievement to unlock. Optional.
/// </summary>
public string achievementID;
}
[JsonObject]
public class AudioVolumeInfo : VolumeInfo
{
/// <summary>
/// The audio to use. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list.
/// </summary>
public string audio;
/// <summary>
/// The audio track of this audio volume
/// </summary>
[DefaultValue("environment")] public AudioMixerTrackName track = AudioMixerTrackName.Environment;
/// <summary>
/// Whether to loop this audio while in this audio volume or just play it once
/// </summary>
[DefaultValue(true)] public bool loop = true;
}
[JsonObject]
public class NotificationVolumeInfo : VolumeInfo
{
/// <summary>
/// What the notification will show for.
/// </summary>
[DefaultValue("all")] public NotificationTarget target = NotificationTarget.All;
/// <summary>
/// The notification that will play when you enter this volume.
/// </summary>
public NotificationInfo entryNotification;
/// <summary>
/// The notification that will play when you exit this volume.
/// </summary>
public NotificationInfo exitNotification;
[JsonObject]
public class NotificationInfo
{
/// <summary>
/// The message that will be displayed.
/// </summary>
public string displayMessage;
/// <summary>
/// The duration this notification will be displayed.
/// </summary>
[DefaultValue(5f)] public float duration = 5f;
}
[JsonConverter(typeof(StringEnumConverter))]
public enum NotificationTarget
{
[EnumMember(Value = @"all")] All = 0,
[EnumMember(Value = @"ship")] Ship = 1,
[EnumMember(Value = @"player")] Player = 2,
}
}
[JsonObject]
public class HazardVolumeInfo : VolumeInfo
{
/// <summary>
/// The type of hazard for this volume.
/// </summary>
[DefaultValue("general")] public HazardType type = HazardType.GENERAL;
/// <summary>
/// The amount of damage you will take per second while inside this volume.
/// </summary>
[DefaultValue(10f)] public float damagePerSecond = 10f;
/// <summary>
/// The type of damage you will take when you first touch this volume.
/// </summary>
[DefaultValue("impact")] public InstantDamageType firstContactDamageType = InstantDamageType.Impact;
/// <summary>
/// The amount of damage you will take when you first touch this volume.
/// </summary>
public float firstContactDamage;
[JsonConverter(typeof(StringEnumConverter))]
public enum HazardType
{
[EnumMember(Value = @"none")] NONE = 0,
[EnumMember(Value = @"general")] GENERAL = 1,
[EnumMember(Value = @"ghostMatter")] DARKMATTER = 2,
[EnumMember(Value = @"heat")] HEAT = 4,
[EnumMember(Value = @"fire")] FIRE = 8,
[EnumMember(Value = @"sandfall")] SANDFALL = 16,
[EnumMember(Value = @"electricity")] ELECTRICITY = 32,
[EnumMember(Value = @"rapids")] RAPIDS = 64
}
[JsonConverter(typeof(StringEnumConverter))]
public enum InstantDamageType
{
[EnumMember(Value = @"impact")] Impact,
[EnumMember(Value = @"puncture")] Puncture,
[EnumMember(Value = @"electrical")] Electrical
}
}
}
[JsonConverter(typeof(StringEnumConverter))]
public enum AudioMixerTrackName
{
[EnumMember(Value = @"undefined")] Undefined = 0,
[EnumMember(Value = @"menu")] Menu = 1,
[EnumMember(Value = @"music")] Music = 2,
[EnumMember(Value = @"environment")] Environment = 4,
[EnumMember(Value = @"environmentUnfiltered")] Environment_Unfiltered = 5,
[EnumMember(Value = @"endTimesSfx")] EndTimes_SFX = 8,
[EnumMember(Value = @"signal")] Signal = 16,
[EnumMember(Value = @"death")] Death = 32,
[EnumMember(Value = @"player")] Player = 64,
[EnumMember(Value = @"playerExternal")] Player_External = 65,
[EnumMember(Value = @"ship")] Ship = 128,
[EnumMember(Value = @"map")] Map = 256,
[EnumMember(Value = @"endTimesMusic")] EndTimes_Music = 512,
[EnumMember(Value = @"muffleWhileRafting")] MuffleWhileRafting = 1024,
[EnumMember(Value = @"muffleIndoors")] MuffleIndoors = 2048,
[EnumMember(Value = @"slideReelMusic")] SlideReelMusic = 4096,
}
}

View File

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using NewHorizons.Utility;
@ -11,12 +11,15 @@ namespace NewHorizons.External
private static string _activeProfileName;
private static readonly string FileName = "save.json";
// This is its own method so it can be patched by NH-QSB compat
public static string GetProfileName() => StandaloneProfileManager.SharedInstance?.currentProfile?.profileName;
public static void Load()
{
_activeProfileName = StandaloneProfileManager.SharedInstance?.currentProfile?.profileName;
_activeProfileName = GetProfileName();
if (_activeProfileName == null)
{
Logger.LogError("Couldn't find active profile, are you on Gamepass?");
Logger.LogWarning("Couldn't find active profile, are you on Gamepass?");
_activeProfileName = "XboxGamepassDefaultProfile";
}
@ -79,12 +82,13 @@ namespace NewHorizons.External
KnownFrequencies = new List<string>();
KnownSignals = new List<string>();
NewlyRevealedFactIDs = new List<string>();
PopupsRead = new List<string>();
}
public List<string> KnownFrequencies { get; }
public List<string> KnownSignals { get; }
public List<string> NewlyRevealedFactIDs { get; }
public List<string> PopupsRead { get; }
}
#region Frequencies
@ -152,5 +156,21 @@ namespace NewHorizons.External
}
#endregion
#region Read popups
public static void ReadOneTimePopup(string id)
{
_activeProfile?.PopupsRead.Add(id);
Save();
}
public static bool HasReadOneTimePopup(string id)
{
// To avoid spam, we'll just say the popup has been read if we can't load the profile
return _activeProfile?.PopupsRead.Contains(id) ?? true;
}
#endregion
}
}

View File

@ -2,6 +2,7 @@ using NewHorizons.Utility;
using OWML.Common;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
@ -65,7 +66,7 @@ namespace NewHorizons.Handlers
var id = mod.ModHelper.Manifest.UniqueName + "_" + audioPath;
if (_customAudioTypes.TryGetValue(id, out audioType)) return audioType;
var audioClip = AudioUtilities.LoadAudio(mod.ModHelper.Manifest.ModFolderPath + "/" + audioPath);
var audioClip = AudioUtilities.LoadAudio(Path.Combine(mod.ModHelper.Manifest.ModFolderPath, audioPath));
if (audioClip == null)
{

View File

@ -39,7 +39,7 @@ namespace NewHorizons.Handlers
private static void AddCreditsSection(string sectionName, string[] entries, ref XmlDocument xml)
{
var finalCredits = xml.SelectSingleNode("Credits/section");
var finalCredits = xml.SelectSingleNode("Credits/section[@name='CreditsFinal']");
/*
* Looks bad, would need more customization, complicated, messes up music timing, wont do for now
@ -134,11 +134,8 @@ namespace NewHorizons.Handlers
{
var rootSection = MakeNode(doc, "section", new Dictionary<string, string>()
{
{ "platform", "All" },
{ "type", "Scroll" },
{ "scrollDuration", "214" },
{ "spacing", "12" },
{ "width", "1590" }
{ "name", title },
{ "credits-type", "Final Fast Krazy" }
});
var titleLayout = MakeNode(doc, "layout", new Dictionary<string, string>()

View File

@ -0,0 +1,75 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace NewHorizons.Handlers
{
using InterferenceVolume = Components.Volumes.InterferenceVolume;
public static class InterferenceHandler
{
private static List<InterferenceVolume> _playerInterference;
private static List<InterferenceVolume> _probeInterference;
private static List<InterferenceVolume> _shipInterference;
public static void Init()
{
_playerInterference = new List<InterferenceVolume>();
_probeInterference = new List<InterferenceVolume>();
_shipInterference = new List<InterferenceVolume>();
}
public static bool PlayerHasInterference() => _playerInterference.Any(volume => volume != null);
public static bool ProbeHasInterference() => _probeInterference.Any(volume => volume != null);
public static bool ShipHasInterference() => _shipInterference.Any(volume => volume != null);
public static bool IsPlayerSameAsProbe()
{
_playerInterference.RemoveAll(volume => volume == null);
return _playerInterference.All(_probeInterference.Contains) && _playerInterference.Count == _probeInterference.Count;
}
public static bool IsPlayerSameAsShip()
{
_playerInterference.RemoveAll(volume => volume == null);
return _playerInterference.All(_shipInterference.Contains) && _playerInterference.Count == _shipInterference.Count;
}
public static void OnPlayerEnterInterferenceVolume(InterferenceVolume interferenceVolume)
{
_playerInterference.SafeAdd(interferenceVolume);
GlobalMessenger.FireEvent("RefreshHUDVisibility");
}
public static void OnPlayerExitInterferenceVolume(InterferenceVolume interferenceVolume)
{
_playerInterference.Remove(interferenceVolume);
GlobalMessenger.FireEvent("RefreshHUDVisibility");
}
public static void OnProbeEnterInterferenceVolume(InterferenceVolume interferenceVolume)
{
_probeInterference.SafeAdd(interferenceVolume);
GlobalMessenger.FireEvent("RefreshHUDVisibility");
}
public static void OnProbeExitInterferenceVolume(InterferenceVolume interferenceVolume)
{
_probeInterference.Remove(interferenceVolume);
GlobalMessenger.FireEvent("RefreshHUDVisibility");
}
public static void OnShipEnterInterferenceVolume(InterferenceVolume interferenceVolume)
{
_shipInterference.SafeAdd(interferenceVolume);
GlobalMessenger.FireEvent("RefreshHUDVisibility");
}
public static void OnShipExitInterferenceVolume(InterferenceVolume interferenceVolume)
{
_shipInterference.Remove(interferenceVolume);
GlobalMessenger.FireEvent("RefreshHUDVisibility");
}
}
}

View File

@ -3,8 +3,10 @@ using NewHorizons.Builder.Body;
using NewHorizons.Builder.General;
using NewHorizons.Builder.Orbital;
using NewHorizons.Builder.Props;
using NewHorizons.Components;
using NewHorizons.Builder.Volumes;
using NewHorizons.Components.Orbital;
using NewHorizons.Components.Quantum;
using NewHorizons.Components.Stars;
using NewHorizons.OtherMods.OWRichPresence;
using NewHorizons.Utility;
using System;
@ -56,8 +58,9 @@ namespace NewHorizons.Handlers
GameObject.Destroy(starLightGO.GetComponent<Light>());
starLightGO.name = "StarLightController";
starLightGO.AddComponent<StarLightController>();
StarLightController.AddStar(starController);
starLightGO.AddComponent<SunLightEffectsController>();
SunLightEffectsController.AddStar(starController);
SunLightEffectsController.AddStarLight(starController.Light);
starLightGO.SetActive(true);
@ -248,6 +251,16 @@ namespace NewHorizons.Handlers
}
}
}
try
{
Main.Instance.OnPlanetLoaded?.Invoke(body.Config.name);
}
catch (Exception e)
{
Logger.LogError($"Error in event handler for OnPlanetLoaded on body {body.Config.name}: {e}");
}
return true;
}
@ -487,7 +500,10 @@ namespace NewHorizons.Handlers
{
var (star, starController, starEvolutionController) = StarBuilder.Make(go, sector, body.Config.Star, body.Mod, body.Config.isStellarRemnant);
if (starController != null) StarLightController.AddStar(starController);
if (starController != null) SunLightEffectsController.AddStar(starController);
var starLight = star.FindChild("SunLight");
if (starLight != null) SunLightEffectsController.AddStarLight(starLight.GetComponent<Light>());
// If it has an evolution controller that means it will die -> we make a remnant (unless its a remnant)
if (starEvolutionController != null && !body.Config.isStellarRemnant)
@ -536,9 +552,12 @@ namespace NewHorizons.Handlers
}
}
if (body.Config.Ring != null)
if (body.Config.Rings != null)
{
RingBuilder.Make(go, sector, body.Config.Ring, body.Mod);
foreach (var ring in body.Config.Rings)
{
RingBuilder.Make(go, sector, ring, body.Mod);
}
}
if (body.Config.AsteroidBelt != null)
@ -579,7 +598,7 @@ namespace NewHorizons.Handlers
if (!string.IsNullOrEmpty(body.Config.Atmosphere?.clouds?.texturePath))
{
CloudsBuilder.Make(go, sector, body.Config.Atmosphere, willHaveCloak, body.Mod);
SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, body.Config.Water, surfaceSize);
if (body.Config.Atmosphere.clouds.cloudsPrefab != External.Modules.CloudPrefabType.Transparent) SunOverrideBuilder.Make(go, sector, body.Config.Atmosphere, body.Config.Water, surfaceSize);
}
if (body.Config.Atmosphere.hasRain || body.Config.Atmosphere.hasSnow)
@ -598,6 +617,11 @@ namespace NewHorizons.Handlers
PropBuildManager.Make(go, sector, rb, body.Config, body.Mod);
}
if (body.Config.Volumes != null)
{
VolumesBuildManager.Make(go, sector, rb, body.Config, body.Mod);
}
if (body.Config.Funnel != null)
{
FunnelBuilder.Make(go, go.GetComponentInChildren<ConstantForceDetector>(), rb, body.Config.Funnel);

View File

@ -1,4 +1,4 @@
using NewHorizons.Components;
using NewHorizons.Components.Stars;
using NewHorizons.Utility;
using OWML.Utils;
using System;
@ -117,7 +117,8 @@ namespace NewHorizons.Handlers
break;
case AstroObject.Name.Sun:
var starController = ao.gameObject.GetComponent<StarController>();
StarLightController.RemoveStar(starController);
SunLightEffectsController.RemoveStar(starController);
SunLightEffectsController.RemoveStarLight(ao.transform.Find("Sector_SUN/Effects_SUN/SunLight").GetComponent<Light>());
GameObject.Destroy(starController);
var audio = ao.GetComponentInChildren<SunSurfaceAudioController>();

View File

@ -1,4 +1,4 @@
using NewHorizons.Components;
using NewHorizons.Components.ShipLog;
using NewHorizons.Utility;
using System.Collections.Generic;
using UnityEngine;

View File

@ -89,7 +89,7 @@ namespace NewHorizons.Handlers
heightMap.minHeight = body.Config.HeightMap.minHeight * size / body.Config.HeightMap.maxHeight;
heightMap.stretch = body.Config.HeightMap.stretch;
}
if (body.Config.Atmosphere?.clouds?.texturePath != null)
if (body.Config.Atmosphere?.clouds?.texturePath != null && body.Config.Atmosphere?.clouds?.cloudsPrefab != CloudPrefabType.Transparent)
{
// Hacky but whatever I just want a sphere
size = Mathf.Clamp(body.Config.Atmosphere.size / 10, minSize, maxSize);
@ -107,13 +107,16 @@ namespace NewHorizons.Handlers
}
pivot.name = "Pivot";
if (body.Config.Ring != null)
if (body.Config.Rings != null && body.Config.Rings.Length > 0)
{
RingModule newRing = new RingModule();
newRing.innerRadius = size * 1.2f;
newRing.outerRadius = size * 2f;
newRing.texture = body.Config.Ring.texture;
var ring = RingBuilder.Make(titleScreenGO, null, newRing, body.Mod);
foreach (var ring in body.Config.Rings)
{
RingModule newRing = new RingModule();
newRing.innerRadius = size * 1.2f;
newRing.outerRadius = size * 2f;
newRing.texture = ring.texture;
RingBuilder.Make(titleScreenGO, null, newRing, body.Mod);
}
titleScreenGO.transform.localScale = Vector3.one * 0.8f;
}

View File

@ -66,9 +66,10 @@ namespace NewHorizons.Handlers
foreach (var originalKey in config.ShipLogDictionary.Keys)
{
var key = originalKey.Replace("&lt;", "<").Replace("&gt;", ">").Replace("<![CDATA[", "").Replace("]]>", "");
var value = config.ShipLogDictionary[originalKey].Replace("&lt;", "<").Replace("&gt;", ">").Replace("<![CDATA[", "").Replace("]]>", "");
if (!_shipLogTranslationDictionary[language].ContainsKey(key)) _shipLogTranslationDictionary[language].Add(key, config.ShipLogDictionary[originalKey]);
else _shipLogTranslationDictionary[language][key] = config.ShipLogDictionary[originalKey];
if (!_shipLogTranslationDictionary[language].ContainsKey(key)) _shipLogTranslationDictionary[language].Add(key, value);
else _shipLogTranslationDictionary[language][key] = value;
}
}
@ -78,9 +79,10 @@ namespace NewHorizons.Handlers
foreach (var originalKey in config.DialogueDictionary.Keys)
{
var key = originalKey.Replace("&lt;", "<").Replace("&gt;", ">").Replace("<![CDATA[", "").Replace("]]>", "");
var value = config.DialogueDictionary[originalKey].Replace("&lt;", "<").Replace("&gt;", ">").Replace("<![CDATA[", "").Replace("]]>", "");
if (!_dialogueTranslationDictionary[language].ContainsKey(key)) _dialogueTranslationDictionary[language].Add(key, config.DialogueDictionary[originalKey]);
else _dialogueTranslationDictionary[language][key] = config.DialogueDictionary[originalKey];
if (!_dialogueTranslationDictionary[language].ContainsKey(key)) _dialogueTranslationDictionary[language].Add(key, value);
else _dialogueTranslationDictionary[language][key] = value;
}
}
@ -90,16 +92,17 @@ namespace NewHorizons.Handlers
foreach (var originalKey in config.UIDictionary.Keys)
{
var key = originalKey.Replace("&lt;", "<").Replace("&gt;", ">").Replace("<![CDATA[", "").Replace("]]>", "");
var value = config.UIDictionary[originalKey].Replace("&lt;", "<").Replace("&gt;", ">").Replace("<![CDATA[", "").Replace("]]>", "");
if (!_uiTranslationDictionary[language].ContainsKey(key)) _uiTranslationDictionary[language].Add(key, config.UIDictionary[originalKey]);
else _uiTranslationDictionary[language][key] = config.UIDictionary[originalKey];
if (!_uiTranslationDictionary[language].ContainsKey(key)) _uiTranslationDictionary[language].Add(key, value);
else _uiTranslationDictionary[language][key] = value;
}
}
}
public static void AddDialogue(string rawText, params string[] rawPreText)
public static void AddDialogue(string rawText, bool trimRawTextForKey = false, params string[] rawPreText)
{
var key = string.Join(string.Empty, rawPreText) + rawText;
var key = string.Join(string.Empty, rawPreText) + (trimRawTextForKey? rawText.Trim() : rawText);
var text = GetTranslation(rawText, TextType.DIALOGUE);

View File

@ -1,4 +1,4 @@
using NewHorizons.Components;
using NewHorizons.Components.ShipLog;
using NewHorizons.Utility;
using System;
using System.Collections.Generic;

View File

@ -43,6 +43,22 @@ namespace NewHorizons
/// </summary>
UnityEvent<string> GetStarSystemLoadedEvent();
/// <summary>
/// An event invoked when NH has finished a planet for a star system.
/// Gives the name of the planet that was just loaded.
/// </summary>
UnityEvent<string> GetBodyLoadedEvent();
/// <summary>
/// Uses JSONPath to query a body
/// </summary>
object QueryBody(Type outType, string bodyName, string path);
/// <summary>
/// Uses JSONPath to query a system
/// </summary>
object QuerySystem(Type outType, string path);
/// <summary>
/// Allows you to overwrite the default system. This is where the player is respawned after dying.
/// </summary>

View File

@ -1,16 +1,20 @@
using HarmonyLib;
using NewHorizons.OtherMods.AchievementsPlus;
using NewHorizons.Builder.Atmosphere;
using NewHorizons.Builder.Body;
using NewHorizons.Builder.Props;
using NewHorizons.Components;
using NewHorizons.Components.Fixers;
using NewHorizons.Components.SizeControllers;
using NewHorizons.External;
using NewHorizons.External.Configs;
using NewHorizons.Handlers;
using NewHorizons.OtherMods.AchievementsPlus;
using NewHorizons.OtherMods.MenuFramework;
using NewHorizons.OtherMods.OWRichPresence;
using NewHorizons.OtherMods.VoiceActing;
using NewHorizons.Utility;
using NewHorizons.Utility.DebugMenu;
using NewHorizons.Utility.DebugUtilities;
using NewHorizons.OtherMods.VoiceActing;
using OWML.Common;
using OWML.ModHelper;
using System;
@ -22,8 +26,6 @@ using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using Logger = NewHorizons.Utility.Logger;
using NewHorizons.OtherMods.OWRichPresence;
using NewHorizons.Components.SizeControllers;
namespace NewHorizons
{
@ -68,6 +70,7 @@ namespace NewHorizons
public class StarSystemEvent : UnityEvent<string> { }
public StarSystemEvent OnChangeStarSystem;
public StarSystemEvent OnStarSystemLoaded;
public StarSystemEvent OnPlanetLoaded;
// For warping to the eye system
private GameObject _ship;
@ -94,9 +97,9 @@ namespace NewHorizons
DebugMenu.UpdatePauseMenuButton();
}
if (VerboseLogs) Logger.UpdateLogLevel(Logger.LogType.Verbose);
else if (Debug) Logger.UpdateLogLevel(Logger.LogType.Log);
else Logger.UpdateLogLevel(Logger.LogType.Error);
if (VerboseLogs) Logger.UpdateLogLevel(Logger.LogType.Verbose);
else if (Debug) Logger.UpdateLogLevel(Logger.LogType.Log);
else Logger.UpdateLogLevel(Logger.LogType.Error);
_defaultSystemOverride = config.GetSettingsValue<string>("Default System Override");
@ -119,14 +122,14 @@ namespace NewHorizons
_wasConfigured = true;
}
public static void ResetConfigs(bool resetTranslation = true)
public void ResetConfigs(bool resetTranslation = true)
{
BodyDict.Clear();
SystemDict.Clear();
BodyDict["SolarSystem"] = new List<NewHorizonsBody>();
BodyDict["EyeOfTheUniverse"] = new List<NewHorizonsBody>(); // Keep this empty tho fr
SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(), Instance)
SystemDict["SolarSystem"] = new NewHorizonsSystem("SolarSystem", new StarSystemConfig(), "", Instance)
{
Config =
{
@ -142,7 +145,7 @@ namespace NewHorizons
}
}
};
SystemDict["EyeOfTheUniverse"] = new NewHorizonsSystem("EyeOfTheUniverse", new StarSystemConfig(), Instance)
SystemDict["EyeOfTheUniverse"] = new NewHorizonsSystem("EyeOfTheUniverse", new StarSystemConfig(), "", Instance)
{
Config =
{
@ -158,9 +161,18 @@ namespace NewHorizons
}
};
if (!resetTranslation) return;
TranslationHandler.ClearTables();
TextTranslation.Get().SetLanguage(TextTranslation.Get().GetLanguage());
if (resetTranslation)
{
TranslationHandler.ClearTables();
TextTranslation.Get().SetLanguage(TextTranslation.Get().GetLanguage());
}
LoadTranslations(Path.Combine(Instance.ModHelper.Manifest.ModFolderPath, "Assets/"), this);
}
public void Awake()
{
Instance = this;
}
public void Start()
@ -170,11 +182,11 @@ namespace NewHorizons
OnChangeStarSystem = new StarSystemEvent();
OnStarSystemLoaded = new StarSystemEvent();
OnPlanetLoaded = new StarSystemEvent();
SceneManager.sceneLoaded += OnSceneLoaded;
SceneManager.sceneUnloaded += OnSceneUnloaded;
Instance = this;
GlobalMessenger<DeathType>.AddListener("PlayerDeath", OnDeath);
GlobalMessenger.AddListener("WakeUp", OnWakeUp);
@ -198,6 +210,7 @@ namespace NewHorizons
Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => _firstLoad = false);
Instance.ModHelper.Menus.PauseMenu.OnInit += DebugReload.InitializePauseMenu;
MenuHandler.Init();
AchievementHandler.Init();
VoiceHandler.Init();
RichPresenceHandler.Init();
@ -303,14 +316,12 @@ namespace NewHorizons
AstroObjectLocator.Init();
StreamingHandler.Init();
AudioTypeHandler.Init();
InterferenceHandler.Init();
RemoteHandler.Init();
AtmosphereBuilder.Init();
BrambleNodeBuilder.Init(BodyDict[CurrentStarSystem].Select(x => x.Config).Where(x => x.Bramble?.dimension != null).ToArray());
StarEvolutionController.Init();
// Has to go before loading planets else the Discord Rich Presence mod won't show the right text
LoadTranslations(ModHelper.Manifest.ModFolderPath + "Assets/", this);
if (isSolarSystem)
{
foreach (var supernovaPlanetEffectController in GameObject.FindObjectsOfType<SupernovaPlanetEffectController>())
@ -343,6 +354,7 @@ namespace NewHorizons
var map = GameObject.FindObjectOfType<MapController>();
if (map != null) map._maxPanDistance = FurthestOrbit * 1.5f;
// Fix the map satellite
SearchUtilities.Find("HearthianMapSatellite_Body", false).AddComponent<MapSatelliteOrbitFix>();
@ -409,7 +421,7 @@ namespace NewHorizons
var ssrLight = solarSystemRoot.AddComponent<Light>();
ssrLight.innerSpotAngle = 0;
ssrLight.spotAngle = 179;
ssrLight.range = Main.FurthestOrbit * (4f/3f);
ssrLight.range = Main.FurthestOrbit * (4f / 3f);
ssrLight.intensity = 0.001f;
var fluid = playerBody.FindChild("PlayerDetector").GetComponent<DynamicFluidDetector>();
@ -483,10 +495,22 @@ namespace NewHorizons
}
var folder = mod.ModHelper.Manifest.ModFolderPath;
var systemsFolder = Path.Combine(folder, "systems");
var planetsFolder = Path.Combine(folder, "planets");
// Load systems first so that when we load bodies later we can check for missing ones
if (Directory.Exists(folder + @"systems\"))
if (Directory.Exists(systemsFolder))
{
foreach (var file in Directory.GetFiles(folder + @"systems\", "*.json?", SearchOption.AllDirectories))
var systemFiles = Directory.GetFiles(systemsFolder, "*.json", SearchOption.AllDirectories)
.Concat(Directory.GetFiles(systemsFolder, "*.jsonc", SearchOption.AllDirectories))
.ToArray();
if(systemFiles.Length == 0)
{
Logger.LogVerbose($"Found no JSON files in systems folder: {systemsFolder}");
}
foreach (var file in systemFiles)
{
var name = Path.GetFileNameWithoutExtension(file);
@ -500,7 +524,7 @@ namespace NewHorizons
if (starSystemConfig.startHere)
{
// We always want to allow mods to overwrite setting the main SolarSystem as default but not the other way around
if (name != "SolarSystem")
if (name != "SolarSystem")
{
SetDefaultSystem(name);
_currentStarSystem = name;
@ -515,13 +539,22 @@ namespace NewHorizons
}
else
{
SystemDict[name] = new NewHorizonsSystem(name, starSystemConfig, mod);
SystemDict[name] = new NewHorizonsSystem(name, starSystemConfig, relativePath, mod);
}
}
}
if (Directory.Exists(folder + "planets"))
if (Directory.Exists(planetsFolder))
{
foreach (var file in Directory.GetFiles(folder + @"planets\", "*.json?", SearchOption.AllDirectories))
var planetFiles = Directory.GetFiles(planetsFolder, "*.json", SearchOption.AllDirectories)
.Concat(Directory.GetFiles(planetsFolder, "*.jsonc", SearchOption.AllDirectories))
.ToArray();
if(planetFiles.Length == 0)
{
Logger.LogVerbose($"Found no JSON files in planets folder: {planetsFolder}");
}
foreach (var file in planetFiles)
{
var relativeDirectory = file.Replace(folder, "");
var body = LoadConfig(mod, relativeDirectory);
@ -562,6 +595,7 @@ namespace NewHorizons
if (addonConfig.achievements != null) AchievementHandler.RegisterAddon(addonConfig, mod as ModBehaviour);
if (addonConfig.credits != null) CreditsHandler.RegisterCredits(mod.ModHelper.Manifest.Name, addonConfig.credits);
if (!string.IsNullOrEmpty(addonConfig.popupMessage)) MenuHandler.RegisterOneTimePopup(mod, addonConfig.popupMessage);
}
private void LoadTranslations(string folder, IModBehaviour mod)
@ -601,6 +635,7 @@ namespace NewHorizons
if (config == null)
{
Logger.LogError($"Couldn't load {relativePath}. Is your Json formatted correctly?");
MenuHandler.RegisterFailedConfig(Path.GetFileName(relativePath));
return null;
}
@ -616,7 +651,7 @@ namespace NewHorizons
starSystemConfig.Migrate();
starSystemConfig.FixCoordinates();
var system = new NewHorizonsSystem(config.starSystem, starSystemConfig, mod);
var system = new NewHorizonsSystem(config.starSystem, starSystemConfig, $"", mod);
SystemDict.Add(config.starSystem, system);
@ -632,6 +667,7 @@ namespace NewHorizons
catch (Exception e)
{
Logger.LogError($"Error encounter when loading {relativePath}:\n{e}");
MenuHandler.RegisterFailedConfig(Path.GetFileName(relativePath));
}
return body;
@ -647,6 +683,13 @@ namespace NewHorizons
#region Change star system
public void ChangeCurrentStarSystem(string newStarSystem, bool warp = false, bool vessel = false)
{
// If we're just on the title screen set the system for later
if (LoadManager.GetCurrentScene() == OWScene.TitleScreen)
{
_currentStarSystem = newStarSystem;
return;
}
if (IsChangingStarSystem) return;
IsWarpingFromShip = warp;
@ -658,9 +701,6 @@ namespace NewHorizons
IsChangingStarSystem = true;
WearingSuit = PlayerState.IsWearingSuit();
// We kill them so they don't move as much
Locator.GetDeathManager().KillPlayer(DeathType.Meditation);
OWScene sceneToLoad;
if (newStarSystem == "EyeOfTheUniverse")
@ -678,12 +718,15 @@ namespace NewHorizons
_currentStarSystem = newStarSystem;
// Freeze player inputs
OWInput.ChangeInputMode(InputMode.None);
LoadManager.LoadSceneAsync(sceneToLoad, !vessel, LoadManager.FadeType.ToBlack, 0.1f, true);
}
void OnDeath(DeathType _)
{
// We reset the solar system on death (unless we just killed the player)
// We reset the solar system on death
if (!IsChangingStarSystem)
{
// If the override is a valid system then we go there

View File

@ -17,7 +17,7 @@
<ItemGroup>
<PackageReference Include="HarmonyX" Version="2.10.0" />
<PackageReference Include="OWML" Version="2.6.0" />
<PackageReference Include="OuterWildsGameLibs" Version="1.1.12.201" />
<PackageReference Include="OuterWildsGameLibs" Version="1.1.13.393" />
<Reference Include="../Lib/System.ComponentModel.Annotations.dll" />
</ItemGroup>
<ItemGroup>

View File

@ -7,12 +7,15 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
using UnityEngine.Events;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons
{
public class NewHorizonsApi : INewHorizons
{
[Obsolete("Create(Dictionary<string, object> config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")]
@ -33,10 +36,10 @@ namespace NewHorizons
if (name == null) return;
var relativePath = $"temp/{name}.json";
var fullPath = Main.Instance.ModHelper.Manifest.ModFolderPath + relativePath;
if (!Directory.Exists(Main.Instance.ModHelper.Manifest.ModFolderPath + "temp"))
var fullPath = Path.Combine(Main.Instance.ModHelper.Manifest.ModFolderPath, relativePath);
if (!Directory.Exists(Path.Combine(Main.Instance.ModHelper.Manifest.ModFolderPath, "temp")))
{
Directory.CreateDirectory(Main.Instance.ModHelper.Manifest.ModFolderPath + "temp");
Directory.CreateDirectory(Path.Combine(Main.Instance.ModHelper.Manifest.ModFolderPath, "temp"));
}
JsonHelper.SaveJsonObject(fullPath, config);
var body = Main.Instance.LoadConfig(Main.Instance, relativePath);
@ -64,20 +67,10 @@ namespace NewHorizons
return Main.BodyDict.Values.SelectMany(x => x)?.ToList()?.FirstOrDefault(x => x.Config.name == name)?.Object;
}
public string GetCurrentStarSystem()
{
return Main.Instance.CurrentStarSystem;
}
public UnityEvent<string> GetChangeStarSystemEvent()
{
return Main.Instance.OnChangeStarSystem;
}
public UnityEvent<string> GetStarSystemLoadedEvent()
{
return Main.Instance.OnStarSystemLoaded;
}
public string GetCurrentStarSystem() => Main.Instance.CurrentStarSystem;
public UnityEvent<string> GetChangeStarSystemEvent() => Main.Instance.OnChangeStarSystem;
public UnityEvent<string> GetStarSystemLoadedEvent() => Main.Instance.OnStarSystemLoaded;
public UnityEvent<string> GetBodyLoadedEvent() => Main.Instance.OnPlanetLoaded;
public bool SetDefaultSystem(string name)
{
@ -108,6 +101,42 @@ namespace NewHorizons
}
}
private static object QueryJson(Type outType, string filePath, string jsonPath)
{
if (filePath == "") return null;
try
{
var jsonText = File.ReadAllText(filePath);
var jsonData = JObject.Parse(jsonText);
return jsonData.SelectToken(jsonPath)?.ToObject(outType);
}
catch (FileNotFoundException)
{
return null;
}
catch (JsonException e)
{
Logger.LogError(e.ToString());
return null;
}
}
public object QueryBody(Type outType, string bodyName, string jsonPath)
{
var planet = Main.BodyDict[Main.Instance.CurrentStarSystem].Find((b) => b.Config.name == bodyName);
return planet == null
? null
: QueryJson(outType, Path.Combine(planet.Mod.ModHelper.Manifest.ModFolderPath, planet.RelativePath), jsonPath);
}
public object QuerySystem(Type outType, string jsonPath)
{
var system = Main.SystemDict[Main.Instance.CurrentStarSystem];
return system == null
? null
: QueryJson(outType, Path.Combine(system.Mod.ModHelper.Manifest.ModFolderPath, system.RelativePath), jsonPath);
}
public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles,
float scale, bool alignWithNormal)
{

View File

@ -0,0 +1,27 @@
using NewHorizons.OtherMods.MenuFramework;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.OtherMods.CommonCameraUtility
{
public static class CommonCameraHandler
{
private static ICommonCameraAPI _cameraAPI;
static CommonCameraHandler()
{
_cameraAPI = Main.Instance.ModHelper.Interaction.TryGetModApi<ICommonCameraAPI>("xen.CommonCameraUtility");
}
public static void RegisterCustomCamera(OWCamera camera)
{
if (_cameraAPI != null)
{
_cameraAPI.RegisterCustomCamera(camera);
}
else
{
Logger.LogError("Tried to register custom camera but Common Camera Utility was missing.");
}
}
}
}

View File

@ -0,0 +1,13 @@
using UnityEngine;
using UnityEngine.Events;
namespace NewHorizons.OtherMods.CommonCameraUtility
{
public interface ICommonCameraAPI
{
void RegisterCustomCamera(OWCamera OWCamera);
(OWCamera, Camera) CreateCustomCamera(string name);
UnityEvent<PlayerTool> EquipTool();
UnityEvent<PlayerTool> UnequipTool();
}
}

View File

@ -0,0 +1,20 @@
using UnityEngine;
using UnityEngine.UI;
namespace NewHorizons.OtherMods.MenuFramework
{
public interface IMenuAPI
{
GameObject TitleScreen_MakeMenuOpenButton(string name, int index, Menu menuToOpen);
GameObject TitleScreen_MakeSceneLoadButton(string name, int index, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null);
Button TitleScreen_MakeSimpleButton(string name, int index);
GameObject PauseMenu_MakeMenuOpenButton(string name, Menu menuToOpen, Menu customMenu = null);
GameObject PauseMenu_MakeSceneLoadButton(string name, SubmitActionLoadScene.LoadableScenes sceneToLoad, PopupMenu confirmPopup = null, Menu customMenu = null);
Button PauseMenu_MakeSimpleButton(string name, Menu customMenu = null);
Menu PauseMenu_MakePauseListMenu(string title);
PopupMenu MakeTwoChoicePopup(string message, string confirmText, string cancelText);
PopupInputMenu MakeInputFieldPopup(string message, string placeholderMessage, string confirmText, string cancelText);
PopupMenu MakeInfoPopup(string message, string continueButtonText);
void RegisterStartupPopup(string message);
}
}

View File

@ -0,0 +1,69 @@
using NewHorizons.External;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using OWML.Common;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Logger = NewHorizons.Utility.Logger;
namespace NewHorizons.OtherMods.MenuFramework
{
public static class MenuHandler
{
private static IMenuAPI _menuApi;
private static List<(IModBehaviour mod, string message)> _registeredPopups = new();
private static List<string> _failedFiles = new();
public static void Init()
{
_menuApi = Main.Instance.ModHelper.Interaction.TryGetModApi<IMenuAPI>("_nebula.MenuFramework");
TextTranslation.Get().OnLanguageChanged += OnLanguageChanged;
}
public static void OnLanguageChanged()
{
// Have to load save data before doing popups
NewHorizonsData.Load();
if (!VersionUtility.CheckUpToDate())
{
var warning = string.Format(TranslationHandler.GetTranslation("OUTDATED_VERSION_WARNING", TranslationHandler.TextType.UI),
VersionUtility.RequiredVersionString,
Application.version);
Logger.LogError(warning);
_menuApi.RegisterStartupPopup(warning);
}
foreach(var (mod, message) in _registeredPopups)
{
if (!NewHorizonsData.HasReadOneTimePopup(mod.ModHelper.Manifest.UniqueName))
{
_menuApi.RegisterStartupPopup(TranslationHandler.GetTranslation(message, TranslationHandler.TextType.UI));
NewHorizonsData.ReadOneTimePopup(mod.ModHelper.Manifest.UniqueName);
}
}
if (_failedFiles.Count > 0)
{
var message = TranslationHandler.GetTranslation("JSON_FAILED_TO_LOAD", TranslationHandler.TextType.UI);
var mods = string.Join(",", _failedFiles.Take(10));
if (_failedFiles.Count > 10) mods += "...";
_menuApi.RegisterStartupPopup(string.Format(message, mods));
}
_registeredPopups.Clear();
_failedFiles.Clear();
// Just wanted to do this when the language is loaded in initially
TextTranslation.Get().OnLanguageChanged -= OnLanguageChanged;
}
public static void RegisterFailedConfig(string filename) => _failedFiles.Add(filename);
public static void RegisterOneTimePopup(IModBehaviour mod, string message) => _registeredPopups.Add((mod, message));
}
}

View File

@ -1,4 +1,4 @@
using NewHorizons.Components;
using NewHorizons.Components.ShipLog;
using NewHorizons.Handlers;
using NewHorizons.Utility;
using System;
@ -47,7 +47,7 @@ namespace NewHorizons.OtherMods.OWRichPresence
var localizedName = TranslationHandler.GetTranslation(name, TranslationHandler.TextType.UI);
var message = TranslationHandler.GetTranslation("RICH_PRESENCE_EXPLORING", TranslationHandler.TextType.UI).Replace("{0}", localizedName);
API.CreateTrigger(go, sector, message, name.Replace(" ", "").Replace("'", "").ToLowerInvariant());
API.CreateTrigger(go, sector, message, name.Replace(" ", "").Replace("'", "").Replace("-", "").ToLowerInvariant());
}
public static void OnStarSystemLoaded(string name)

View File

@ -38,10 +38,10 @@ namespace NewHorizons.OtherMods.VoiceActing
{
foreach (var mod in Main.Instance.GetDependants().Append(Main.Instance))
{
var folder = $"{mod.ModHelper.Manifest.ModFolderPath}voicemod";
var folder = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, "voicemod");
if (!Directory.Exists(folder)) {
// Fallback to PascalCase bc it used to be like that
folder = $"{mod.ModHelper.Manifest.ModFolderPath}VoiceMod";
folder = Path.Combine(mod.ModHelper.Manifest.ModFolderPath, "VoiceMod");
}
if (Directory.Exists(folder))
{

View File

@ -0,0 +1,24 @@
using HarmonyLib;
using NewHorizons.OtherMods.CommonCameraUtility;
using UnityEngine;
namespace NewHorizons.Patches.CameraPatches
{
[HarmonyPatch]
public static class NomaiRemoteCameraPatches
{
[HarmonyPostfix]
[HarmonyPatch(typeof(NomaiRemoteCamera), nameof(NomaiRemoteCamera.Awake))]
public static void NomaiRemoteCamera_Awake(NomaiRemoteCamera __instance)
{
// Ensures that if the player is visible from the remote camera they look normal
CommonCameraHandler.RegisterCustomCamera(__instance._camera);
// These layers were left on because it doesnt come up in base game (Dreamworld is inactive, player is far away)
__instance._camera.mainCamera.cullingMask &= ~(1 << LayerMask.NameToLayer("DreamSimulation"));
__instance._camera.mainCamera.cullingMask &= ~(1 <<LayerMask.NameToLayer("UI"));
__instance._camera.mainCamera.cullingMask &= ~(1 <<LayerMask.NameToLayer("HeadsUpDisplay"));
__instance._camera.mainCamera.cullingMask &= ~(1 <<LayerMask.NameToLayer("HelmetUVPass"));
}
}
}

View File

@ -0,0 +1,20 @@
using HarmonyLib;
namespace NewHorizons.Patches.CameraPatches
{
[HarmonyPatch]
public static class OWCameraPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(OWCamera), nameof(OWCamera.Awake))]
public static void OnOWCameraAwake(OWCamera __instance)
{
if (Main.SystemDict.TryGetValue(Main.Instance.CurrentStarSystem, out var system) && system?.Config?.farClipPlaneOverride != 0f)
{
__instance.farClipPlane = system.Config.farClipPlaneOverride;
__instance.farCameraDistance = system.Config.farClipPlaneOverride;
__instance.mainCamera.farClipPlane = system.Config.farClipPlaneOverride;
}
}
}
}

View File

@ -0,0 +1,26 @@
using HarmonyLib;
namespace NewHorizons.Patches;
[HarmonyPatch]
internal static class CharacterDialogueTreePatches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.Awake))]
private static void CharacterDialogueTree_Awake(CharacterDialogueTree __instance)
{
GlobalMessenger<OWRigidbody>.AddListener("AttachPlayerToPoint", __instance.OnAttachPlayerToPoint);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(CharacterDialogueTree), nameof(CharacterDialogueTree.OnDestroy))]
private static void CharacterDialogueTree_OnDestroy(CharacterDialogueTree __instance)
{
GlobalMessenger<OWRigidbody>.RemoveListener("AttachPlayerToPoint", __instance.OnAttachPlayerToPoint);
}
private static void OnAttachPlayerToPoint(this CharacterDialogueTree characterDialogueTree, OWRigidbody rigidbody)
{
characterDialogueTree.EndConversation();
}
}

View File

@ -1,5 +1,5 @@
using HarmonyLib;
using NewHorizons.Components;
using NewHorizons.Components.Quantum;
using System;
using System.Collections.Generic;
using System.Linq;

View File

@ -1,4 +1,5 @@
using HarmonyLib;
using NewHorizons.Handlers;
namespace NewHorizons.Patches
{
@ -9,6 +10,8 @@ namespace NewHorizons.Patches
[HarmonyPatch(typeof(HUDMarker), nameof(HUDMarker.Awake))]
public static void HUDMarker_Awake(HUDMarker __instance)
{
GlobalMessenger.AddListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility);
GlobalMessenger.AddListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility);
GlobalMessenger.AddListener("PlayerEnterCloakField", __instance.OnPlayerEnterCloakField);
GlobalMessenger.AddListener("PlayerExitCloakField", __instance.OnPlayerExitCloakField);
}
@ -17,6 +20,8 @@ namespace NewHorizons.Patches
[HarmonyPatch(typeof(HUDMarker), nameof(HUDMarker.OnDestroy))]
public static void HUDMarker_OnDestroy(HUDMarker __instance)
{
GlobalMessenger.RemoveListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility);
GlobalMessenger.RemoveListener("RefreshHUDVisibility", __instance.RefreshOwnVisibility);
GlobalMessenger.RemoveListener("PlayerEnterCloakField", __instance.OnPlayerEnterCloakField);
GlobalMessenger.RemoveListener("PlayerExitCloakField", __instance.OnPlayerExitCloakField);
}
@ -53,11 +58,67 @@ namespace NewHorizons.Patches
GlobalMessenger.RemoveListener("ShipExitCloakField", __instance.RefreshOwnVisibility);
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ProbeHUDMarker), nameof(ProbeHUDMarker.RefreshOwnVisibility))]
public static bool ProbeHUDMarker_RefreshOwnVisibility(ProbeHUDMarker __instance)
{
bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye();
bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsProbeInside());
bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside == Locator.GetRingWorldController().isProbeInside;
bool insideIP = Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isProbeInsideCloak;
bool insideCloak = Components.CloakSectorController.isPlayerInside == Components.CloakSectorController.isProbeInside;
bool sameInterference = InterferenceHandler.IsPlayerSameAsProbe();
bool isActive = __instance.gameObject.activeInHierarchy || __instance._isTLCDuplicate;
__instance._isVisible = isActive && !insideEYE && !insideQM && !__instance._translatorEquipped && !__instance._inConversation && __instance._launched && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideRW && insideIP && insideCloak && sameInterference;
if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipHUDMarker), nameof(ShipHUDMarker.RefreshOwnVisibility))]
public static bool ShipHUDMarker_RefreshOwnVisibility(ShipHUDMarker __instance)
{
bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye();
bool insideQM = __instance._quantumMoon != null && (__instance._quantumMoon.IsPlayerInside() || __instance._quantumMoon.IsShipInside());
bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside;
bool insideIP = Locator.GetCloakFieldController() != null ? Locator.GetCloakFieldController().isPlayerInsideCloak == Locator.GetCloakFieldController().isShipInsideCloak : true;
bool insideCloak = Components.CloakSectorController.isPlayerInside == Components.CloakSectorController.isShipInside;
bool sameInterference = InterferenceHandler.IsPlayerSameAsShip();
__instance._isVisible = !insideEYE && !insideQM && !insideRW && !__instance._translatorEquipped && !__instance._inConversation && !__instance._shipDestroyed && !__instance._playerInShip && PlayerState.HasPlayerEnteredShip() && __instance._isWearingHelmet && insideIP && insideCloak && sameInterference;
if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible);
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ShipLogEntryHUDMarker), nameof(ShipLogEntryHUDMarker.RefreshOwnVisibility))]
public static bool ShipLogEntryHUDMarker_RefreshOwnVisibility(ShipLogEntryHUDMarker __instance)
{
bool hasEntryLocation = ShipLogEntryHUDMarker.s_entryLocation != null;
bool insideEYE = Locator.GetEyeStateManager() != null && Locator.GetEyeStateManager().IsInsideTheEye();
bool insideQM = __instance._quantumMoon != null && __instance._quantumMoon.IsPlayerInside();
bool insideRW = Locator.GetRingWorldController() != null && Locator.GetRingWorldController().isPlayerInside && ShipLogEntryHUDMarker.s_entryLocationID == "IP_RING_WORLD";
bool insideIP = (hasEntryLocation && ShipLogEntryHUDMarker.s_entryLocation.IsWithinCloakField()) || !(Locator.GetCloakFieldController() != null && Locator.GetCloakFieldController().isPlayerInsideCloak);
bool insideCloak = (hasEntryLocation && ShipLogEntryHUDMarker.s_entryLocation.IsWithinCloakField()) || !Components.CloakSectorController.isPlayerInside;
__instance._isVisible = (!insideEYE && !insideQM && !insideRW && !__instance._translatorEquipped && !__instance._inConversation && hasEntryLocation && (__instance._isWearingHelmet || __instance._atFlightConsole) && insideIP && insideCloak);
if (__instance._canvasMarker != null) __instance._canvasMarker.SetVisibility(__instance._isVisible);
return false;
}
[HarmonyPostfix]
[HarmonyPatch(typeof(ProbeCamera), nameof(ProbeCamera.HasInterference))]
public static void ProbeCamera_HasInterference(ProbeCamera __instance, ref bool __result)
{
__result = __result || Components.CloakSectorController.isPlayerInside != Components.CloakSectorController.isProbeInside;
__result = __result || (__instance._id != ProbeCamera.ID.PreLaunch && (Components.CloakSectorController.isPlayerInside != Components.CloakSectorController.isProbeInside || !InterferenceHandler.IsPlayerSameAsProbe()));
}
}
}

View File

@ -1,4 +1,5 @@
using HarmonyLib;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace NewHorizons.Patches
@ -10,11 +11,11 @@ namespace NewHorizons.Patches
[HarmonyPatch(typeof(MapController), nameof(MapController.Awake))]
public static void MapController_Awake(MapController __instance)
{
__instance._maxPanDistance = Main.FurthestOrbit * 1.5f;
__instance._maxPanDistance = Mathf.Max(__instance._maxPanDistance, Main.FurthestOrbit * 1.5f);
__instance._maxZoomDistance *= 6f;
__instance._minPitchAngle = -90f;
__instance._zoomSpeed *= 4f;
__instance._mapCamera.farClipPlane = Main.FurthestOrbit * 10f;
__instance._mapCamera.farClipPlane = Mathf.Max(__instance._mapCamera.farClipPlane, Main.FurthestOrbit * 10f);
}
[HarmonyPostfix]

View File

@ -1,32 +0,0 @@
using HarmonyLib;
namespace NewHorizons.Patches
{
[HarmonyPatch]
public static class OWCameraPatch
{
[HarmonyPostfix]
[HarmonyPatch(typeof(OWCamera), nameof(OWCamera.Awake))]
public static void OnOWCameraAwake(OWCamera __instance)
{
// var oldDist = __instance.farClipPlane;
// var newDist = __instance.farClipPlane * 10f;
// if (__instance.useFarCamera) Mathf.Clamp(newDist, oldDist, 50000f);
// else newDist = Mathf.Clamp(newDist, oldDist, 10000000f);
// __instance.farClipPlane = newDist;
// __instance.farCameraDistance = newDist;
// __instance.mainCamera.farClipPlane = newDist;
}
// [HarmonyPrefix]
// [HarmonyPatch(typeof(OWCamera), nameof(OWCamera.RebuildSkybox))]
// public static bool OnOWCameraRebuildSkybox(OWCamera __instance)
// {
// __instance._skyboxCommandBuffer = new CommandBuffer();
// __instance._skyboxCommandBuffer.name = "Skybox";
// var camera = __instance._useFarCamera && !SystemInfo.usesReversedZBuffer ? __instance._farCamera : __instance._mainCamera;
// CameraEvent evt = CameraEvent.BeforeSkybox;
// camera.AddCommandBuffer(evt, __instance._skyboxCommandBuffer);
// return false;
// }
}
}

View File

@ -25,6 +25,7 @@ namespace NewHorizons.Patches
ProxyPlanet_Initialize(__instance);
__instance._moon.SetOriginalBodies(Locator.GetAstroObject(AstroObject.Name.VolcanicMoon).transform, Locator.GetAstroObject(AstroObject.Name.BrittleHollow).transform);
if (!__instance._fragmentsResolved) __instance.ResolveFragments();
__instance.AssignBrittleHollowReference();
__instance._blackHoleMaterial = new Material(__instance._blackHoleRenderer.sharedMaterial);
__instance._blackHoleRenderer.sharedMaterial = __instance._blackHoleMaterial;
}

View File

@ -1,5 +1,5 @@
using HarmonyLib;
using NewHorizons.Components;
using NewHorizons.Components.Volumes;
using UnityEngine;
namespace NewHorizons.Patches
{

View File

@ -0,0 +1,29 @@
using HarmonyLib;
using System.Collections.Generic;
namespace NewHorizons.Patches
{
[HarmonyPatch]
public class ShapePatches
{
[HarmonyPrefix]
[HarmonyPatch(typeof(ShapeManager), nameof(ShapeManager.Initialize))]
public static bool ShapeManager_Initialize()
{
ShapeManager._exists = true;
ShapeManager._detectors = new ShapeManager.Layer(256);
for (int index = 0; index < 256; ++index)
ShapeManager._detectors[index].contacts = new List<ShapeManager.ContactData>(64);
ShapeManager._volumes = new ShapeManager.Layer[4];
for (int index = 0; index < 4; ++index)
ShapeManager._volumes[index] = new ShapeManager.Layer(2048);
ShapeManager._locked = false;
ShapeManager._frameFlag = false;
return false;
}
}
}

Some files were not shown because too many files have changed in this diff Show More