2026-09-29 16:11:54 +01:00
|
|
|
using UnityEngine;
|
|
|
|
|
using UnityEngine.UI;
|
|
|
|
|
|
|
|
|
|
public class PlayerUIManager : MonoBehaviour
|
|
|
|
|
{
|
|
|
|
|
[Header("References")]
|
|
|
|
|
[Tooltip("Drag the Player (or the GameObject with PlayerStats) here")]
|
|
|
|
|
public PlayerStats playerStats;
|
|
|
|
|
|
|
|
|
|
[Header("UI Bars (Sliders)")]
|
|
|
|
|
[Tooltip("Assign if you are using Unity UI Sliders for your bars")]
|
|
|
|
|
public Slider healthBar;
|
|
|
|
|
public Slider manaBar;
|
|
|
|
|
public Slider staminaBar;
|
|
|
|
|
|
|
|
|
|
[Header("UI Bars (Images - Fill Method)")]
|
|
|
|
|
[Tooltip("Assign if you are using UI Images with Image Type set to 'Filled'")]
|
|
|
|
|
public Image healthFill;
|
|
|
|
|
public Image manaFill;
|
|
|
|
|
public Image staminaFill;
|
|
|
|
|
|
2026-09-30 16:39:18 +01:00
|
|
|
[Header("Combat UI")]
|
|
|
|
|
public BowAimLayerController bowAimLayerController;
|
|
|
|
|
[Tooltip("A Slider that fills up from 0 to 1 as the bow is drawn.")]
|
|
|
|
|
public Slider bowDrawBar;
|
|
|
|
|
|
2026-10-01 15:14:37 +01:00
|
|
|
[Header("Quest UI")]
|
|
|
|
|
[Tooltip("The parent GameObject that holds all the Quest UI elements (allows us to hide the whole window when empty)")]
|
|
|
|
|
public GameObject questUIPanel;
|
|
|
|
|
[Tooltip("The TextMeshPro text for the name of the Quest")]
|
|
|
|
|
public TMPro.TextMeshProUGUI questNameText;
|
|
|
|
|
[Tooltip("The container transform where the Objective prefabs will be spawned (e.g., a Vertical Layout Group)")]
|
|
|
|
|
public Transform objectivesContainer;
|
|
|
|
|
[Tooltip("The prefab for a single objective row (Should have the QuestObjectiveUI script on it)")]
|
|
|
|
|
public QuestObjectiveUI objectivePrefab;
|
|
|
|
|
|
|
|
|
|
[Header("Interaction UI")]
|
|
|
|
|
[Tooltip("The parent GameObject for the interaction popup")]
|
|
|
|
|
public GameObject interactionPanel;
|
|
|
|
|
[Tooltip("The TMPro Text that shows the primary interaction prompt (e.g., 'Collect')")]
|
|
|
|
|
public TMPro.TextMeshProUGUI interactionText;
|
|
|
|
|
[Tooltip("The secondary TMPro Text for the interaction prompt (e.g., 'Press E' or the Item Name)")]
|
|
|
|
|
public TMPro.TextMeshProUGUI interactionSecondaryText;
|
|
|
|
|
|
|
|
|
|
[Header("Crosshair UI")]
|
|
|
|
|
[Tooltip("The crosshair image in the center of the screen")]
|
|
|
|
|
public GameObject crosshairImage;
|
|
|
|
|
|
2026-09-29 16:11:54 +01:00
|
|
|
private void Start()
|
|
|
|
|
{
|
|
|
|
|
if (playerStats == null)
|
|
|
|
|
{
|
|
|
|
|
Debug.LogWarning("PlayerUIManager: PlayerStats reference is missing! Please assign it in the Inspector.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Initialize Slider max values if they are being used
|
|
|
|
|
if (healthBar != null) healthBar.maxValue = playerStats.maxHealth;
|
|
|
|
|
if (manaBar != null) manaBar.maxValue = playerStats.maxMana;
|
|
|
|
|
if (staminaBar != null) staminaBar.maxValue = playerStats.maxStamina;
|
2026-09-30 16:39:18 +01:00
|
|
|
|
|
|
|
|
if (bowDrawBar != null)
|
|
|
|
|
{
|
|
|
|
|
bowDrawBar.minValue = 0f;
|
|
|
|
|
bowDrawBar.maxValue = 1f;
|
|
|
|
|
bowDrawBar.value = 0f;
|
|
|
|
|
}
|
2026-10-01 15:14:37 +01:00
|
|
|
|
|
|
|
|
// Try to connect to the Quest Manager to listen for updates
|
|
|
|
|
if (QuestManager.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
QuestManager.Instance.onQuestUpdated += DrawQuestUI;
|
|
|
|
|
DrawQuestUI(); // Draw initial state
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void OnDestroy()
|
|
|
|
|
{
|
|
|
|
|
// Unsubscribe to prevent memory leaks
|
|
|
|
|
if (QuestManager.Instance != null)
|
|
|
|
|
{
|
|
|
|
|
QuestManager.Instance.onQuestUpdated -= DrawQuestUI;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DrawQuestUI()
|
|
|
|
|
{
|
|
|
|
|
// If there's no Quest Manager or no active quest, hide the UI completely
|
|
|
|
|
if (QuestManager.Instance == null || QuestManager.Instance.activeQuest == null || string.IsNullOrEmpty(QuestManager.Instance.activeQuest.questName))
|
|
|
|
|
{
|
|
|
|
|
if (questUIPanel != null) questUIPanel.SetActive(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Quest activeQuest = QuestManager.Instance.activeQuest;
|
|
|
|
|
|
|
|
|
|
// 1. Show the panel and update the Name
|
|
|
|
|
if (questUIPanel != null) questUIPanel.SetActive(true);
|
|
|
|
|
if (questNameText != null) questNameText.text = activeQuest.questName;
|
|
|
|
|
|
|
|
|
|
// 2. Clear existing objectives in the container
|
|
|
|
|
if (objectivesContainer != null)
|
|
|
|
|
{
|
|
|
|
|
foreach (Transform child in objectivesContainer)
|
|
|
|
|
{
|
|
|
|
|
Destroy(child.gameObject);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 3. Spawn a prefab for each objective
|
|
|
|
|
if (objectivePrefab != null)
|
|
|
|
|
{
|
|
|
|
|
bool foundActive = false;
|
|
|
|
|
foreach (var objective in activeQuest.objectives)
|
|
|
|
|
{
|
|
|
|
|
QuestObjectiveUI newObjUI = Instantiate(objectivePrefab, objectivesContainer);
|
|
|
|
|
|
|
|
|
|
// Determine if THIS objective is the active one
|
|
|
|
|
// (The first incomplete objective in the list)
|
|
|
|
|
bool isThisActive = false;
|
|
|
|
|
if (!objective.isCompleted && !foundActive)
|
|
|
|
|
{
|
|
|
|
|
isThisActive = true;
|
|
|
|
|
foundActive = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string countText = "";
|
|
|
|
|
if (objective.requiresCount)
|
|
|
|
|
{
|
|
|
|
|
countText = $" ({objective.currentCount}/{objective.targetCount})";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
newObjUI.Setup(objective.description, isThisActive, objective.isCompleted, countText);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-29 16:11:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Update()
|
|
|
|
|
{
|
|
|
|
|
UpdateBars();
|
2026-09-30 16:39:18 +01:00
|
|
|
UpdateCombatUI();
|
2026-10-01 15:14:37 +01:00
|
|
|
UpdateCrosshair();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateCrosshair()
|
|
|
|
|
{
|
|
|
|
|
if (crosshairImage != null)
|
|
|
|
|
{
|
|
|
|
|
// Only show crosshair if we have a bow equipped and are currently holding aim/draw
|
|
|
|
|
bool shouldShow = bowAimLayerController != null && bowAimLayerController.IsAiming && bowAimLayerController.IsDrawing;
|
|
|
|
|
crosshairImage.SetActive(shouldShow);
|
|
|
|
|
}
|
2026-09-29 16:11:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateBars()
|
|
|
|
|
{
|
2026-09-30 16:39:18 +01:00
|
|
|
if (playerStats == null) return;
|
|
|
|
|
|
2026-09-29 16:11:54 +01:00
|
|
|
// 1. Update Sliders (if assigned)
|
|
|
|
|
if (healthBar != null) healthBar.value = playerStats.currentHealth;
|
|
|
|
|
if (manaBar != null) manaBar.value = playerStats.currentMana;
|
|
|
|
|
if (staminaBar != null) staminaBar.value = playerStats.currentStamina;
|
|
|
|
|
|
|
|
|
|
// 2. Update Image Fills (if assigned)
|
|
|
|
|
if (healthFill != null) healthFill.fillAmount = playerStats.currentHealth / playerStats.maxHealth;
|
|
|
|
|
if (manaFill != null) manaFill.fillAmount = playerStats.currentMana / playerStats.maxMana;
|
|
|
|
|
if (staminaFill != null) staminaFill.fillAmount = playerStats.currentStamina / playerStats.maxStamina;
|
|
|
|
|
}
|
2026-09-30 16:39:18 +01:00
|
|
|
|
|
|
|
|
private void UpdateCombatUI()
|
|
|
|
|
{
|
|
|
|
|
if (bowDrawBar != null && bowAimLayerController != null)
|
|
|
|
|
{
|
|
|
|
|
float drawPercentage = bowAimLayerController.CurrentDrawPercentage;
|
|
|
|
|
bowDrawBar.value = drawPercentage;
|
|
|
|
|
|
|
|
|
|
// Optional: Hide the bar completely if we aren't drawing the bow
|
|
|
|
|
bowDrawBar.gameObject.SetActive(drawPercentage > 0f);
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-09-29 16:11:54 +01:00
|
|
|
}
|