package quests import "fmt" // Player interface defines the required player functionality for quest system type Player interface { // Basic player information GetID() int32 GetName() string GetLevel() int8 GetTSLevel() int8 GetClass() int8 GetTSClass() int8 GetRace() int8 // Client interface for packet sending GetClient() Client // Quest-related player methods GetQuest(questID int32) *Quest HasQuest(questID int32) bool HasQuestBeenCompleted(questID int32) bool AddQuest(quest *Quest) error RemoveQuest(questID int32) bool // Position and zone information GetX() float32 GetY() float32 GetZ() float32 GetZoneID() int32 // Faction information GetFactionValue(factionID int32) int32 // Experience and rewards AddCoins(amount int64) AddExp(amount int32) AddTSExp(amount int32) AddStatusPoints(amount int32) // Inventory management GetPlayerItemList() ItemList // Arrow color calculation (difficulty indication) GetArrowColor(level int8) int8 GetTSArrowColor(level int8) int8 } // Client interface defines client functionality needed for quest system type Client interface { // Basic client information GetVersion() int16 GetNameCRC() int32 GetPlayer() Player // Packet sending QueuePacket(packet Packet) SimpleMessage(color int32, message string) // Quest-specific client methods SendQuestJournalUpdate(quest *Quest, forceUpdate bool) PopulateQuestRewardItems(items *[]Item, packet PacketStruct, arrayName ...string) } // Spawn interface defines spawn functionality needed for quest system type Spawn interface { // Basic spawn information GetID() int32 GetDatabaseID() int32 GetName() string GetRace() int8 GetModelType() int16 // Position information GetX() float32 GetY() float32 GetZ() float32 GetZoneID() int32 } // Spell interface defines spell functionality needed for quest system type Spell interface { GetSpellID() int32 GetName() string } // Item interface defines item functionality needed for quest system type Item interface { GetItemID() int32 GetName() string GetIcon(version int16) int32 GetDetails() ItemDetails GetStackCount() int32 } // ItemDetails interface defines item detail functionality type ItemDetails interface { GetItemID() int32 GetUniqueID() int32 GetCount() int32 } // ItemList interface defines item list functionality type ItemList interface { GetItemFromID(itemID int32, count int32) Item } // Packet interface defines packet functionality type Packet interface { // Packet data methods (placeholder) Serialize() []byte } // PacketStruct interface defines packet structure functionality type PacketStruct interface { // Packet building methods SetDataByName(name string, value interface{}, index ...int) SetArrayLengthByName(name string, length int) SetArrayDataByName(name string, value interface{}, index int) SetSubArrayLengthByName(name string, length int, index int) SetSubArrayDataByName(name string, value interface{}, index1, index2 int) SetSubstructArrayDataByName(substruct, name string, value interface{}, index int) SetItemArrayDataByName(name string, item Item, player Player, index int, flag ...int) Serialize() Packet GetVersion() int16 } // QuestOfferer interface defines NPCs that can offer quests type QuestOfferer interface { Spawn GetOfferedQuests() []int32 CanOfferQuest(questID int32, player Player) bool OfferQuest(questID int32, player Player) error } // QuestReceiver interface defines NPCs that can receive completed quests type QuestReceiver interface { Spawn GetAcceptedQuests() []int32 CanAcceptQuest(questID int32, player Player) bool AcceptCompletedQuest(questID int32, player Player) error } // QuestValidator interface defines quest validation functionality type QuestValidator interface { ValidatePrerequisites(quest *Quest, player Player) error ValidateQuestCompletion(quest *Quest, player Player) error ValidateQuestSharing(quest *Quest, sharer, receiver Player) error } // QuestRewardProcessor interface defines quest reward processing type QuestRewardProcessor interface { ProcessQuestRewards(quest *Quest, player Player) error CalculateRewards(quest *Quest, player Player) *QuestRewards GiveRewards(rewards *QuestRewards, player Player) error } // QuestRewards contains calculated quest rewards type QuestRewards struct { Coins int64 `json:"coins"` Experience int32 `json:"experience"` TSExperience int32 `json:"ts_experience"` StatusPoints int32 `json:"status_points"` Items []Item `json:"items"` FactionRewards map[int32]int32 `json:"faction_rewards"` } // QuestEventHandler interface defines quest event handling type QuestEventHandler interface { OnQuestStarted(quest *Quest, player Player) OnQuestStepCompleted(quest *Quest, step *QuestStep, player Player) OnQuestCompleted(quest *Quest, player Player) OnQuestFailed(quest *Quest, step *QuestStep, player Player) OnQuestAbandoned(quest *Quest, player Player) OnQuestShared(quest *Quest, sharer, receiver Player) } // Database interface defines database operations for quest system type Database interface { // Quest CRUD operations LoadQuest(questID int32) (*Quest, error) SaveQuest(quest *Quest) error DeleteQuest(questID int32) error LoadAllQuests() ([]*Quest, error) // Player quest operations LoadPlayerQuests(playerID int32) ([]*Quest, error) SavePlayerQuest(playerID int32, quest *Quest) error DeletePlayerQuest(playerID, questID int32) error MarkQuestCompleted(playerID, questID int32) error IsQuestCompleted(playerID, questID int32) bool // Quest step operations SaveQuestStepProgress(playerID, questID, stepID int32, progress int32) error LoadQuestStepProgress(playerID, questID, stepID int32) (int32, error) } // Logger interface defines logging functionality for quest system type Logger interface { LogInfo(message string, args ...interface{}) LogError(message string, args ...interface{}) LogDebug(message string, args ...interface{}) LogWarning(message string, args ...interface{}) } // Configuration interface defines quest system configuration type Configuration interface { GetMaxPlayerQuests() int GetQuestSharingEnabled() bool GetQuestFailureEnabled() bool GetQuestTimersEnabled() bool GetXPBonusMultiplier() float64 GetCoinBonusMultiplier() float64 GetStatusBonusMultiplier() float64 } // QuestSystemAdapter provides integration with other game systems type QuestSystemAdapter struct { questManager *QuestManager validator QuestValidator rewardProcessor QuestRewardProcessor eventHandler QuestEventHandler database Database logger Logger config Configuration } // NewQuestSystemAdapter creates a new quest system adapter func NewQuestSystemAdapter(questManager *QuestManager, validator QuestValidator, rewardProcessor QuestRewardProcessor, eventHandler QuestEventHandler, database Database, logger Logger, config Configuration) *QuestSystemAdapter { return &QuestSystemAdapter{ questManager: questManager, validator: validator, rewardProcessor: rewardProcessor, eventHandler: eventHandler, database: database, logger: logger, config: config, } } // StartQuest handles starting a new quest for a player func (qsa *QuestSystemAdapter) StartQuest(questID int32, player Player) error { // Get quest from master list quest := qsa.questManager.GetMasterList().GetQuest(questID, true) if quest == nil { return fmt.Errorf("quest %d not found", questID) } // Validate prerequisites if qsa.validator != nil { if err := qsa.validator.ValidatePrerequisites(quest, player); err != nil { return fmt.Errorf("quest prerequisites not met: %w", err) } } // Check if player can accept more quests if qsa.config != nil { maxQuests := qsa.config.GetMaxPlayerQuests() if maxQuests > 0 && qsa.questManager.GetPlayerQuestCount(player.GetID()) >= maxQuests { return fmt.Errorf("player has too many active quests") } } // Give quest to player _, err := qsa.questManager.GiveQuestToPlayer(player.GetID(), questID) if err != nil { return err } // Save to database if qsa.database != nil { if err := qsa.database.SavePlayerQuest(player.GetID(), quest); err != nil { qsa.logger.LogError("Failed to save player quest to database: %v", err) } } // Trigger event if qsa.eventHandler != nil { qsa.eventHandler.OnQuestStarted(quest, player) } // Log if qsa.logger != nil { qsa.logger.LogInfo("Player %s (%d) started quest %s (%d)", player.GetName(), player.GetID(), quest.Name, questID) } return nil } // CompleteQuest handles completing a quest for a player func (qsa *QuestSystemAdapter) CompleteQuest(questID int32, player Player) error { // Get player's quest quest := qsa.questManager.GetPlayerQuest(player.GetID(), questID) if quest == nil { return fmt.Errorf("player does not have quest %d", questID) } // Validate completion if qsa.validator != nil { if err := qsa.validator.ValidateQuestCompletion(quest, player); err != nil { return fmt.Errorf("quest completion validation failed: %w", err) } } // Check if quest is actually complete if !quest.GetCompleted() { return fmt.Errorf("quest is not complete") } // Process rewards if qsa.rewardProcessor != nil { if err := qsa.rewardProcessor.ProcessQuestRewards(quest, player); err != nil { qsa.logger.LogError("Failed to process quest rewards: %v", err) return fmt.Errorf("failed to process quest rewards: %w", err) } } // Mark as completed in database if qsa.database != nil { if err := qsa.database.MarkQuestCompleted(player.GetID(), questID); err != nil { qsa.logger.LogError("Failed to mark quest as completed in database: %v", err) } } // Remove from active quests if not repeatable if !quest.IsRepeatable() { qsa.questManager.RemoveQuestFromPlayer(player.GetID(), questID) } // Trigger event if qsa.eventHandler != nil { qsa.eventHandler.OnQuestCompleted(quest, player) } // Log if qsa.logger != nil { qsa.logger.LogInfo("Player %s (%d) completed quest %s (%d)", player.GetName(), player.GetID(), quest.Name, questID) } return nil } // UpdateQuestProgress handles updating quest step progress func (qsa *QuestSystemAdapter) UpdateQuestProgress(questID, stepID, progress int32, player Player) error { // Get player's quest quest := qsa.questManager.GetPlayerQuest(player.GetID(), questID) if quest == nil { return fmt.Errorf("player does not have quest %d", questID) } // Update progress if !quest.AddStepProgress(stepID, progress) { return fmt.Errorf("failed to update quest step progress") } // Check if step is now complete step := quest.GetQuestStep(stepID) if step != nil && step.Complete() { // Execute complete action if exists if quest.HasCompleteAction(stepID) { if err := quest.ExecuteCompleteAction(stepID); err != nil { qsa.logger.LogError("Failed to execute quest step complete action: %v", err) } } // Trigger event if qsa.eventHandler != nil { qsa.eventHandler.OnQuestStepCompleted(quest, step, player) } // Log if qsa.logger != nil { qsa.logger.LogInfo("Player %s (%d) completed step %d of quest %s (%d)", player.GetName(), player.GetID(), stepID, quest.Name, questID) } } // Save progress to database if qsa.database != nil { if err := qsa.database.SaveQuestStepProgress(player.GetID(), questID, stepID, step.GetStepProgress()); err != nil { qsa.logger.LogError("Failed to save quest step progress to database: %v", err) } } return nil } // AbandonQuest handles abandoning a quest func (qsa *QuestSystemAdapter) AbandonQuest(questID int32, player Player) error { // Get player's quest quest := qsa.questManager.GetPlayerQuest(player.GetID(), questID) if quest == nil { return fmt.Errorf("player does not have quest %d", questID) } // Check if quest can be abandoned if !quest.CanDeleteQuest { return fmt.Errorf("quest cannot be abandoned") } // Remove from player if !qsa.questManager.RemoveQuestFromPlayer(player.GetID(), questID) { return fmt.Errorf("failed to remove quest from player") } // Remove from database if qsa.database != nil { if err := qsa.database.DeletePlayerQuest(player.GetID(), questID); err != nil { qsa.logger.LogError("Failed to delete player quest from database: %v", err) } } // Trigger event if qsa.eventHandler != nil { qsa.eventHandler.OnQuestAbandoned(quest, player) } // Log if qsa.logger != nil { qsa.logger.LogInfo("Player %s (%d) abandoned quest %s (%d)", player.GetName(), player.GetID(), quest.Name, questID) } return nil } // ShareQuest handles sharing a quest between players func (qsa *QuestSystemAdapter) ShareQuest(questID int32, sharer, receiver Player) error { if !qsa.config.GetQuestSharingEnabled() { return fmt.Errorf("quest sharing is disabled") } // Get sharer's quest quest := qsa.questManager.GetPlayerQuest(sharer.GetID(), questID) if quest == nil { return fmt.Errorf("sharer does not have quest %d", questID) } // Validate sharing if qsa.validator != nil { if err := qsa.validator.ValidateQuestSharing(quest, sharer, receiver); err != nil { return fmt.Errorf("quest sharing validation failed: %w", err) } } // Check if receiver can accept more quests if qsa.config != nil { maxQuests := qsa.config.GetMaxPlayerQuests() if maxQuests > 0 && qsa.questManager.GetPlayerQuestCount(receiver.GetID()) >= maxQuests { return fmt.Errorf("receiver has too many active quests") } } // Give quest to receiver _, err := qsa.questManager.GiveQuestToPlayer(receiver.GetID(), questID) if err != nil { return fmt.Errorf("failed to give quest to receiver: %w", err) } // Save to database if qsa.database != nil { receiverQuest := qsa.questManager.GetPlayerQuest(receiver.GetID(), questID) if err := qsa.database.SavePlayerQuest(receiver.GetID(), receiverQuest); err != nil { qsa.logger.LogError("Failed to save shared quest to database: %v", err) } } // Trigger event if qsa.eventHandler != nil { qsa.eventHandler.OnQuestShared(quest, sharer, receiver) } // Log if qsa.logger != nil { qsa.logger.LogInfo("Player %s (%d) shared quest %s (%d) with %s (%d)", sharer.GetName(), sharer.GetID(), quest.Name, questID, receiver.GetName(), receiver.GetID()) } return nil }