using System.Collections.Generic;
using UnityEngine;
using UnityEngine.InputSystem;
using TMPro;
/// <summary>
/// GAME 1303 Tier 6 — Shows "Press E to Examine" over the nearest Interactable and
/// handles the button press. ONE of these on the player covers the whole game.
///
/// SETUP
/// 1. Add to the player object.
/// 2. Input: add an "Interact" Button action to the Player map (E key, gamepad South/A).
/// This listens for OnInteract.
/// 3. Prompt UI: make a small world-space Canvas prefab with a TMP text (and optionally
/// a key icon), drag it into Prompt Prefab. It's spawned once and moved around.
/// If you'd rather use a screen-space UI, drag an existing object into Prompt Instance
/// and tick Screen Space — it will just show/hide and set the text.
/// 4. When several interactables overlap, the closest one wins.
/// 5. Block While Dialogue Open is on by default so pressing E to advance dialogue
/// doesn't also re-trigger the thing you're talking to.
/// </summary>
public class InteractionPrompt : MonoBehaviour
{
[Header("Prompt UI")]
public GameObject promptPrefab;
public GameObject promptInstance;
public bool screenSpace = false;
public string format = "[E] {0}";
[Header("Rules")]
public bool blockWhileDialogueOpen = true;
private static readonly List<Interactable> inRange = new List<Interactable>();
private TMP_Text promptLabel;
private Interactable current;
public static void Register(Interactable i) { if (!inRange.Contains(i)) inRange.Add(i); }
public static void Unregister(Interactable i) { inRange.Remove(i); }
void Awake()
{
if (promptInstance == null && promptPrefab != null)
promptInstance = Instantiate(promptPrefab);
if (promptInstance != null)
{
promptLabel = promptInstance.GetComponentInChildren<TMP_Text>();
promptInstance.SetActive(false);
}
}
void OnDestroy() => inRange.Clear();
void Update()
{
inRange.RemoveAll(i => i == null);
current = Closest();
bool show = current != null && !DialogueBlocked();
if (promptInstance != null)
{
if (promptInstance.activeSelf != show) promptInstance.SetActive(show);
if (show)
{
if (promptLabel != null) promptLabel.text = string.Format(format, current.promptText);
if (!screenSpace) promptInstance.transform.position = current.PromptPosition;
}
}
}
Interactable Closest()
{
Interactable best = null;
float bestDist = float.MaxValue;
foreach (var i in inRange)
{
if (i == null || !i.IsAvailable) continue;
float d = Vector2.Distance(transform.position, i.transform.position);
if (d < bestDist) { bestDist = d; best = i; }
}
return best;
}
bool DialogueBlocked() => blockWhileDialogueOpen && DialogueRunner.IsAnyOpen;
void OnInteract(InputValue value)
{
if (!value.isPressed) return;
// Dialogue takes priority: the same key advances the conversation
if (DialogueRunner.IsAnyOpen) { DialogueRunner.Active?.Advance(); return; }
if (current != null) current.Interact();
}
}