using System.Collections.Generic; using UnityEngine; using System; [System.Serializable] public class Objective { public string name; public string description; public bool isCompleted; public int totalItems; public int checkedItems; public int brokenItems; public Objective(string name, string description, int totalItems = 0) { this.name = name; this.description = description; this.isCompleted = false; this.totalItems = totalItems; this.checkedItems = 0; this.brokenItems = 0; } } public class LevelManager : MonoBehaviour { public static LevelManager Instance { get; private set; } [Header("Level Objectives")] [SerializeField] private List objectives = new List(); private Dictionary objectiveDict = new Dictionary(); private HashSet checkedObjects = new HashSet(); // Event that UI can subscribe to for showing the review prompt public event Action> OnRequestReview; // Event that fires when an objective is completed public event Action OnObjectiveCompleted; private GameObject currentReviewObject; private void Awake() { if (Instance != null && Instance != this) { Destroy(gameObject); return; } Instance = this; InitializeObjectives(); } private void InitializeObjectives() { // Clear existing objectives objectives.Clear(); objectiveDict.Clear(); checkedObjects.Clear(); // Add all objectives with item counts AddObjective("doors", "Check all doors open and close", CountObjectsWithTag("Door")); AddObjective("light_switches", "Check all light switches turn on and off", CountObjectsWithTag("LightSwitch")); AddObjective("lights", "Check all lights turn on and off", CountObjectsWithTag("Light")); AddObjective("toilets", "Check toilets work", CountObjectsWithTag("Toilet")); AddObjective("oven", "Check oven works", CountObjectsWithTag("Oven")); AddObjective("taps", "Check tap and sinks work", CountObjectsWithTag("Tap")); AddObjective("no_damage", "Check no damage to property", 1); } private int CountObjectsWithTag(string tag) { GameObject[] objects = GameObject.FindGameObjectsWithTag(tag); return objects != null ? objects.Length : 0; } private void AddObjective(string key, string description, int totalItems = 0) { Objective objective = new Objective(key, description, totalItems); objectives.Add(objective); objectiveDict[key] = objective; } public void CompleteObjective(string objectiveKey) { if (objectiveDict.ContainsKey(objectiveKey)) { objectiveDict[objectiveKey].isCompleted = true; Debug.Log($"Objective completed: {objectiveDict[objectiveKey].description}"); OnObjectiveCompleted?.Invoke(objectiveKey); CheckAllObjectivesComplete(); } else { Debug.LogWarning($"Objective '{objectiveKey}' not found!"); } } public bool IsObjectiveComplete(string objectiveKey) { return objectiveDict.ContainsKey(objectiveKey) && objectiveDict[objectiveKey].isCompleted; } public List GetAllObjectives() { return objectives; } public int GetCompletedCount() { int count = 0; foreach (var objective in objectives) { if (objective.isCompleted) count++; } return count; } private void CheckAllObjectivesComplete() { if (GetCompletedCount() == objectives.Count) { Debug.Log("All objectives completed!"); OnAllObjectivesComplete(); } } private void OnAllObjectivesComplete() { // Add logic for what happens when all objectives are complete // e.g., show completion UI, unlock exit, etc. } // Called by objects AFTER their OnInteract() is triggered public void RequestReview(GameObject reviewObject) { // Check if already reviewed if (checkedObjects.Contains(reviewObject)) { Debug.Log($"{reviewObject.name} has already been checked!"); return; } currentReviewObject = reviewObject; Debug.Log($"RequestReview: {reviewObject.name} has tag '{reviewObject.tag}'"); // Invoke event for UI to show prompt if (OnRequestReview != null) { OnRequestReview.Invoke(reviewObject, HandleReviewResponse); } else { Debug.LogError("LevelManager: OnRequestReview event has NO subscribers! UI will not show."); } } // For testing - reset checked objects [ContextMenu("Reset All Checked Objects")] public void ResetCheckedObjects() { checkedObjects.Clear(); foreach (var objective in objectives) { objective.checkedItems = 0; objective.brokenItems = 0; objective.isCompleted = false; } Debug.Log("All checked objects and progress reset!"); } private void HandleReviewResponse(bool isBroken) { if (currentReviewObject == null) return; // Mark as checked checkedObjects.Add(currentReviewObject); // Determine which objective this belongs to string objectiveKey = GetObjectiveKeyFromTag(currentReviewObject.tag); if (!string.IsNullOrEmpty(objectiveKey) && objectiveDict.ContainsKey(objectiveKey)) { Objective objective = objectiveDict[objectiveKey]; objective.checkedItems++; if (isBroken) { objective.brokenItems++; Debug.Log($"{currentReviewObject.name} marked as BROKEN"); } else { Debug.Log($"{currentReviewObject.name} marked as OK"); } // Check if all items for this objective are checked if (objective.checkedItems >= objective.totalItems && objective.totalItems > 0) { CompleteObjective(objectiveKey); } Debug.Log($"Progress for '{objectiveKey}': {objective.checkedItems}/{objective.totalItems} ({objective.brokenItems} broken)"); } else { Debug.LogWarning($"No objective found for object '{currentReviewObject.name}' with tag '{currentReviewObject.tag}'"); } currentReviewObject = null; } private string GetObjectiveKeyFromTag(string tag) { switch (tag) { case "Door": return "doors"; case "LightSwitch": return "light_switches"; case "Light": return "lights"; case "Toilet": return "toilets"; case "Oven": return "oven"; case "Tap": return "taps"; default: return null; } } }