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 any, index ...int) SetArrayLengthByName(name string, length int) SetArrayDataByName(name string, value any, index int) SetSubArrayLengthByName(name string, length int, index int) SetSubArrayDataByName(name string, value any, index1, index2 int) SetSubstructArrayDataByName(substruct, name string, value any, 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 ...any) LogError(message string, args ...any) LogDebug(message string, args ...any) LogWarning(message string, args ...any) } // 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.Repeatable { 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 }