mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Interaction volumes
This commit is contained in:
parent
7223a4f523
commit
1330df64b4
87
NewHorizons/Builder/Volumes/InteractionVolumeBuilder.cs
Normal file
87
NewHorizons/Builder/Volumes/InteractionVolumeBuilder.cs
Normal file
@ -0,0 +1,87 @@
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -70,6 +70,13 @@ namespace NewHorizons.Builder.Volumes
|
||||
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)
|
||||
{
|
||||
foreach (var interferenceVolume in config.Volumes.interferenceVolumes)
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -43,6 +43,12 @@ namespace NewHorizons.External.Modules.Volumes
|
||||
/// </summary>
|
||||
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>
|
||||
/// 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.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user