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
}