| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515 |
- using UnityEngine;
- using System.Collections.Generic;
- using System.Linq;
- /// <summary>
- /// Manages the Adventurer's Guild - quest board, quest generation, and guild services
- /// </summary>
- 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<Quest> availableQuests = new List<Quest>();
- [SerializeField] private List<Quest> questBoard = new List<Quest>();
- [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<QuestManager>();
- 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;
- }
- }
- }
- /// <summary>
- /// Load all available quests from Resources folder
- /// </summary>
- private void LoadAvailableQuests()
- {
- availableQuests.Clear();
- LogDebug("🔍 Starting quest loading process...");
- // First, try to load quests from specific subfolders
- var combatQuests = Resources.LoadAll<Quest>("Quests/Combat");
- var rescueQuests = Resources.LoadAll<Quest>("Quests/Rescue");
- var retrievalQuests = Resources.LoadAll<Quest>("Quests/Retrieval");
- var explorationQuests = Resources.LoadAll<Quest>("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<Quest>("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<Quest>("");
- 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})");
- }
- }
- }
- /// <summary>
- /// Create default quests if none are found in Resources
- /// </summary>
- private void CreateDefaultQuests()
- {
- LogDebug("Creating default starter quests...");
- var starterQuest = ScriptableObject.CreateInstance<Quest>();
- 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<Quest>();
- 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");
- }
- /// <summary>
- /// Refresh the quest board with new available quests
- /// </summary>
- 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");
- }
- /// <summary>
- /// Check if a quest is eligible for the current party
- /// </summary>
- 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;
- }
- /// <summary>
- /// Accept a quest from the guild board
- /// </summary>
- 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;
- }
- /// <summary>
- /// Get all quests currently on the board
- /// </summary>
- public List<Quest> GetQuestBoard() => new List<Quest>(questBoard);
- /// <summary>
- /// Generate a random quest based on current area/difficulty
- /// </summary>
- 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;
- }
- /// <summary>
- /// Get quest recommendations based on party strength/renown
- /// </summary>
- public List<Quest> GetRecommendedQuests(int count = 3)
- {
- var questManager = QuestManager.Instance;
- if (questManager == null) return new List<Quest>();
- 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;
- }
- /// <summary>
- /// Calculate travel time to quest location from current position
- /// </summary>
- 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<Quest>();
- 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<Quest>("Quests");
- LogDebug($"Resources.LoadAll<Quest>(\"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
- }
|