Hallucination system setup & implementation with the infinite staircase + Fake volumetric lights test

This commit is contained in:
Ferlat Thibaud
2026-03-27 20:47:11 +01:00
parent 34d8ffd5b0
commit 395f6266d6
119 changed files with 44996 additions and 816 deletions
@@ -1,42 +1,86 @@
using System.Collections.Generic;
using UnityEngine;
using Unheimlich.Features.Dialogue.UI;
namespace Unheimlich.Features.Hallucination
{
// ─── Per-label override data ───────────────────────────────────────────────
/// <summary>
/// Describes how a specific FloatingLabel should behave when a HallucinationEvent fires.
/// </summary>
[System.Serializable]
public class FloatingLabelOverride
{
[Tooltip("The FloatingLabel to override when this event fires.")]
public FloatingLabel Target;
[Header("Shake Override")]
[Tooltip("Absolute shake radius applied during the override (world units). 0 = no shake.")]
[Min(0f)] public float ShakeRadius = 0.15f;
[Tooltip("Shake speed during the override.")]
[Min(0f)] public float ShakeSpeed = 3f;
[Tooltip("Shake smoothness during the override.")]
[Min(0f)] public float ShakeSmoothness = 4f;
[Header("Ghost Trail Override")]
public bool GhostEnabled = true;
[Range(0f, 1f)] public float GhostAlpha = 0.5f;
[Header("Duration")]
[Tooltip("How long the override lasts (seconds) before reverting to the sanity baseline.")]
[Min(0f)] public float Duration = 2f;
}
// ─── ScriptableObject ──────────────────────────────────────────────────────
/// <summary>
/// ScriptableObject describing a discrete hallucination event.
/// Configure in the inspector and pass to HallucinationManager.TriggerHallucinationEvent().
///
/// Ghost word spawn removed. Words live on FloatingLabel components in the scene.
/// LabelOverrides targets specific labels with timed shake/ghost overrides.
/// </summary>
[CreateAssetMenu(fileName = "HallucinationEvent", menuName = "Unheimlich/Hallucination/Hallucination Event")]
[CreateAssetMenu(
fileName = "HallucinationEvent",
menuName = "Unheimlich/Hallucination/Hallucination Event")]
public class HallucinationEvent : ScriptableObject
{
[Header("Identity")]
[Tooltip("Human-readable label for this event (used in logs and the inspector)")]
[SerializeField] private string _label;
[Header("Ghost Word")]
[Tooltip("Spawn a ghost word that moves toward the player")]
[SerializeField] private bool _spawnGhostWord;
[Tooltip("Text displayed by the ghost word")]
[SerializeField] private string _ghostWordText;
[Tooltip("World-space spawn position offset from the anchor point")]
[SerializeField] private Vector3 _ghostWordSpawnOffset = new Vector3(0f, 1.5f, 2f);
[Tooltip("Duration before the ghost word disappears (seconds)")]
[SerializeField] private float _ghostWordLifetime = 3f;
[Header("Sanity Cost")]
[Tooltip("Sanity added to the player when this event fires (0 = no change)")]
[SerializeField, Range(0f, 1f)] private float _sanityCost = 0f;
// ─── Public Accessors ──────────────────────────────────────────────────────
[Header("Floating Label Overrides")]
[Tooltip("One entry per FloatingLabel to affect when this event fires.")]
[SerializeField] private List<FloatingLabelOverride> _labelOverrides = new();
public string Label => _label;
public bool SpawnGhostWord => _spawnGhostWord;
public string GhostWordText => _ghostWordText;
public Vector3 GhostWordSpawnOffset => _ghostWordSpawnOffset;
public float GhostWordLifetime => _ghostWordLifetime;
public float SanityCost => _sanityCost;
// ─── Public Accessors ──────────────────────────────────────────────────
public string Label => _label;
public float SanityCost => _sanityCost;
public IReadOnlyList<FloatingLabelOverride> LabelOverrides => _labelOverrides;
// ─── Internal ─────────────────────────────────────────────────────────
/// <summary>
/// Pushes all label overrides onto their target FloatingLabels.
/// Called by HallucinationManager.TriggerHallucinationEvent().
/// </summary>
internal void ApplyLabelOverrides()
{
foreach (FloatingLabelOverride entry in _labelOverrides)
{
if (entry.Target == null) continue;
entry.Target.ApplyOverride(
entry.ShakeRadius,
entry.ShakeSpeed,
entry.ShakeSmoothness,
entry.GhostEnabled,
entry.GhostAlpha,
entry.Duration);
}
}
}
}
}