eq2go/internal/world/achievement_events.go
2025-08-07 11:21:56 -05:00

416 lines
12 KiB
Go

package world
import (
"fmt"
)
// AchievementEventType represents different types of achievement events
type AchievementEventType int
const (
// Combat events
EventNPCKill AchievementEventType = iota
EventPlayerKill
EventDeathByNPC
EventDeathByPlayer
EventDamageDealt
EventHealingDone
// Quest events
EventQuestCompleted
EventQuestStep
EventQuestStarted
EventQuestAbandoned
// Skill events
EventSkillIncrease
EventSkillMastery
EventSpellLearned
EventSpellCast
// Item events
EventItemDiscovered
EventItemCrafted
EventItemLooted
EventItemEquipped
EventItemSold
EventItemBought
// Exploration events
EventZoneDiscovered
EventLocationDiscovered
EventPOIDiscovered
// Social events
EventGuildJoin
EventGuildLeave
EventGroupJoin
EventGroupLeave
EventFriendAdded
EventPlayerTell
// Harvesting/Crafting events
EventHarvest
EventRareHarvest
EventCraftingSuccess
EventCraftingFailure
EventRecipeDiscovered
// Level/Experience events
EventLevelGain
EventAAPoint
EventExperienceGain
EventStatusGain
// PvP events
EventPvPKill
EventPvPDeath
EventPvPAssist
EventArenaWin
EventArenaLoss
// Special events
EventHeroicOpportunity
EventRaidBoss
EventInstanceComplete
EventCollectionComplete
)
// AchievementEvent represents a single achievement-related event
type AchievementEvent struct {
Type AchievementEventType
CharacterID int32
Data map[string]any
Timestamp int64
}
// AchievementEventHandler processes achievement events
type AchievementEventHandler struct {
world *World
}
// NewAchievementEventHandler creates a new achievement event handler
func NewAchievementEventHandler(world *World) *AchievementEventHandler {
return &AchievementEventHandler{
world: world,
}
}
// ProcessEvent processes an achievement event and updates progress
func (aeh *AchievementEventHandler) ProcessEvent(event *AchievementEvent) error {
if event == nil {
return fmt.Errorf("event cannot be nil")
}
// Get player's achievement manager
achievementMgr := aeh.world.GetAchievementManager()
if achievementMgr == nil {
return fmt.Errorf("achievement manager not available")
}
// Process different event types
switch event.Type {
case EventNPCKill:
return aeh.handleNPCKill(event, achievementMgr)
case EventQuestCompleted:
return aeh.handleQuestCompleted(event, achievementMgr)
case EventLevelGain:
return aeh.handleLevelGain(event, achievementMgr)
case EventSkillIncrease:
return aeh.handleSkillIncrease(event, achievementMgr)
case EventItemDiscovered:
return aeh.handleItemDiscovered(event, achievementMgr)
case EventZoneDiscovered:
return aeh.handleZoneDiscovered(event, achievementMgr)
case EventHarvest:
return aeh.handleHarvest(event, achievementMgr)
case EventPvPKill:
return aeh.handlePvPKill(event, achievementMgr)
default:
// For unhandled events, try generic processing
return aeh.handleGenericEvent(event, achievementMgr)
}
}
// handleNPCKill processes NPC kill events
func (aeh *AchievementEventHandler) handleNPCKill(event *AchievementEvent, achievementMgr *AchievementManager) error {
npcID, ok := event.Data["npc_id"].(int32)
if !ok {
return fmt.Errorf("npc_id not found in event data")
}
level, ok := event.Data["level"].(int32)
if !ok {
level = 1 // Default level
}
// Update generic kill count achievements
err := achievementMgr.UpdateProgress(event.CharacterID, 1, 1) // Achievement ID 1: "First Blood"
if err != nil {
fmt.Printf("Error updating kill achievement: %v\n", err)
}
// Update level-specific kill achievements
if level >= 10 {
achievementMgr.UpdateProgress(event.CharacterID, 2, 1) // Achievement ID 2: "Veteran Hunter"
}
// Update specific NPC kill achievements (example)
if npcID == 100 { // Boss NPC
achievementMgr.UpdateProgress(event.CharacterID, 10, 1) // Achievement ID 10: "Boss Slayer"
}
return nil
}
// handleQuestCompleted processes quest completion events
func (aeh *AchievementEventHandler) handleQuestCompleted(event *AchievementEvent, achievementMgr *AchievementManager) error {
questID, ok := event.Data["quest_id"].(int32)
if !ok {
return fmt.Errorf("quest_id not found in event data")
}
// Update quest completion achievements
err := achievementMgr.UpdateProgress(event.CharacterID, 20, 1) // Achievement ID 20: "Quest Master"
if err != nil {
fmt.Printf("Error updating quest achievement: %v\n", err)
}
// Update specific quest achievements
if questID == 1000 { // Main story quest
achievementMgr.UpdateProgress(event.CharacterID, 21, 1) // Achievement ID 21: "Hero's Journey"
}
return nil
}
// handleLevelGain processes level gain events
func (aeh *AchievementEventHandler) handleLevelGain(event *AchievementEvent, achievementMgr *AchievementManager) error {
newLevel, ok := event.Data["level"].(int32)
if !ok {
return fmt.Errorf("level not found in event data")
}
// Update level-based achievements
switch newLevel {
case 10:
achievementMgr.UpdateProgress(event.CharacterID, 30, 1) // Achievement ID 30: "Growing Strong"
case 20:
achievementMgr.UpdateProgress(event.CharacterID, 31, 1) // Achievement ID 31: "Seasoned Adventurer"
case 50:
achievementMgr.UpdateProgress(event.CharacterID, 32, 1) // Achievement ID 32: "Veteran"
case 90:
achievementMgr.UpdateProgress(event.CharacterID, 33, 1) // Achievement ID 33: "Master Adventurer"
}
// Update max level achievement
achievementMgr.UpdateProgress(event.CharacterID, 34, uint32(newLevel)) // Achievement ID 34: "Level Up!"
return nil
}
// handleSkillIncrease processes skill increase events
func (aeh *AchievementEventHandler) handleSkillIncrease(event *AchievementEvent, achievementMgr *AchievementManager) error {
skillID, ok := event.Data["skill_id"].(int32)
if !ok {
return fmt.Errorf("skill_id not found in event data")
}
skillLevel, ok := event.Data["skill_level"].(int32)
if !ok {
return fmt.Errorf("skill_level not found in event data")
}
// Update skill mastery achievements based on skill type
switch skillID {
case 1: // Melee skill
if skillLevel >= 300 {
achievementMgr.UpdateProgress(event.CharacterID, 40, 1) // Achievement ID 40: "Weapon Master"
}
case 10: // Magic skill
if skillLevel >= 300 {
achievementMgr.UpdateProgress(event.CharacterID, 41, 1) // Achievement ID 41: "Arcane Scholar"
}
case 20: // Crafting skill
if skillLevel >= 300 {
achievementMgr.UpdateProgress(event.CharacterID, 42, 1) // Achievement ID 42: "Master Craftsman"
}
}
return nil
}
// handleItemDiscovered processes item discovery events
func (aeh *AchievementEventHandler) handleItemDiscovered(event *AchievementEvent, achievementMgr *AchievementManager) error {
itemID, ok := event.Data["item_id"].(int32)
if !ok {
return fmt.Errorf("item_id not found in event data")
}
rarity, ok := event.Data["rarity"].(string)
if !ok {
rarity = "common"
}
// Update item discovery achievements
achievementMgr.UpdateProgress(event.CharacterID, 50, 1) // Achievement ID 50: "Treasure Hunter"
// Update rarity-specific achievements
switch rarity {
case "rare":
achievementMgr.UpdateProgress(event.CharacterID, 51, 1) // Achievement ID 51: "Rare Collector"
case "legendary":
achievementMgr.UpdateProgress(event.CharacterID, 52, 1) // Achievement ID 52: "Legend Seeker"
case "mythical":
achievementMgr.UpdateProgress(event.CharacterID, 53, 1) // Achievement ID 53: "Myth Walker"
}
// Specific item achievements
if itemID == 12345 { // Special artifact
achievementMgr.UpdateProgress(event.CharacterID, 54, 1) // Achievement ID 54: "Ancient Artifact"
}
return nil
}
// handleZoneDiscovered processes zone discovery events
func (aeh *AchievementEventHandler) handleZoneDiscovered(event *AchievementEvent, achievementMgr *AchievementManager) error {
zoneID, ok := event.Data["zone_id"].(int32)
if !ok {
return fmt.Errorf("zone_id not found in event data")
}
// Update exploration achievements
achievementMgr.UpdateProgress(event.CharacterID, 60, 1) // Achievement ID 60: "Explorer"
// Update specific zone achievements
switch zoneID {
case 1: // Starting zone
achievementMgr.UpdateProgress(event.CharacterID, 61, 1) // Achievement ID 61: "First Steps"
case 100: // End game zone
achievementMgr.UpdateProgress(event.CharacterID, 62, 1) // Achievement ID 62: "Into the Unknown"
}
return nil
}
// handleHarvest processes harvesting events
func (aeh *AchievementEventHandler) handleHarvest(event *AchievementEvent, achievementMgr *AchievementManager) error {
resourceType, ok := event.Data["resource_type"].(string)
if !ok {
return fmt.Errorf("resource_type not found in event data")
}
isRare, _ := event.Data["is_rare"].(bool)
// Update harvesting achievements
achievementMgr.UpdateProgress(event.CharacterID, 70, 1) // Achievement ID 70: "Gatherer"
// Update resource-specific achievements
switch resourceType {
case "ore":
achievementMgr.UpdateProgress(event.CharacterID, 71, 1) // Achievement ID 71: "Miner"
case "wood":
achievementMgr.UpdateProgress(event.CharacterID, 72, 1) // Achievement ID 72: "Lumberjack"
case "fish":
achievementMgr.UpdateProgress(event.CharacterID, 73, 1) // Achievement ID 73: "Angler"
}
// Update rare harvest achievement
if isRare {
achievementMgr.UpdateProgress(event.CharacterID, 74, 1) // Achievement ID 74: "Lucky Find"
}
return nil
}
// handlePvPKill processes PvP kill events
func (aeh *AchievementEventHandler) handlePvPKill(event *AchievementEvent, achievementMgr *AchievementManager) error {
targetLevel, ok := event.Data["target_level"].(int32)
if !ok {
targetLevel = 1
}
// Update PvP achievements
achievementMgr.UpdateProgress(event.CharacterID, 80, 1) // Achievement ID 80: "First Blood PvP"
// Update level-based PvP achievements
if targetLevel >= 50 {
achievementMgr.UpdateProgress(event.CharacterID, 81, 1) // Achievement ID 81: "Veteran Slayer"
}
return nil
}
// handleGenericEvent processes generic events
func (aeh *AchievementEventHandler) handleGenericEvent(event *AchievementEvent, achievementMgr *AchievementManager) error {
// For events without specific handlers, attempt generic progress updates
// This allows for easy extension without requiring handler updates
// Log unhandled event types for debugging
fmt.Printf("Unhandled achievement event type: %d for character %d\n",
int(event.Type), event.CharacterID)
return nil
}
// TriggerEvent is a convenience method for triggering achievement events
func (w *World) TriggerAchievementEvent(eventType AchievementEventType, characterID int32, data map[string]any) {
if w.achievementMgr == nil {
return // Achievement system not initialized
}
event := &AchievementEvent{
Type: eventType,
CharacterID: characterID,
Data: data,
Timestamp: int64(w.worldTime.Year), // Use game time as timestamp
}
handler := NewAchievementEventHandler(w)
go func() {
if err := handler.ProcessEvent(event); err != nil {
fmt.Printf("Error processing achievement event: %v\n", err)
}
}()
}
// Convenience methods for common events
// OnNPCKill triggers an NPC kill achievement event
func (w *World) OnNPCKill(characterID int32, npcID int32, npcLevel int32) {
w.TriggerAchievementEvent(EventNPCKill, characterID, map[string]any{
"npc_id": npcID,
"level": npcLevel,
})
}
// OnQuestComplete triggers a quest completion achievement event
func (w *World) OnQuestComplete(characterID int32, questID int32) {
w.TriggerAchievementEvent(EventQuestCompleted, characterID, map[string]any{
"quest_id": questID,
})
}
// OnLevelGain triggers a level gain achievement event
func (w *World) OnLevelGain(characterID int32, newLevel int32) {
w.TriggerAchievementEvent(EventLevelGain, characterID, map[string]any{
"level": newLevel,
})
}
// OnItemDiscovered triggers an item discovery achievement event
func (w *World) OnItemDiscovered(characterID int32, itemID int32, rarity string) {
w.TriggerAchievementEvent(EventItemDiscovered, characterID, map[string]any{
"item_id": itemID,
"rarity": rarity,
})
}
// OnZoneDiscovered triggers a zone discovery achievement event
func (w *World) OnZoneDiscovered(characterID int32, zoneID int32) {
w.TriggerAchievementEvent(EventZoneDiscovered, characterID, map[string]any{
"zone_id": zoneID,
})
}