mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Compare commits
58 Commits
1270d1c61f
...
30cb5253ab
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30cb5253ab | ||
|
|
09bd1df199 | ||
|
|
03ef2f4e81 | ||
|
|
0b7e9b47fd | ||
|
|
2c36015a68 | ||
|
|
ff699e313d | ||
|
|
fd8e240657 | ||
|
|
8d271c368c | ||
|
|
7c0731fbae | ||
|
|
4982f2a69a | ||
|
|
4e3e438cde | ||
|
|
1c7faa93fc | ||
|
|
9f5b71e1cc | ||
|
|
1ce62f383d | ||
|
|
765d3a136d | ||
|
|
1511cc5cb0 | ||
|
|
54165a8d5e | ||
|
|
be3f77d02b | ||
|
|
999bcae536 | ||
|
|
0b419b66c4 | ||
|
|
94ff93d597 | ||
|
|
696bce2f3a | ||
|
|
8af363f8f8 | ||
|
|
831a94cdbc | ||
|
|
57d945d6ee | ||
|
|
8089de358a | ||
|
|
2e07c93fc4 | ||
|
|
915b5bc55d | ||
|
|
ced49c6606 | ||
|
|
201a310e2b | ||
|
|
38ae757f58 | ||
|
|
f7c9685457 | ||
|
|
4c3d92a4a3 | ||
|
|
5391e4a555 | ||
|
|
65ecbb1f9a | ||
|
|
fe55ccfcdc | ||
|
|
ecdc0c8af4 | ||
|
|
31a6093a1b | ||
|
|
78d8150c4c | ||
|
|
361fc2aa57 | ||
|
|
b0f445e415 | ||
|
|
d38d9fa1c8 | ||
|
|
20126dfe91 | ||
|
|
ea85e3bab0 | ||
|
|
fdf78802e9 | ||
|
|
3403c5da34 | ||
|
|
1d4a2b328b | ||
|
|
e4f89be4e9 | ||
|
|
2e06de70c2 | ||
|
|
e626dc6974 | ||
|
|
1330df64b4 | ||
|
|
b71aa9f845 | ||
|
|
7223a4f523 | ||
|
|
d072a74b5d | ||
|
|
330564538a | ||
|
|
b84d94a404 | ||
|
|
3fbe752395 | ||
|
|
01866cc6be |
@ -68,3 +68,9 @@ These will automatically be converted from strings to the proper enum type.
|
|||||||
## Contributing to Documentation
|
## Contributing to Documentation
|
||||||
|
|
||||||
If you wish to contribute to the documentation, take a look at [CONTRIBUTING.md](docs/CONTRIBUTING.md) in the docs folder.
|
If you wish to contribute to the documentation, take a look at [CONTRIBUTING.md](docs/CONTRIBUTING.md) in the docs folder.
|
||||||
|
|
||||||
|
## Disclaimer
|
||||||
|
|
||||||
|
This should go without saying, but we will not accept PRs that are obviously AI generated, nor will we accept PRs from people who have not actually played the game or any mods.
|
||||||
|
|
||||||
|
Any potential bug bounties for New Horizons are only eligible to be claimed by those who have created mods for Outer Wilds in the past.
|
||||||
|
|||||||
@ -100,8 +100,6 @@ namespace NewHorizons.Builder.Props.Audio
|
|||||||
var freq = CollectionUtilities.KeyByValue(_customFrequencyNames, str);
|
var freq = CollectionUtilities.KeyByValue(_customFrequencyNames, str);
|
||||||
if (freq != default) return freq;
|
if (freq != default) return freq;
|
||||||
|
|
||||||
NHLogger.Log($"Registering new frequency name [{str}]");
|
|
||||||
|
|
||||||
if (NumberOfFrequencies == 31)
|
if (NumberOfFrequencies == 31)
|
||||||
{
|
{
|
||||||
NHLogger.LogWarning($"Can't store any more frequencies, skipping [{str}]");
|
NHLogger.LogWarning($"Can't store any more frequencies, skipping [{str}]");
|
||||||
@ -111,10 +109,9 @@ namespace NewHorizons.Builder.Props.Audio
|
|||||||
freq = EnumUtilities.Create<SignalFrequency>(str);
|
freq = EnumUtilities.Create<SignalFrequency>(str);
|
||||||
_customFrequencyNames.Add(freq, str);
|
_customFrequencyNames.Add(freq, str);
|
||||||
|
|
||||||
NumberOfFrequencies = EnumUtils.GetValues<SignalFrequency>().Length;
|
NHLogger.Log($"Registered new frequency name [{str}] with value [{(int)freq}] and index [{AudioSignal.FrequencyToIndex(freq)}]");
|
||||||
|
|
||||||
// This stuff happens after the signalscope is Awake so we have to change the number of frequencies now
|
NumberOfFrequencies = EnumUtils.GetValues<SignalFrequency>().Length;
|
||||||
GameObject.FindObjectOfType<Signalscope>()._strongestSignals = new AudioSignal[NumberOfFrequencies + 1];
|
|
||||||
|
|
||||||
return freq;
|
return freq;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -290,6 +290,10 @@ namespace NewHorizons.Builder.Props
|
|||||||
|
|
||||||
interact._interactRange = info.range;
|
interact._interactRange = info.range;
|
||||||
|
|
||||||
|
// If a dialogue is on the ship, make sure its usable
|
||||||
|
// Assumes these are inside the ship and not outside, not sure if thats an issue
|
||||||
|
interact._usableInShip = planetGO.name == "Ship_Body";
|
||||||
|
|
||||||
if (info.radius <= 0)
|
if (info.radius <= 0)
|
||||||
{
|
{
|
||||||
sphere.enabled = false;
|
sphere.enabled = false;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using NewHorizons.Components.EOTE;
|
||||||
using NewHorizons.External.Modules.Props;
|
using NewHorizons.External.Modules.Props;
|
||||||
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
||||||
using NewHorizons.Handlers;
|
using NewHorizons.Handlers;
|
||||||
@ -70,6 +71,12 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye
|
|||||||
dreamCandle._startLit = info.startLit;
|
dreamCandle._startLit = info.startLit;
|
||||||
dreamCandle.SetLit(info.startLit, false, true);
|
dreamCandle.SetLit(info.startLit, false, true);
|
||||||
|
|
||||||
|
if (info.condition != null)
|
||||||
|
{
|
||||||
|
var conditionController = dreamCandle.gameObject.AddComponent<DreamLightConditionController>();
|
||||||
|
conditionController.SetFromInfo(info.condition);
|
||||||
|
}
|
||||||
|
|
||||||
return candleObj;
|
return candleObj;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
using NewHorizons.Components.EOTE;
|
||||||
using NewHorizons.External.Modules.Props;
|
using NewHorizons.External.Modules.Props;
|
||||||
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
||||||
using NewHorizons.Handlers;
|
using NewHorizons.Handlers;
|
||||||
@ -116,6 +117,13 @@ namespace NewHorizons.Builder.Props.EchoesOfTheEye
|
|||||||
projector._lit = info.startLit;
|
projector._lit = info.startLit;
|
||||||
projector._startLit = info.startLit;
|
projector._startLit = info.startLit;
|
||||||
projector._extinguishOnly = info.extinguishOnly;
|
projector._extinguishOnly = info.extinguishOnly;
|
||||||
|
|
||||||
|
if (info.condition != null)
|
||||||
|
{
|
||||||
|
var conditionController = projector.gameObject.AddComponent<DreamLightConditionController>();
|
||||||
|
conditionController.SetFromInfo(info.condition);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Delay.FireOnNextUpdate(() =>
|
Delay.FireOnNextUpdate(() =>
|
||||||
{
|
{
|
||||||
|
|||||||
@ -16,13 +16,6 @@ namespace NewHorizons.Builder.Props
|
|||||||
|
|
||||||
internal static void Init()
|
internal static void Init()
|
||||||
{
|
{
|
||||||
if (_itemTypes != null)
|
|
||||||
{
|
|
||||||
foreach (var value in _itemTypes.Values)
|
|
||||||
{
|
|
||||||
EnumUtils.Remove<ItemType>(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_itemTypes = new Dictionary<string, ItemType>();
|
_itemTypes = new Dictionary<string, ItemType>();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,11 +134,7 @@ namespace NewHorizons.Builder.Props
|
|||||||
{
|
{
|
||||||
go.layer = Layer.Interactible;
|
go.layer = Layer.Interactible;
|
||||||
|
|
||||||
var itemType = EnumUtils.TryParse(info.itemType, true, out ItemType result) ? result : ItemType.Invalid;
|
var itemType = GetOrCreateItemType(info.itemType);
|
||||||
if (itemType == ItemType.Invalid && !string.IsNullOrEmpty(info.itemType))
|
|
||||||
{
|
|
||||||
itemType = EnumUtilities.Create<ItemType>(info.itemType);
|
|
||||||
}
|
|
||||||
|
|
||||||
var socket = go.GetAddComponent<NHItemSocket>();
|
var socket = go.GetAddComponent<NHItemSocket>();
|
||||||
socket._sector = sector;
|
socket._sector = sector;
|
||||||
@ -205,7 +194,7 @@ namespace NewHorizons.Builder.Props
|
|||||||
}
|
}
|
||||||
else if (!string.IsNullOrEmpty(name))
|
else if (!string.IsNullOrEmpty(name))
|
||||||
{
|
{
|
||||||
itemType = EnumUtils.Create<ItemType>(name);
|
itemType = EnumUtilities.Create<ItemType>(name);
|
||||||
_itemTypes.Add(name, itemType);
|
_itemTypes.Add(name, itemType);
|
||||||
}
|
}
|
||||||
return itemType;
|
return itemType;
|
||||||
|
|||||||
25
NewHorizons/Builder/Volumes/ConditionTriggerVolumeBuilder.cs
Normal file
25
NewHorizons/Builder/Volumes/ConditionTriggerVolumeBuilder.cs
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
using NewHorizons.Components.Volumes;
|
||||||
|
using NewHorizons.External.Modules.Volumes.VolumeInfos;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Builder.Volumes
|
||||||
|
{
|
||||||
|
internal static class ConditionTriggerVolumeBuilder
|
||||||
|
{
|
||||||
|
public static ConditionTriggerVolume Make(GameObject planetGO, Sector sector, ConditionTriggerVolumeInfo info)
|
||||||
|
{
|
||||||
|
var volume = VolumeBuilder.Make<ConditionTriggerVolume>(planetGO, sector, info);
|
||||||
|
|
||||||
|
volume.Condition = info.condition;
|
||||||
|
volume.Persistent = info.persistent;
|
||||||
|
volume.Reversible = info.reversible;
|
||||||
|
volume.Player = info.player;
|
||||||
|
volume.Probe = info.probe;
|
||||||
|
volume.Ship = info.ship;
|
||||||
|
|
||||||
|
volume.gameObject.SetActive(true);
|
||||||
|
|
||||||
|
return volume;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
91
NewHorizons/Builder/Volumes/InteractionVolumeBuilder.cs
Normal file
91
NewHorizons/Builder/Volumes/InteractionVolumeBuilder.cs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
using NewHorizons.Components.Volumes;
|
||||||
|
using NewHorizons.External.Modules.Volumes.VolumeInfos;
|
||||||
|
using NewHorizons.Handlers;
|
||||||
|
using NewHorizons.Utility;
|
||||||
|
using NewHorizons.Utility.Files;
|
||||||
|
using NewHorizons.Utility.OuterWilds;
|
||||||
|
using NewHorizons.Utility.OWML;
|
||||||
|
using OWML.Common;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Builder.Volumes
|
||||||
|
{
|
||||||
|
internal static class InteractionVolumeBuilder
|
||||||
|
{
|
||||||
|
public static InteractReceiver Make(GameObject planetGO, Sector sector, InteractionVolumeInfo info, IModBehaviour mod)
|
||||||
|
{
|
||||||
|
// Interaction volumes must use colliders because the first-person interaction system uses raycasting
|
||||||
|
if (info.shape != null && info.shape?.useShape == false)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Interaction volumes only support colliders. Affects planet [{planetGO.name}]. Set useShape to false.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// If info.shape was null, it will still default to using a sphere with info.radius, just make sure it does so with a collider
|
||||||
|
info.shape ??= new();
|
||||||
|
info.shape.useShape = false;
|
||||||
|
|
||||||
|
var receiver = VolumeBuilder.Make<InteractReceiver>(planetGO, sector, info);
|
||||||
|
receiver.gameObject.layer = Layer.Interactible;
|
||||||
|
|
||||||
|
receiver._interactRange = info.range;
|
||||||
|
receiver._checkViewAngle = info.maxViewAngle.HasValue;
|
||||||
|
receiver._maxViewAngle = info.maxViewAngle ?? 180f;
|
||||||
|
receiver._usableInShip = info.usableInShip;
|
||||||
|
|
||||||
|
var volume = receiver.gameObject.AddComponent<NHInteractionVolume>();
|
||||||
|
|
||||||
|
volume.Reusable = info.reusable;
|
||||||
|
volume.Condition = info.condition;
|
||||||
|
volume.Persistent = info.persistent;
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(info.audio))
|
||||||
|
{
|
||||||
|
var audioSource = receiver.gameObject.AddComponent<AudioSource>();
|
||||||
|
|
||||||
|
// This could be more configurable but this should cover the most common use cases without bloating the info object
|
||||||
|
var owAudioSource = receiver.gameObject.AddComponent<OWAudioSource>();
|
||||||
|
owAudioSource._audioSource = audioSource;
|
||||||
|
owAudioSource.playOnAwake = false;
|
||||||
|
owAudioSource.loop = false;
|
||||||
|
owAudioSource.SetMaxVolume(1f);
|
||||||
|
owAudioSource.SetClipSelectionType(OWAudioSource.ClipSelectionOnPlay.RANDOM);
|
||||||
|
owAudioSource.SetTrack(OWAudioMixer.TrackName.Environment);
|
||||||
|
AudioUtilities.SetAudioClip(owAudioSource, info.audio, mod);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(info.pathToAnimator))
|
||||||
|
{
|
||||||
|
var animObj = planetGO.transform.Find(info.pathToAnimator);
|
||||||
|
|
||||||
|
if (animObj == null)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Couldn't find child of {planetGO.transform.GetPath()} at {info.pathToAnimator}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var animator = animObj.GetComponent<Animator>();
|
||||||
|
if (animator == null)
|
||||||
|
{
|
||||||
|
NHLogger.LogError($"Couldn't find Animator on {animObj.name} at {info.pathToAnimator}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
volume.TargetAnimator = animator;
|
||||||
|
volume.AnimationTrigger = info.animationTrigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
receiver.gameObject.SetActive(true);
|
||||||
|
|
||||||
|
var text = TranslationHandler.GetTranslation(info.prompt, TranslationHandler.TextType.UI);
|
||||||
|
Delay.FireOnNextUpdate(() =>
|
||||||
|
{
|
||||||
|
// This NREs if set immediately
|
||||||
|
receiver.ChangePrompt(text);
|
||||||
|
});
|
||||||
|
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -35,6 +35,13 @@ namespace NewHorizons.Builder.Volumes
|
|||||||
AudioVolumeBuilder.Make(go, sector, audioVolume, mod);
|
AudioVolumeBuilder.Make(go, sector, audioVolume, mod);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (config.Volumes.conditionTriggerVolumes != null)
|
||||||
|
{
|
||||||
|
foreach (var conditionTriggerVolume in config.Volumes.conditionTriggerVolumes)
|
||||||
|
{
|
||||||
|
ConditionTriggerVolumeBuilder.Make(go, sector, conditionTriggerVolume);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (config.Volumes.dayNightAudioVolumes != null)
|
if (config.Volumes.dayNightAudioVolumes != null)
|
||||||
{
|
{
|
||||||
foreach (var dayNightAudioVolume in config.Volumes.dayNightAudioVolumes)
|
foreach (var dayNightAudioVolume in config.Volumes.dayNightAudioVolumes)
|
||||||
@ -63,6 +70,13 @@ namespace NewHorizons.Builder.Volumes
|
|||||||
VolumeBuilder.MakeAndEnable<MapRestrictionVolume>(go, sector, mapRestrictionVolume);
|
VolumeBuilder.MakeAndEnable<MapRestrictionVolume>(go, sector, mapRestrictionVolume);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (config.Volumes.interactionVolumes != null)
|
||||||
|
{
|
||||||
|
foreach (var interactionVolume in config.Volumes.interactionVolumes)
|
||||||
|
{
|
||||||
|
InteractionVolumeBuilder.Make(go, sector, interactionVolume, mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (config.Volumes.interferenceVolumes != null)
|
if (config.Volumes.interferenceVolumes != null)
|
||||||
{
|
{
|
||||||
foreach (var interferenceVolume in config.Volumes.interferenceVolumes)
|
foreach (var interferenceVolume in config.Volumes.interferenceVolumes)
|
||||||
|
|||||||
85
NewHorizons/Components/EOTE/DreamLightConditionController.cs
Normal file
85
NewHorizons/Components/EOTE/DreamLightConditionController.cs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
using NewHorizons.External.Modules.Props.EchoesOfTheEye;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Components.EOTE
|
||||||
|
{
|
||||||
|
public class DreamLightConditionController : MonoBehaviour
|
||||||
|
{
|
||||||
|
public string Condition { get; set; }
|
||||||
|
public bool Persistent { get; set; }
|
||||||
|
public bool Reversible { get; set; }
|
||||||
|
public bool OnExtinguish { get; set; }
|
||||||
|
|
||||||
|
DreamObjectProjector _projector;
|
||||||
|
DreamCandle _dreamCandle;
|
||||||
|
|
||||||
|
public void SetFromInfo(DreamLightConditionInfo info)
|
||||||
|
{
|
||||||
|
Condition = info.condition;
|
||||||
|
Persistent = info.persistent;
|
||||||
|
Reversible = info.reversible;
|
||||||
|
OnExtinguish = info.onExtinguish;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void Awake()
|
||||||
|
{
|
||||||
|
_projector = GetComponent<DreamObjectProjector>();
|
||||||
|
_projector.OnProjectorLit.AddListener(OnProjectorLit);
|
||||||
|
_projector.OnProjectorExtinguished.AddListener(OnProjectorExtinguished);
|
||||||
|
|
||||||
|
_dreamCandle = GetComponent<DreamCandle>();
|
||||||
|
if (_dreamCandle != null)
|
||||||
|
{
|
||||||
|
_dreamCandle.OnLitStateChanged.AddListener(OnCandleLitStateChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnDestroy()
|
||||||
|
{
|
||||||
|
if (_projector != null)
|
||||||
|
{
|
||||||
|
_projector.OnProjectorLit.RemoveListener(OnProjectorLit);
|
||||||
|
_projector.OnProjectorExtinguished.RemoveListener(OnProjectorExtinguished);
|
||||||
|
}
|
||||||
|
if (_dreamCandle != null)
|
||||||
|
{
|
||||||
|
_dreamCandle.OnLitStateChanged.RemoveListener(OnCandleLitStateChanged);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnProjectorLit()
|
||||||
|
{
|
||||||
|
HandleCondition(!OnExtinguish);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnProjectorExtinguished()
|
||||||
|
{
|
||||||
|
HandleCondition(OnExtinguish);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCandleLitStateChanged()
|
||||||
|
{
|
||||||
|
HandleCondition(OnExtinguish ? !_dreamCandle._lit : _dreamCandle._lit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleCondition(bool shouldSet)
|
||||||
|
{
|
||||||
|
if (shouldSet || Reversible)
|
||||||
|
{
|
||||||
|
if (Persistent)
|
||||||
|
{
|
||||||
|
PlayerData.SetPersistentCondition(Condition, shouldSet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DialogueConditionManager.SharedInstance.SetConditionState(Condition, shouldSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
66
NewHorizons/Components/Volumes/ConditionTriggerVolume.cs
Normal file
66
NewHorizons/Components/Volumes/ConditionTriggerVolume.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Components.Volumes
|
||||||
|
{
|
||||||
|
public class ConditionTriggerVolume : BaseVolume
|
||||||
|
{
|
||||||
|
public string Condition { get; set; }
|
||||||
|
public bool Persistent { get; set; }
|
||||||
|
public bool Reversible { get; set; }
|
||||||
|
public bool Player { get; set; } = true;
|
||||||
|
public bool Probe { get; set; }
|
||||||
|
public bool Ship { get; set; }
|
||||||
|
|
||||||
|
public override void OnTriggerVolumeEntry(GameObject hitObj)
|
||||||
|
{
|
||||||
|
if (TestHitObject(hitObj))
|
||||||
|
{
|
||||||
|
if (Persistent)
|
||||||
|
{
|
||||||
|
PlayerData.SetPersistentCondition(Condition, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DialogueConditionManager.SharedInstance.SetConditionState(Condition, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void OnTriggerVolumeExit(GameObject hitObj)
|
||||||
|
{
|
||||||
|
if (Reversible && TestHitObject(hitObj))
|
||||||
|
{
|
||||||
|
if (Persistent)
|
||||||
|
{
|
||||||
|
PlayerData.SetPersistentCondition(Condition, false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DialogueConditionManager.SharedInstance.SetConditionState(Condition, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TestHitObject(GameObject hitObj)
|
||||||
|
{
|
||||||
|
if (Player && hitObj.CompareTag("PlayerDetector"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Probe && hitObj.CompareTag("ProbeDetector"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (Ship && hitObj.CompareTag("ShipDetector"))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
69
NewHorizons/Components/Volumes/NHInteractionVolume.cs
Normal file
69
NewHorizons/Components/Volumes/NHInteractionVolume.cs
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NewHorizons.Components.Volumes
|
||||||
|
{
|
||||||
|
public class NHInteractionVolume : MonoBehaviour
|
||||||
|
{
|
||||||
|
public bool Reusable { get; set; }
|
||||||
|
public string Condition { get; set; }
|
||||||
|
public bool Persistent { get; set; }
|
||||||
|
public Animator TargetAnimator { get; set; }
|
||||||
|
public string AnimationTrigger { get; set; }
|
||||||
|
|
||||||
|
InteractReceiver _interactReceiver;
|
||||||
|
OWAudioSource _audioSource;
|
||||||
|
|
||||||
|
protected void Awake()
|
||||||
|
{
|
||||||
|
_interactReceiver = GetComponent<InteractReceiver>();
|
||||||
|
_audioSource = GetComponent<OWAudioSource>();
|
||||||
|
|
||||||
|
_interactReceiver.OnPressInteract += OnInteract;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnDestroy()
|
||||||
|
{
|
||||||
|
_interactReceiver.OnPressInteract -= OnInteract;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void OnInteract()
|
||||||
|
{
|
||||||
|
if (!string.IsNullOrEmpty(Condition))
|
||||||
|
{
|
||||||
|
if (Persistent)
|
||||||
|
{
|
||||||
|
PlayerData.SetPersistentCondition(Condition, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DialogueConditionManager.SharedInstance.SetConditionState(Condition, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_audioSource != null)
|
||||||
|
{
|
||||||
|
_audioSource.Play();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TargetAnimator)
|
||||||
|
{
|
||||||
|
TargetAnimator.SetTrigger(AnimationTrigger);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Reusable)
|
||||||
|
{
|
||||||
|
_interactReceiver.ResetInteraction();
|
||||||
|
_interactReceiver.EnableInteraction();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_interactReceiver.DisableInteraction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -20,5 +20,10 @@ namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
|
|||||||
/// Whether the candle should start lit or extinguished.
|
/// Whether the candle should start lit or extinguished.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool startLit;
|
public bool startLit;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A condition to set when the candle is lit.
|
||||||
|
/// </summary>
|
||||||
|
public DreamLightConditionInfo condition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
31
NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamLightConditionInfo.cs
vendored
Normal file
31
NewHorizons/External/Modules/Props/EchoesOfTheEye/DreamLightConditionInfo.cs
vendored
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
|
||||||
|
{
|
||||||
|
public class DreamLightConditionInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the dialogue condition or persistent condition to set when the light is lit.
|
||||||
|
/// </summary>
|
||||||
|
public string condition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, the condition will persist across all future loops until unset.
|
||||||
|
/// </summary>
|
||||||
|
public bool persistent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to unset the condition when the light is extinguished again.
|
||||||
|
/// </summary>
|
||||||
|
public bool reversible;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to set the condition when the light is extinguished instead. If `reversible` is true, the condition will be unset when the light is lit again.
|
||||||
|
/// </summary>
|
||||||
|
public bool onExtinguish;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -45,5 +45,10 @@ namespace NewHorizons.External.Modules.Props.EchoesOfTheEye
|
|||||||
/// If set, projected objects will be set to fully active or fully disabled instantly instead of smoothly fading lights/renderers/colliders. Use this if the normal behavior is insufficient for the objects you're using.
|
/// If set, projected objects will be set to fully active or fully disabled instantly instead of smoothly fading lights/renderers/colliders. Use this if the normal behavior is insufficient for the objects you're using.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool toggleProjectedObjectsActive;
|
public bool toggleProjectedObjectsActive;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A condition to set when the totem is lit.
|
||||||
|
/// </summary>
|
||||||
|
public DreamLightConditionInfo condition;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,8 +6,8 @@ namespace NewHorizons.External.Modules.VariableSize
|
|||||||
public class VariableSizeModule
|
public class VariableSizeModule
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Scale this object over time. Time value is in minutes.
|
/// Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TimeValuePair[] curve;
|
public TimeValuePair[] curve;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
39
NewHorizons/External/Modules/Volumes/VolumeInfos/ConditionTriggerVolumeInfo.cs
vendored
Normal file
39
NewHorizons/External/Modules/Volumes/VolumeInfos/ConditionTriggerVolumeInfo.cs
vendored
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System.ComponentModel;
|
||||||
|
|
||||||
|
namespace NewHorizons.External.Modules.Volumes.VolumeInfos
|
||||||
|
{
|
||||||
|
[JsonObject]
|
||||||
|
public class ConditionTriggerVolumeInfo : VolumeInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the dialogue condition or persistent condition to set when entering the volume.
|
||||||
|
/// </summary>
|
||||||
|
public string condition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, the condition will persist across all future loops until unset.
|
||||||
|
/// </summary>
|
||||||
|
public bool persistent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to unset the condition when existing the volume.
|
||||||
|
/// </summary>
|
||||||
|
public bool reversible;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to set the condition when the player enters this volume. Defaults to true.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(true)] public bool player = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to set the condition when the scout probe enters this volume.
|
||||||
|
/// </summary>
|
||||||
|
public bool probe;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to set the condition when the ship enters this volume.
|
||||||
|
/// </summary>
|
||||||
|
public bool ship;
|
||||||
|
}
|
||||||
|
}
|
||||||
65
NewHorizons/External/Modules/Volumes/VolumeInfos/InteractionVolumeInfo.cs
vendored
Normal file
65
NewHorizons/External/Modules/Volumes/VolumeInfos/InteractionVolumeInfo.cs
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace NewHorizons.External.Modules.Volumes.VolumeInfos
|
||||||
|
{
|
||||||
|
[JsonObject]
|
||||||
|
public class InteractionVolumeInfo : VolumeInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The prompt to display when the volume is interacted with.
|
||||||
|
/// </summary>
|
||||||
|
public string prompt;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The range at which the volume can be interacted with.
|
||||||
|
/// </summary>
|
||||||
|
[DefaultValue(2f)] public float range = 2f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The max view angle (in degrees) the player can see the volume with to interact with it. This will effectively be a cone extending from the volume's center forwards (along the Z axis) based on the volume's rotation.
|
||||||
|
/// If not specified, no view angle restriction will be applied.
|
||||||
|
/// </summary>
|
||||||
|
public float? maxViewAngle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the volume can be interacted with while in the ship.
|
||||||
|
/// </summary>
|
||||||
|
public bool usableInShip;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether the volume can be interacted with multiple times.
|
||||||
|
/// </summary>
|
||||||
|
public bool reusable;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the dialogue condition or persistent condition to set when the volume is interacted with.
|
||||||
|
/// </summary>
|
||||||
|
public string condition;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If true, the condition will persist across all future loops until unset.
|
||||||
|
/// </summary>
|
||||||
|
public bool persistent;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A sound to play when the volume is interacted with. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list.
|
||||||
|
/// </summary>
|
||||||
|
public string audio;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A path to an animator component where an animation will be triggered when the volume is interacted with.
|
||||||
|
/// </summary>
|
||||||
|
public string pathToAnimator;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of an animation trigger to set on the animator when the volume is interacted with.
|
||||||
|
/// </summary>
|
||||||
|
public string animationTrigger;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -11,6 +11,11 @@ namespace NewHorizons.External.Modules.Volumes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public AudioVolumeInfo[] audioVolumes;
|
public AudioVolumeInfo[] audioVolumes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add condition trigger volumes to this planet. Sets a condition when the player, scout, or ship enters this volume.
|
||||||
|
/// </summary>
|
||||||
|
public ConditionTriggerVolumeInfo[] conditionTriggerVolumes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add day night audio volumes to this planet. These volumes play a different clip depending on the time of day.
|
/// Add day night audio volumes to this planet. These volumes play a different clip depending on the time of day.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -38,6 +43,12 @@ namespace NewHorizons.External.Modules.Volumes
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public HazardVolumeInfo[] hazardVolumes;
|
public HazardVolumeInfo[] hazardVolumes;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add interaction volumes to this planet.
|
||||||
|
/// They can be interacted with by the player to trigger various effects.
|
||||||
|
/// </summary>
|
||||||
|
public InteractionVolumeInfo[] interactionVolumes;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add interference volumes to this planet.
|
/// Add interference volumes to this planet.
|
||||||
/// Hides HUD markers of ship scout/probe and prevents scout photos if you are not inside the volume together with ship or scout probe.
|
/// Hides HUD markers of ship scout/probe and prevents scout photos if you are not inside the volume together with ship or scout probe.
|
||||||
|
|||||||
@ -42,6 +42,16 @@ namespace NewHorizons.Handlers
|
|||||||
|
|
||||||
public static void Init(List<NewHorizonsBody> bodies)
|
public static void Init(List<NewHorizonsBody> bodies)
|
||||||
{
|
{
|
||||||
|
// TH gets preloaded in title screen. custom systems dont need this
|
||||||
|
if (Main.Instance.CurrentStarSystem is not ("SolarSystem" or "EyeOfTheUniverse"))
|
||||||
|
{
|
||||||
|
foreach (var bundle in StreamingManager.s_activeBundles)
|
||||||
|
{
|
||||||
|
// save memory NOW instead of next frame when other stuff has loaded and taken memory
|
||||||
|
bundle.UnloadImmediate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Start by destroying all planets if need be
|
// Start by destroying all planets if need be
|
||||||
if (Main.SystemDict[Main.Instance.CurrentStarSystem].Config.destroyStockPlanets)
|
if (Main.SystemDict[Main.Instance.CurrentStarSystem].Config.destroyStockPlanets)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -83,7 +83,7 @@ namespace NewHorizons
|
|||||||
|
|
||||||
public GameObject GetPlanet(string name)
|
public GameObject GetPlanet(string name)
|
||||||
{
|
{
|
||||||
return Main.BodyDict.Values.SelectMany(x => x)?.ToList()?.FirstOrDefault(x => x.Config.name == name)?.Object;
|
return Main.BodyDict[Main.Instance.CurrentStarSystem].FirstOrDefault(x => x.Config.name == name)?.Object;
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetCurrentStarSystem() => Main.Instance.CurrentStarSystem;
|
public string GetCurrentStarSystem() => Main.Instance.CurrentStarSystem;
|
||||||
|
|||||||
@ -45,7 +45,9 @@ namespace NewHorizons.Patches.SignalPatches
|
|||||||
SignalFrequency.HideAndSeek => 5,
|
SignalFrequency.HideAndSeek => 5,
|
||||||
SignalFrequency.Radio => 6,
|
SignalFrequency.Radio => 6,
|
||||||
SignalFrequency.Statue => 7,
|
SignalFrequency.Statue => 7,
|
||||||
_ => (int)(Mathf.Log((float)frequency) / Mathf.Log(2f)),// Frequencies are in powers of 2
|
// Can't cast to int because floating point error, it was doing 12.9999999 -> 12
|
||||||
|
// Frequencies are in powers of 2
|
||||||
|
_ => Mathf.RoundToInt(Mathf.Log((float)frequency) / Mathf.Log(2f)),
|
||||||
};
|
};
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -11,7 +11,7 @@ namespace NewHorizons.Patches.SignalPatches
|
|||||||
[HarmonyPatch(nameof(Signalscope.Awake))]
|
[HarmonyPatch(nameof(Signalscope.Awake))]
|
||||||
public static void Signalscope_Awake(Signalscope __instance)
|
public static void Signalscope_Awake(Signalscope __instance)
|
||||||
{
|
{
|
||||||
__instance._strongestSignals = new AudioSignal[8];
|
__instance._strongestSignals = new AudioSignal[32];
|
||||||
}
|
}
|
||||||
|
|
||||||
[HarmonyPrefix]
|
[HarmonyPrefix]
|
||||||
|
|||||||
@ -1846,7 +1846,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"curve": {
|
"curve": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Scale this object over time. Time value is in minutes.",
|
"description": "Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/TimeValuePair"
|
"$ref": "#/definitions/TimeValuePair"
|
||||||
}
|
}
|
||||||
@ -2035,7 +2035,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"curve": {
|
"curve": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Scale this object over time. Time value is in minutes.",
|
"description": "Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/TimeValuePair"
|
"$ref": "#/definitions/TimeValuePair"
|
||||||
}
|
}
|
||||||
@ -4571,6 +4571,10 @@
|
|||||||
"startLit": {
|
"startLit": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "Whether the candle should start lit or extinguished."
|
"description": "Whether the candle should start lit or extinguished."
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"description": "A condition to set when the candle is lit.",
|
||||||
|
"$ref": "#/definitions/DreamLightConditionInfo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4600,6 +4604,28 @@
|
|||||||
"pile"
|
"pile"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"DreamLightConditionInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"condition": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the dialogue condition or persistent condition to set when the light is lit."
|
||||||
|
},
|
||||||
|
"persistent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "If true, the condition will persist across all future loops until unset."
|
||||||
|
},
|
||||||
|
"reversible": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to unset the condition when the light is extinguished again."
|
||||||
|
},
|
||||||
|
"onExtinguish": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to set the condition when the light is extinguished instead. If `reversible` is true, the condition will be unset when the light is lit again."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"ProjectionTotemInfo": {
|
"ProjectionTotemInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@ -4667,6 +4693,10 @@
|
|||||||
"toggleProjectedObjectsActive": {
|
"toggleProjectedObjectsActive": {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If set, projected objects will be set to fully active or fully disabled instantly instead of smoothly fading lights/renderers/colliders. Use this if the normal behavior is insufficient for the objects you're using."
|
"description": "If set, projected objects will be set to fully active or fully disabled instantly instead of smoothly fading lights/renderers/colliders. Use this if the normal behavior is insufficient for the objects you're using."
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"description": "A condition to set when the totem is lit.",
|
||||||
|
"$ref": "#/definitions/DreamLightConditionInfo"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -4778,7 +4808,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"curve": {
|
"curve": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Scale this object over time. Time value is in minutes.",
|
"description": "Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/TimeValuePair"
|
"$ref": "#/definitions/TimeValuePair"
|
||||||
}
|
}
|
||||||
@ -5059,7 +5089,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"curve": {
|
"curve": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Scale this object over time. Time value is in minutes.",
|
"description": "Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/TimeValuePair"
|
"$ref": "#/definitions/TimeValuePair"
|
||||||
}
|
}
|
||||||
@ -5225,7 +5255,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"curve": {
|
"curve": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Scale this object over time. Time value is in minutes.",
|
"description": "Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/TimeValuePair"
|
"$ref": "#/definitions/TimeValuePair"
|
||||||
}
|
}
|
||||||
@ -5365,6 +5395,13 @@
|
|||||||
"$ref": "#/definitions/AudioVolumeInfo"
|
"$ref": "#/definitions/AudioVolumeInfo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"conditionTriggerVolumes": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Add condition trigger volumes to this planet. Sets a condition when the player, scout, or ship enters this volume.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/ConditionTriggerVolumeInfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
"dayNightAudioVolumes": {
|
"dayNightAudioVolumes": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Add day night audio volumes to this planet. These volumes play a different clip depending on the time of day.",
|
"description": "Add day night audio volumes to this planet. These volumes play a different clip depending on the time of day.",
|
||||||
@ -5397,6 +5434,13 @@
|
|||||||
"$ref": "#/definitions/HazardVolumeInfo"
|
"$ref": "#/definitions/HazardVolumeInfo"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"interactionVolumes": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Add interaction volumes to this planet.\nThey can be interacted with by the player to trigger various effects.",
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/definitions/InteractionVolumeInfo"
|
||||||
|
}
|
||||||
|
},
|
||||||
"interferenceVolumes": {
|
"interferenceVolumes": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Add interference volumes to this planet.\nHides HUD markers of ship scout/probe and prevents scout photos if you are not inside the volume together with ship or scout probe.",
|
"description": "Add interference volumes to this planet.\nHides HUD markers of ship scout/probe and prevents scout photos if you are not inside the volume together with ship or scout probe.",
|
||||||
@ -5724,6 +5768,74 @@
|
|||||||
"manual"
|
"manual"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"ConditionTriggerVolumeInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"radius": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The radius of this volume, if a shape is not specified.",
|
||||||
|
"format": "float",
|
||||||
|
"default": 1.0
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"description": "The shape of this volume. Defaults to a sphere with a radius of `radius` if not specified.",
|
||||||
|
"$ref": "#/definitions/ShapeInfo"
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"description": "Rotation of the object",
|
||||||
|
"$ref": "#/definitions/MVector3"
|
||||||
|
},
|
||||||
|
"alignRadial": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else."
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"description": "Position of the object",
|
||||||
|
"$ref": "#/definitions/MVector3"
|
||||||
|
},
|
||||||
|
"isRelativeToParent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object."
|
||||||
|
},
|
||||||
|
"parentPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||||
|
},
|
||||||
|
"rename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "An optional rename of this object"
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the dialogue condition or persistent condition to set when entering the volume."
|
||||||
|
},
|
||||||
|
"persistent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "If true, the condition will persist across all future loops until unset."
|
||||||
|
},
|
||||||
|
"reversible": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to unset the condition when existing the volume."
|
||||||
|
},
|
||||||
|
"player": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to set the condition when the player enters this volume. Defaults to true.",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
"probe": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to set the condition when the scout probe enters this volume."
|
||||||
|
},
|
||||||
|
"ship": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to set the condition when the ship enters this volume."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"DayNightAudioVolumeInfo": {
|
"DayNightAudioVolumeInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@ -6528,6 +6640,95 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"InteractionVolumeInfo": {
|
||||||
|
"type": "object",
|
||||||
|
"additionalProperties": false,
|
||||||
|
"properties": {
|
||||||
|
"radius": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The radius of this volume, if a shape is not specified.",
|
||||||
|
"format": "float",
|
||||||
|
"default": 1.0
|
||||||
|
},
|
||||||
|
"shape": {
|
||||||
|
"description": "The shape of this volume. Defaults to a sphere with a radius of `radius` if not specified.",
|
||||||
|
"$ref": "#/definitions/ShapeInfo"
|
||||||
|
},
|
||||||
|
"rotation": {
|
||||||
|
"description": "Rotation of the object",
|
||||||
|
"$ref": "#/definitions/MVector3"
|
||||||
|
},
|
||||||
|
"alignRadial": {
|
||||||
|
"type": [
|
||||||
|
"boolean",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"description": "Do we try to automatically align this object to stand upright relative to the body's center? Stacks with rotation.\nDefaults to true for geysers, tornados, and volcanoes, and false for everything else."
|
||||||
|
},
|
||||||
|
"position": {
|
||||||
|
"description": "Position of the object",
|
||||||
|
"$ref": "#/definitions/MVector3"
|
||||||
|
},
|
||||||
|
"isRelativeToParent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the positional and rotational coordinates are relative to parent instead of the root planet object."
|
||||||
|
},
|
||||||
|
"parentPath": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)."
|
||||||
|
},
|
||||||
|
"rename": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "An optional rename of this object"
|
||||||
|
},
|
||||||
|
"prompt": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The prompt to display when the volume is interacted with."
|
||||||
|
},
|
||||||
|
"range": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "The range at which the volume can be interacted with.",
|
||||||
|
"format": "float",
|
||||||
|
"default": 2.0
|
||||||
|
},
|
||||||
|
"maxViewAngle": {
|
||||||
|
"type": [
|
||||||
|
"null",
|
||||||
|
"number"
|
||||||
|
],
|
||||||
|
"description": "The max view angle (in degrees) the player can see the volume with to interact with it. This will effectively be a cone extending from the volume's center forwards (along the Z axis) based on the volume's rotation.\nIf not specified, no view angle restriction will be applied.",
|
||||||
|
"format": "float"
|
||||||
|
},
|
||||||
|
"usableInShip": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the volume can be interacted with while in the ship."
|
||||||
|
},
|
||||||
|
"reusable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether the volume can be interacted with multiple times."
|
||||||
|
},
|
||||||
|
"condition": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of the dialogue condition or persistent condition to set when the volume is interacted with."
|
||||||
|
},
|
||||||
|
"persistent": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "If true, the condition will persist across all future loops until unset."
|
||||||
|
},
|
||||||
|
"audio": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A sound to play when the volume is interacted with. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list."
|
||||||
|
},
|
||||||
|
"pathToAnimator": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "A path to an animator component where an animation will be triggered when the volume is interacted with. "
|
||||||
|
},
|
||||||
|
"animationTrigger": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The name of an animation trigger to set on the animator when the volume is interacted with."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"VolumeInfo": {
|
"VolumeInfo": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"additionalProperties": false,
|
"additionalProperties": false,
|
||||||
@ -7629,7 +7830,7 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"curve": {
|
"curve": {
|
||||||
"type": "array",
|
"type": "array",
|
||||||
"description": "Scale this object over time. Time value is in minutes.",
|
"description": "Scale this object over time. Time is in minutes. Value is a multiplier of the size of the object.",
|
||||||
"items": {
|
"items": {
|
||||||
"$ref": "#/definitions/TimeValuePair"
|
"$ref": "#/definitions/TimeValuePair"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, and friends",
|
"author": "xen, Bwc9876, JohnCorby, MegaPiggy, and friends",
|
||||||
"name": "New Horizons",
|
"name": "New Horizons",
|
||||||
"uniqueName": "xen.NewHorizons",
|
"uniqueName": "xen.NewHorizons",
|
||||||
"version": "1.28.4",
|
"version": "1.28.8",
|
||||||
"owmlVersion": "2.12.1",
|
"owmlVersion": "2.12.1",
|
||||||
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
"dependencies": [ "JohnCorby.VanillaFix", "xen.CommonCameraUtility", "dgarro.CustomShipLogModes" ],
|
||||||
"conflicts": [ "PacificEngine.OW_CommonResources" ],
|
"conflicts": [ "PacificEngine.OW_CommonResources" ],
|
||||||
|
|||||||
@ -23,4 +23,6 @@ To unlock ship logs after reading each text block, add a `<ShipLogConditions>` n
|
|||||||
|
|
||||||
In your planet config, you must define where the Nomai text is positioned. See [the translator text json schema](/schemas/body-schema/defs/translatortextinfo/) for more info.
|
In your planet config, you must define where the Nomai text is positioned. See [the translator text json schema](/schemas/body-schema/defs/translatortextinfo/) for more info.
|
||||||
|
|
||||||
You can input a `seed` for a wall of text which will randomly generate the position of each arc. To test out different combinations, just keep incrementing the number and then hit "Reload Configs" from the pause menu with debug mode on. This seed ensures the same positioning each time the mod is played. Alternatively, you can use `arcInfo` to set the position and rotation of all text arcs, as well as determining their types (adult, teenager, child, or Stranger). The various age stages make the text look messier, while Stranger allows you to make a translatable version of the DLC text.
|
You can input a `seed` for a wall of text which will randomly generate the position of each arc. To test out different combinations, just keep incrementing the number and then hit "Reload Configs" from the pause menu with debug mode on. This seed ensures the same positioning each time the mod is played. Alternatively, you can use `arcInfo` to set the position and rotation of all text arcs, as well as determining their types (adult, teenager, child, or Stranger). The various age stages make the text look messier, while Stranger allows you to make a translatable version of the DLC text.
|
||||||
|
|
||||||
|
If you decide to arrange text manually in your mod, the [Unity Explorer](https://outerwildsmods.com/mods/unityexplorer/) and [Nomai Text Printer](https://github.com/coderCleric/NomaiTextPrinter) mods can make that much more convenient.
|
||||||
@ -56,6 +56,7 @@ These mods are useful when developing your addon
|
|||||||
- [Save Editor](https://outerwildsmods.com/mods/saveeditor) - Useful when creating a custom [ship log](/ship-log), can be used to reveal all custom facts so you can see them in the ship's computer.
|
- [Save Editor](https://outerwildsmods.com/mods/saveeditor) - Useful when creating a custom [ship log](/ship-log), can be used to reveal all custom facts so you can see them in the ship's computer.
|
||||||
- [Time Saver](https://outerwildsmods.com/mods/timesaver/) - Lets you skip some repeated cutscenes and get into the game faster.
|
- [Time Saver](https://outerwildsmods.com/mods/timesaver/) - Lets you skip some repeated cutscenes and get into the game faster.
|
||||||
- [The Examples Mod](https://github.com/Outer-Wilds-New-Horizons/nh-examples) - A mod that contains examples of how to use New Horizons features.
|
- [The Examples Mod](https://github.com/Outer-Wilds-New-Horizons/nh-examples) - A mod that contains examples of how to use New Horizons features.
|
||||||
|
- [Nomai Text Printer](https://github.com/coderCleric/NomaiTextPrinter) - Useful for saving text changes (such as moving arcs with Unity Explorer) to your json files.
|
||||||
|
|
||||||
## Helpful Tools
|
## Helpful Tools
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user