| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Linq;
- /// <summary>
- /// Manages quest markers on the map - shows quest locations and handles completion detection
- /// </summary>
- 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<string, QuestMarker> activeQuestMarkers = new Dictionary<string, QuestMarker>();
- 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<MapVisualizer>();
- 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<MapVisualizer>();
- 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<QuestReward> 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<QuestMarker>();
- if (questMarker == null)
- {
- questMarker = markerObject.AddComponent<QuestMarker>();
- }
- 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<Renderer>();
- if (renderer != null)
- {
- renderer.material.color = Color.yellow;
- }
- // Remove collider to avoid interference
- var collider = marker.GetComponent<Collider>();
- 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<Renderer>();
- 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<Collider>();
- if (collider != null)
- {
- DestroyImmediate(collider);
- }
- return area;
- }
- /// <summary>
- /// Get all active quest markers
- /// </summary>
- public List<QuestMarker> GetActiveMarkers()
- {
- return activeQuestMarkers.Values.Where(m => m != null).ToList();
- }
- /// <summary>
- /// Get quest marker by quest ID
- /// </summary>
- public QuestMarker GetMarkerByQuestId(string questId)
- {
- activeQuestMarkers.TryGetValue(questId, out QuestMarker marker);
- return marker;
- }
- /// <summary>
- /// Refresh all quest markers (useful when loading a saved game)
- /// </summary>
- 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}");
- }
- }
- /// <summary>
- /// Focus the camera on a specific quest's marker
- /// </summary>
- 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<CameraController>();
- 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}");
- }
- }
- }
- }
- /// <summary>
- /// Get the world position of a quest marker
- /// </summary>
- 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
- }
|