using UnityEngine; using System.Collections.Generic; using System.Linq; /// /// Manages quest markers on the map - shows quest locations and handles completion detection /// public class QuestMapMarkerManager : MonoBehaviour { [Header("Marker Prefabs")] [Tooltip("Prefab for quest objective markers")] public GameObject questMarkerPrefab; [Tooltip("Prefab for quest completion areas")] public GameObject questAreaPrefab; [Header("Marker Settings")] [Tooltip("Scale factor for quest markers")] public float markerScale = 0.5f; [Tooltip("How often to check for quest completion (seconds)")] public float completionCheckInterval = 1f; [Header("Marker Colors")] public Color easyQuestColor = Color.green; public Color normalQuestColor = Color.yellow; public Color hardQuestColor = Color.red; public Color legendaryQuestColor = Color.magenta; public Color completedQuestColor = Color.gray; [Header("Debug")] public bool enableDebugLogs = true; private Dictionary activeQuestMarkers = new Dictionary(); private Transform teamMarker; private float lastCompletionCheck = 0f; private void Start() { InitializeMarkerManager(); // Subscribe to quest events if (QuestManager.Instance != null) { QuestManager.Instance.OnQuestAccepted += OnQuestAccepted; QuestManager.Instance.OnQuestCompleted += OnQuestCompleted; QuestManager.Instance.OnQuestFailed += OnQuestFailed; QuestManager.Instance.OnQuestAbandoned += OnQuestAbandoned; // Create markers for any existing active quests StartCoroutine(CreateMarkersForExistingQuests()); } } private System.Collections.IEnumerator CreateMarkersForExistingQuests() { // Wait a frame to ensure all systems are initialized yield return null; RefreshAllMarkers(); LogDebug("Created markers for existing active quests"); } private void Update() { CheckQuestCompletion(); } private void OnDestroy() { // Unsubscribe from quest events if (QuestManager.Instance != null) { QuestManager.Instance.OnQuestAccepted -= OnQuestAccepted; QuestManager.Instance.OnQuestCompleted -= OnQuestCompleted; QuestManager.Instance.OnQuestFailed -= OnQuestFailed; QuestManager.Instance.OnQuestAbandoned -= OnQuestAbandoned; } } private void InitializeMarkerManager() { // Find team marker var teamMarkerObject = GameObject.Find("TeamMarker"); if (teamMarkerObject != null) { teamMarker = teamMarkerObject.transform; LogDebug("Found TeamMarker"); } else { LogDebug("⚠️ TeamMarker not found"); } // Create default marker prefabs if none assigned if (questMarkerPrefab == null) { questMarkerPrefab = CreateDefaultMarkerPrefab(); } if (questAreaPrefab == null) { questAreaPrefab = CreateDefaultAreaPrefab(); } LogDebug("QuestMapMarkerManager initialized"); } private void CheckQuestCompletion() { if (Time.time < lastCompletionCheck + completionCheckInterval) return; if (teamMarker == null || QuestManager.Instance == null) return; lastCompletionCheck = Time.time; // Get current team position in map coordinates Vector2Int teamPosition = WorldToMapCoordinates(teamMarker.position); // Check if any quests can be completed at current position var completedQuests = QuestManager.Instance.TryCompleteQuestsAtPosition(teamPosition); if (completedQuests.Count > 0) { LogDebug($"Completed {completedQuests.Count} quests at position {teamPosition}"); } } private Vector2Int WorldToMapCoordinates(Vector3 worldPosition) { // Convert world position to map tile coordinates // This should match the conversion used in other map systems float tileSize = 1f; var mapVisualizer = FindFirstObjectByType(); if (mapVisualizer != null && mapVisualizer.tileSize > 0) { tileSize = mapVisualizer.tileSize; } return new Vector2Int( Mathf.RoundToInt(worldPosition.x / tileSize), Mathf.RoundToInt(worldPosition.z / tileSize) // Use Z for 3D maps ); } private Vector3 MapToWorldCoordinates(Vector2Int mapPosition) { // Convert map tile coordinates to world position float tileSize = 1f; var mapVisualizer = FindFirstObjectByType(); if (mapVisualizer != null && mapVisualizer.tileSize > 0) { tileSize = mapVisualizer.tileSize; } return new Vector3( mapPosition.x * tileSize, 0f, mapPosition.y * tileSize ); } private void OnQuestAccepted(ActiveQuest quest) { CreateQuestMarker(quest); } private void OnQuestCompleted(ActiveQuest quest, List rewards) { RemoveQuestMarker(quest.questId); } private void OnQuestFailed(ActiveQuest quest) { RemoveQuestMarker(quest.questId); } private void OnQuestAbandoned(ActiveQuest quest) { RemoveQuestMarker(quest.questId); } private void CreateQuestMarker(ActiveQuest quest) { if (quest?.questData == null) return; // Remove existing marker if it exists RemoveQuestMarker(quest.questId); // Convert quest position to world coordinates Vector3 worldPosition = MapToWorldCoordinates(quest.questData.targetMapPosition); // Create marker GameObject GameObject markerObject = Instantiate(questMarkerPrefab, worldPosition, Quaternion.identity); markerObject.name = $"QuestMarker_{quest.questData.questTitle}"; markerObject.transform.localScale = Vector3.one * markerScale; // Create completion area GameObject areaObject = Instantiate(questAreaPrefab, worldPosition, Quaternion.identity); areaObject.name = $"QuestArea_{quest.questData.questTitle}"; areaObject.transform.localScale = Vector3.one * quest.questData.completionRadius; // Set up the quest marker component var questMarker = markerObject.GetComponent(); if (questMarker == null) { questMarker = markerObject.AddComponent(); } questMarker.Initialize(quest, areaObject); // Set marker color based on difficulty SetMarkerColor(questMarker, quest.questData.difficulty); // Store reference activeQuestMarkers[quest.questId] = questMarker; LogDebug($"Created quest marker for '{quest.questData.questTitle}' at {quest.questData.targetMapPosition}"); } private void RemoveQuestMarker(string questId) { if (activeQuestMarkers.TryGetValue(questId, out QuestMarker marker)) { if (marker != null && marker.gameObject != null) { Destroy(marker.gameObject); } activeQuestMarkers.Remove(questId); LogDebug($"Removed quest marker for quest {questId}"); } } private void SetMarkerColor(QuestMarker marker, QuestDifficulty difficulty) { Color color = difficulty switch { QuestDifficulty.Easy => easyQuestColor, QuestDifficulty.Normal => normalQuestColor, QuestDifficulty.Hard => hardQuestColor, QuestDifficulty.Legendary => legendaryQuestColor, _ => normalQuestColor }; marker.SetColor(color); } private GameObject CreateDefaultMarkerPrefab() { // Create a simple cube marker GameObject marker = GameObject.CreatePrimitive(PrimitiveType.Cube); marker.name = "DefaultQuestMarker"; // Make it slightly elevated marker.transform.position = Vector3.up * 0.5f; // Add a distinctive material var renderer = marker.GetComponent(); if (renderer != null) { renderer.material.color = Color.yellow; } // Remove collider to avoid interference var collider = marker.GetComponent(); if (collider != null) { DestroyImmediate(collider); } return marker; } private GameObject CreateDefaultAreaPrefab() { // Create a simple cylinder for the completion area GameObject area = GameObject.CreatePrimitive(PrimitiveType.Cylinder); area.name = "DefaultQuestArea"; // Make it flat and transparent area.transform.localScale = new Vector3(1f, 0.1f, 1f); var renderer = area.GetComponent(); if (renderer != null) { // Make it semi-transparent var material = new Material(Shader.Find("Legacy Shaders/Transparent/Diffuse")); material.color = new Color(1f, 1f, 0f, 0.3f); // Semi-transparent yellow renderer.material = material; } // Remove collider var collider = area.GetComponent(); if (collider != null) { DestroyImmediate(collider); } return area; } /// /// Get all active quest markers /// public List GetActiveMarkers() { return activeQuestMarkers.Values.Where(m => m != null).ToList(); } /// /// Get quest marker by quest ID /// public QuestMarker GetMarkerByQuestId(string questId) { activeQuestMarkers.TryGetValue(questId, out QuestMarker marker); return marker; } /// /// Refresh all quest markers (useful when loading a saved game) /// public void RefreshAllMarkers() { // Clear existing markers foreach (var marker in activeQuestMarkers.Values) { if (marker != null && marker.gameObject != null) { Destroy(marker.gameObject); } } activeQuestMarkers.Clear(); // Recreate markers for all active quests if (QuestManager.Instance != null) { var activeQuests = QuestManager.Instance.GetActiveQuests(); foreach (var quest in activeQuests) { CreateQuestMarker(quest); } } LogDebug("Refreshed all quest markers"); } private void LogDebug(string message) { if (enableDebugLogs) { Debug.Log($"[QuestMapMarkerManager] {message}"); } } /// /// Focus the camera on a specific quest's marker /// public void FocusOnQuest(ActiveQuest quest) { if (quest == null || !activeQuestMarkers.ContainsKey(quest.questId)) { LogDebug($"❌ Cannot focus on quest {quest?.questData?.questTitle} - marker not found"); return; } var marker = activeQuestMarkers[quest.questId]; if (marker != null) { var targetPosition = marker.transform.position; // Try to find a camera controller or similar component var cameraController = FindFirstObjectByType(); if (cameraController != null) { // Assuming the camera controller has a method to focus on position // cameraController.FocusOnPosition(targetPosition); LogDebug($"✅ Focusing camera on quest: {quest.questData.questTitle}"); } else { // Fallback: just move the main camera var mainCamera = Camera.main; if (mainCamera != null) { var cameraPos = mainCamera.transform.position; mainCamera.transform.position = new Vector3(targetPosition.x, targetPosition.y, cameraPos.z); LogDebug($"✅ Moved camera to quest location: {quest.questData.questTitle}"); } } } } /// /// Get the world position of a quest marker /// public Vector3? GetQuestMarkerPosition(ActiveQuest quest) { if (quest == null || !activeQuestMarkers.ContainsKey(quest.questId)) return null; var marker = activeQuestMarkers[quest.questId]; return marker?.transform.position; } #region Context Menu Debug Methods [ContextMenu("Refresh All Markers")] private void DebugRefreshAllMarkers() { RefreshAllMarkers(); } [ContextMenu("List Active Markers")] private void DebugListActiveMarkers() { LogDebug($"Active Quest Markers ({activeQuestMarkers.Count}):"); foreach (var kvp in activeQuestMarkers) { var marker = kvp.Value; if (marker != null) { LogDebug($" - {marker.ActiveQuest.questData.questTitle} at {marker.transform.position}"); } } } [ContextMenu("Force Create Test Marker")] private void DebugCreateTestMarker() { if (QuestManager.Instance == null) { LogDebug("❌ No QuestManager found!"); return; } var activeQuests = QuestManager.Instance.GetActiveQuests(); if (activeQuests.Count == 0) { LogDebug("❌ No active quests to create markers for!"); return; } foreach (var quest in activeQuests) { CreateQuestMarker(quest); LogDebug($"✅ Created test marker for: {quest.questData.questTitle}"); } } [ContextMenu("Check Quest System Status")] private void DebugQuestSystemStatus() { LogDebug("=== QUEST SYSTEM STATUS ==="); LogDebug($"QuestManager exists: {QuestManager.Instance != null}"); if (QuestManager.Instance != null) { var activeQuests = QuestManager.Instance.GetActiveQuests(); LogDebug($"Active quests: {activeQuests.Count}"); foreach (var quest in activeQuests) { LogDebug($" - {quest.questData.questTitle} → {quest.questData.targetMapPosition}"); } } LogDebug($"Active markers: {activeQuestMarkers.Count}"); LogDebug($"Team marker found: {teamMarker != null}"); LogDebug($"Marker prefabs: Marker={questMarkerPrefab != null}, Area={questAreaPrefab != null}"); } #endregion }