using UnityEngine; using System.Collections.Generic; using System.Linq; /// /// Manages the Adventurer's Guild - quest board, quest generation, and guild services /// public class AdventurersGuild : MonoBehaviour { [Header("Guild Configuration")] [Tooltip("Maximum number of quests on the board")] public int maxQuestBoardSize = 8; [Tooltip("How often new quests are added (in game hours)")] public float questRefreshRate = 24f; [Header("Available Quests")] [SerializeField] private List availableQuests = new List(); [SerializeField] private List questBoard = new List(); [Header("Guild Services")] [Tooltip("Can abandon quests here")] public bool allowQuestAbandonment = true; [Tooltip("Can view completed quest history")] public bool showQuestHistory = true; [Header("Debug")] public bool enableDebugLogs = false; private float timeSinceLastRefresh = 0f; private void Start() { // Wait a frame to ensure QuestManager is initialized StartCoroutine(InitializeGuild()); } private System.Collections.IEnumerator InitializeGuild() { yield return null; // Wait one frame // Ensure QuestManager exists if (QuestManager.Instance == null) { var questManagerObject = new GameObject("QuestManager"); questManagerObject.AddComponent(); if (enableDebugLogs) Debug.Log("✅ AdventurersGuild created QuestManager instance"); } LoadAvailableQuests(); RefreshQuestBoard(); if (enableDebugLogs) Debug.Log($"🏛️ AdventurersGuild initialized with {availableQuests.Count} available quests"); } private void Update() { // Auto-refresh quest board periodically if (QuestManager.Instance != null) { timeSinceLastRefresh += Time.deltaTime * QuestManager.Instance.gameTimeSpeed; if (timeSinceLastRefresh >= questRefreshRate) { RefreshQuestBoard(); timeSinceLastRefresh = 0f; } } } /// /// Load all available quests from Resources folder /// private void LoadAvailableQuests() { availableQuests.Clear(); LogDebug("🔍 Starting quest loading process..."); // First, try to load quests from specific subfolders var combatQuests = Resources.LoadAll("Quests/Combat"); var rescueQuests = Resources.LoadAll("Quests/Rescue"); var retrievalQuests = Resources.LoadAll("Quests/Retrieval"); var explorationQuests = Resources.LoadAll("Quests/Exploration"); LogDebug($"📁 Found quests in subfolders: Combat={combatQuests.Length}, Rescue={rescueQuests.Length}, Retrieval={retrievalQuests.Length}, Exploration={explorationQuests.Length}"); availableQuests.AddRange(combatQuests); availableQuests.AddRange(rescueQuests); availableQuests.AddRange(retrievalQuests); availableQuests.AddRange(explorationQuests); // Also load any quests directly in the Quests folder var allQuests = Resources.LoadAll("Quests"); LogDebug($"📁 Found {allQuests.Length} quests in main Quests folder"); foreach (var quest in allQuests) { if (quest != null) { LogDebug($" - Found quest: {quest.name} ({quest.questTitle})"); if (!availableQuests.Contains(quest)) { availableQuests.Add(quest); LogDebug($" ✅ Added to available quests"); } else { LogDebug($" ⚠️ Already in list, skipping"); } } else { LogDebug($" - ❌ Found NULL quest in Resources/Quests"); } } // Finally, load any quests from the root Resources folder var rootQuests = Resources.LoadAll(""); foreach (var quest in rootQuests) { if (!availableQuests.Contains(quest)) { availableQuests.Add(quest); } } LogDebug($"📚 Loaded {availableQuests.Count} available quests"); // If no quests found, create some default ones if (availableQuests.Count == 0) { LogDebug("⚠️ No quests found in Resources. Creating default quests..."); CreateDefaultQuests(); } if (enableDebugLogs && availableQuests.Count > 0) { Debug.Log("📋 Available quests:"); foreach (var quest in availableQuests) { Debug.Log($" - {quest.questTitle} ({quest.name})"); } } } /// /// Create default quests if none are found in Resources /// private void CreateDefaultQuests() { LogDebug("Creating default starter quests..."); var starterQuest = ScriptableObject.CreateInstance(); starterQuest.questTitle = "Goblin Trouble"; starterQuest.questDescription = "Goblins have been spotted near the village outskirts. Deal with them before they cause real trouble."; starterQuest.questType = QuestType.Combat; starterQuest.difficulty = QuestDifficulty.Easy; starterQuest.timeLimitDays = 7; starterQuest.targetAreaName = "Village Outskirts"; starterQuest.targetMapPosition = new Vector2Int(45, 55); starterQuest.goldReward = 50; starterQuest.renownReward = 5; starterQuest.minimumRenown = 0; // Available to all players starterQuest.goals.Add(new QuestGoal { description = "Defeat 3 Goblins", goalType = QuestGoalType.KillEnemies, targetName = "Goblin", targetCount = 3 }); availableQuests.Add(starterQuest); var deliveryQuest = ScriptableObject.CreateInstance(); deliveryQuest.questTitle = "Message Delivery"; deliveryQuest.questDescription = "The village elder needs an important message delivered to the neighboring settlement."; deliveryQuest.questType = QuestType.Delivery; deliveryQuest.difficulty = QuestDifficulty.Easy; deliveryQuest.timeLimitDays = 5; deliveryQuest.targetAreaName = "Nearby Settlement"; deliveryQuest.targetMapPosition = new Vector2Int(60, 40); deliveryQuest.goldReward = 40; deliveryQuest.renownReward = 3; deliveryQuest.minimumRenown = 0; deliveryQuest.goals.Add(new QuestGoal { description = "Deliver message to Settlement Leader", goalType = QuestGoalType.ReachLocation, targetName = "Settlement", targetCount = 1 }); availableQuests.Add(deliveryQuest); LogDebug($"✅ Created {availableQuests.Count} default quests"); } /// /// Refresh the quest board with new available quests /// public void RefreshQuestBoard() { questBoard.Clear(); if (availableQuests.Count == 0) { LogDebug("⚠️ No available quests to populate quest board"); return; } // Filter quests based on current renown and prerequisites var eligibleQuests = availableQuests.Where(q => IsQuestEligible(q)).ToList(); // Randomly select quests for the board var questsToAdd = Mathf.Min(maxQuestBoardSize, eligibleQuests.Count); var selectedQuests = eligibleQuests.OrderBy(x => Random.value).Take(questsToAdd); questBoard.AddRange(selectedQuests); LogDebug($"🗂️ Quest board refreshed: {questBoard.Count} quests available"); } /// /// Check if a quest is eligible for the current party /// private bool IsQuestEligible(Quest quest) { if (quest == null) return false; var questManager = QuestManager.Instance; if (questManager == null) return false; // Check renown requirement if (questManager.GetRenown() < quest.minimumRenown) return false; // Check if already have this quest active var activeQuests = questManager.GetActiveQuests(); if (activeQuests.Any(aq => aq.questData == quest)) return false; // Check prerequisites (simplified - just check if we've completed them) // In a full implementation, you'd check the QuestManager's completed quests return true; } /// /// Accept a quest from the guild board /// public bool AcceptQuest(Quest quest) { if (quest == null || !questBoard.Contains(quest)) { LogDebug("❌ Cannot accept quest: not available on board"); return false; } var questManager = QuestManager.Instance; if (questManager == null) { LogDebug("❌ QuestManager not found"); return false; } if (!questManager.CanAcceptMoreQuests()) { LogDebug("❌ Cannot accept more quests"); return false; } bool accepted = questManager.AcceptQuest(quest); if (accepted) { // Remove from board (could be optional - some quests might be repeatable) questBoard.Remove(quest); LogDebug($"✅ Accepted quest from guild: {quest.questTitle}"); } return accepted; } /// /// Get all quests currently on the board /// public List GetQuestBoard() => new List(questBoard); /// /// Generate a random quest based on current area/difficulty /// public Quest GenerateRandomQuest(Vector2Int nearPosition, QuestDifficulty targetDifficulty = QuestDifficulty.Normal) { // This would be used for dynamic quest generation // For now, just return a random quest from available ones var eligibleQuests = availableQuests.Where(q => q.difficulty == targetDifficulty && IsQuestEligible(q)).ToList(); if (eligibleQuests.Count == 0) return null; var randomQuest = eligibleQuests[Random.Range(0, eligibleQuests.Count)]; // Modify the quest position to be near the requested position var questCopy = Object.Instantiate(randomQuest); questCopy.targetMapPosition = nearPosition + new Vector2Int( Random.Range(-10, 11), Random.Range(-10, 11)); return questCopy; } /// /// Get quest recommendations based on party strength/renown /// public List GetRecommendedQuests(int count = 3) { var questManager = QuestManager.Instance; if (questManager == null) return new List(); int renown = questManager.GetRenown(); // Recommend quests slightly above and below current renown level var recommended = questBoard.Where(q => q.minimumRenown <= renown + 10 && q.minimumRenown >= renown - 5) .OrderBy(q => Mathf.Abs(q.minimumRenown - renown)) .Take(count) .ToList(); return recommended; } /// /// Calculate travel time to quest location from current position /// public float CalculateTravelTimeToQuest(Quest quest, Vector2Int currentPosition) { if (quest == null) return 0f; return quest.CalculateTravelTime(currentPosition); } private void LogDebug(string message) { if (enableDebugLogs) { Debug.Log($"[AdventurersGuild] {message}"); } } #region Context Menu Debug Methods [ContextMenu("Refresh Quest Board")] private void DebugRefreshQuestBoard() { RefreshQuestBoard(); } [ContextMenu("List Available Quests")] private void DebugListAvailableQuests() { LogDebug($"Available Quests ({availableQuests.Count}):"); foreach (var quest in availableQuests) { LogDebug($" - {quest.questTitle} (Difficulty: {quest.difficulty}, Renown: {quest.minimumRenown})"); } } [ContextMenu("List Quest Board")] private void DebugListQuestBoard() { LogDebug($"Quest Board ({questBoard.Count}):"); foreach (var quest in questBoard) { LogDebug($" - {quest.questTitle} (Reward: {quest.goldReward}g, Time: {quest.timeLimitDays}d)"); } } [ContextMenu("Force Load Quests")] private void DebugForceLoadQuests() { LoadAvailableQuests(); LogDebug($"Forced quest loading complete. Found {availableQuests.Count} quests."); } [ContextMenu("Check Quest Eligibility")] private void DebugCheckQuestEligibility() { LogDebug("Checking quest eligibility..."); LogDebug($"Current Renown: {QuestManager.Instance?.GetRenown() ?? -1}"); foreach (var quest in availableQuests) { bool eligible = IsQuestEligible(quest); LogDebug($" - {quest.questTitle}: {(eligible ? "✅ ELIGIBLE" : "❌ NOT ELIGIBLE")} (Min Renown: {quest.minimumRenown})"); } } [ContextMenu("Create Simple Test Quest")] private void DebugCreateSimpleQuest() { var simpleQuest = ScriptableObject.CreateInstance(); simpleQuest.questTitle = "Simple Test Quest"; simpleQuest.questDescription = "A basic quest for testing the quest board display."; simpleQuest.questType = QuestType.Combat; simpleQuest.difficulty = QuestDifficulty.Easy; simpleQuest.timeLimitDays = 7; simpleQuest.targetAreaName = "Nearby Forest"; simpleQuest.targetMapPosition = new Vector2Int(50, 50); simpleQuest.goldReward = 50; simpleQuest.renownReward = 5; simpleQuest.minimumRenown = 0; // No requirements simpleQuest.goals.Add(new QuestGoal { description = "Defeat 3 Goblins", goalType = QuestGoalType.KillEnemies, targetName = "Goblin", targetCount = 3 }); // Add directly to available quests and quest board availableQuests.Add(simpleQuest); questBoard.Add(simpleQuest); LogDebug($"✅ Created and added simple test quest: {simpleQuest.questTitle}"); LogDebug($"Quest Board now has {questBoard.Count} quests"); } [ContextMenu("Force Reload Available Quests")] private void DebugReloadQuests() { LogDebug("🔄 Manually reloading available quests..."); LoadAvailableQuests(); RefreshQuestBoard(); } [ContextMenu("List Resources/Quests Contents")] private void DebugListQuestResources() { LogDebug("🔍 Checking Resources/Quests folder contents..."); var allQuests = Resources.LoadAll("Quests"); LogDebug($"Resources.LoadAll(\"Quests\") returned {allQuests.Length} items"); for (int i = 0; i < allQuests.Length; i++) { var quest = allQuests[i]; if (quest != null) { LogDebug($" {i}: {quest.name} - Title: '{quest.questTitle}' - Type: {quest.questType}"); } else { LogDebug($" {i}: NULL quest object"); } } // Also check with UnityEngine.Object var allObjects = Resources.LoadAll("Quests"); LogDebug($"Resources.LoadAll(\"Quests\") returned {allObjects.Length} objects of any type"); for (int i = 0; i < allObjects.Length; i++) { var obj = allObjects[i]; if (obj != null) { LogDebug($" {i}: {obj.name} - Type: {obj.GetType().Name}"); } else { LogDebug($" {i}: NULL object"); } } } [ContextMenu("Check Quest Board Eligibility")] private void DebugCheckQuestBoardEligibility() { LogDebug("🔍 Checking quest eligibility for quest board..."); LogDebug($"Current Renown: {QuestManager.Instance?.GetRenown() ?? -1}"); LogDebug($"Available Quests: {availableQuests.Count}"); foreach (var quest in availableQuests) { if (quest != null) { bool eligible = IsQuestEligible(quest); LogDebug($" - {quest.questTitle}:"); LogDebug($" Min Renown Required: {quest.minimumRenown}"); LogDebug($" Quest Type: {quest.questType}"); LogDebug($" Difficulty: {quest.difficulty}"); LogDebug($" Eligible: {(eligible ? "✅ YES" : "❌ NO")}"); if (!eligible && QuestManager.Instance != null) { // Check specific reasons if (QuestManager.Instance.GetRenown() < quest.minimumRenown) { LogDebug($" ❌ Reason: Not enough renown ({QuestManager.Instance.GetRenown()} < {quest.minimumRenown})"); } // Check if quest is already active var activeQuests = QuestManager.Instance.GetActiveQuests(); bool alreadyActive = activeQuests.Any(aq => aq.questData.name == quest.name); if (alreadyActive) { LogDebug($" ❌ Reason: Quest already active"); } } } } } #endregion }