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
}