eq2go/internal/titles/integration.go

404 lines
12 KiB
Go

package titles
import (
"fmt"
"time"
)
// AchievementIntegration handles title granting from achievements
type AchievementIntegration struct {
titleManager *TitleManager
}
// NewAchievementIntegration creates a new achievement integration handler
func NewAchievementIntegration(titleManager *TitleManager) *AchievementIntegration {
return &AchievementIntegration{
titleManager: titleManager,
}
}
// OnAchievementCompleted is called when a player completes an achievement
func (ai *AchievementIntegration) OnAchievementCompleted(playerID int32, achievementID uint32) error {
return ai.titleManager.ProcessAchievementCompletion(playerID, achievementID)
}
// QuestIntegration handles title granting from quest completion
type QuestIntegration struct {
titleManager *TitleManager
questTitles map[uint32]int32 // Maps quest ID to title ID
}
// NewQuestIntegration creates a new quest integration handler
func NewQuestIntegration(titleManager *TitleManager) *QuestIntegration {
qi := &QuestIntegration{
titleManager: titleManager,
questTitles: make(map[uint32]int32),
}
// Initialize quest-to-title mappings
qi.initializeQuestTitles()
return qi
}
// initializeQuestTitles sets up quest-to-title relationships
func (qi *QuestIntegration) initializeQuestTitles() {
// TODO: Load quest-title mappings from database or configuration
// These would be examples of quest rewards that grant titles
// Example mappings (these would come from quest definitions):
// qi.questTitles[1001] = heroTitleID // "Hero of Qeynos" from major storyline
// qi.questTitles[2001] = explorerTitleID // "Explorer" from exploration quest
// qi.questTitles[3001] = merchantTitleID // "Master Merchant" from trading quest
}
// OnQuestCompleted is called when a player completes a quest
func (qi *QuestIntegration) OnQuestCompleted(playerID int32, questID uint32) error {
titleID, exists := qi.questTitles[questID]
if !exists {
return nil // Quest doesn't grant a title
}
return qi.titleManager.GrantTitle(playerID, titleID, 0, questID)
}
// AddQuestTitleMapping adds a quest-to-title relationship
func (qi *QuestIntegration) AddQuestTitleMapping(questID uint32, titleID int32) {
qi.questTitles[questID] = titleID
}
// RemoveQuestTitleMapping removes a quest-to-title relationship
func (qi *QuestIntegration) RemoveQuestTitleMapping(questID uint32) {
delete(qi.questTitles, questID)
}
// LevelIntegration handles title granting based on character level
type LevelIntegration struct {
titleManager *TitleManager
levelTitles map[int32]int32 // Maps level to title ID
}
// NewLevelIntegration creates a new level integration handler
func NewLevelIntegration(titleManager *TitleManager) *LevelIntegration {
li := &LevelIntegration{
titleManager: titleManager,
levelTitles: make(map[int32]int32),
}
// Initialize level-based titles
li.initializeLevelTitles()
return li
}
// initializeLevelTitles sets up level milestone titles
func (li *LevelIntegration) initializeLevelTitles() {
// TODO: Create and register level milestone titles
// These would be created in the title manager and their IDs stored here
// Example level titles:
// li.levelTitles[10] = noviceTitleID // "Novice" at level 10
// li.levelTitles[25] = adeptTitleID // "Adept" at level 25
// li.levelTitles[50] = veteranTitleID // "Veteran" at level 50
// li.levelTitles[80] = masterTitleID // "Master" at level 80
// li.levelTitles[90] = championTitleID // "Champion" at level 90
}
// OnLevelUp is called when a player levels up
func (li *LevelIntegration) OnLevelUp(playerID, newLevel int32) error {
titleID, exists := li.levelTitles[newLevel]
if !exists {
return nil // No title for this level
}
return li.titleManager.GrantTitle(playerID, titleID, 0, 0)
}
// GuildIntegration handles title granting from guild activities
type GuildIntegration struct {
titleManager *TitleManager
}
// NewGuildIntegration creates a new guild integration handler
func NewGuildIntegration(titleManager *TitleManager) *GuildIntegration {
return &GuildIntegration{
titleManager: titleManager,
}
}
// OnGuildRankChanged is called when a player's guild rank changes
func (gi *GuildIntegration) OnGuildRankChanged(playerID int32, guildID, newRank int32) error {
// TODO: Implement guild rank titles
// Different guild ranks could grant different titles
// Example: Guild leaders get "Guild Leader" title
// if newRank == GUILD_RANK_LEADER {
// return gi.titleManager.GrantTitle(playerID, guildLeaderTitleID, 0, 0)
// }
return nil
}
// OnGuildAchievement is called when a guild completes an achievement
func (gi *GuildIntegration) OnGuildAchievement(guildID int32, achievementID uint32, memberIDs []int32) error {
// TODO: Implement guild achievement titles
// Guild achievements could grant titles to all participating members
// Example: Grant title to all guild members who participated
// for _, memberID := range memberIDs {
// err := gi.titleManager.GrantTitle(memberID, guildAchievementTitleID, achievementID, 0)
// if err != nil {
// // Log error but continue processing other members
// }
// }
return nil
}
// PvPIntegration handles title granting from PvP activities
type PvPIntegration struct {
titleManager *TitleManager
pvpStats map[int32]*PvPStats // Track PvP statistics per player
}
// PvPStats tracks player PvP statistics for title eligibility
type PvPStats struct {
PlayerKills int32
PlayerDeaths int32
HonorPoints int32
LastKillTime time.Time
KillStreak int32
MaxKillStreak int32
}
// NewPvPIntegration creates a new PvP integration handler
func NewPvPIntegration(titleManager *TitleManager) *PvPIntegration {
return &PvPIntegration{
titleManager: titleManager,
pvpStats: make(map[int32]*PvPStats),
}
}
// OnPlayerKill is called when a player kills another player
func (pi *PvPIntegration) OnPlayerKill(killerID, victimID int32, honorGained int32) error {
// Update killer stats
killerStats := pi.getOrCreateStats(killerID)
killerStats.PlayerKills++
killerStats.HonorPoints += honorGained
killerStats.LastKillTime = time.Now()
killerStats.KillStreak++
if killerStats.KillStreak > killerStats.MaxKillStreak {
killerStats.MaxKillStreak = killerStats.KillStreak
}
// Update victim stats
victimStats := pi.getOrCreateStats(victimID)
victimStats.PlayerDeaths++
victimStats.KillStreak = 0 // Reset kill streak on death
// Check for PvP milestone titles
return pi.checkPvPTitles(killerID, killerStats)
}
// getOrCreateStats gets or creates PvP stats for a player
func (pi *PvPIntegration) getOrCreateStats(playerID int32) *PvPStats {
stats, exists := pi.pvpStats[playerID]
if !exists {
stats = &PvPStats{}
pi.pvpStats[playerID] = stats
}
return stats
}
// checkPvPTitles checks if player qualifies for any PvP titles
func (pi *PvPIntegration) checkPvPTitles(playerID int32, stats *PvPStats) error {
// TODO: Implement PvP title thresholds and grant appropriate titles
// Example PvP title thresholds:
// if stats.PlayerKills >= 100 && stats.PlayerKills < 500 {
// pi.titleManager.GrantTitle(playerID, slayerTitleID, 0, 0)
// } else if stats.PlayerKills >= 500 && stats.PlayerKills < 1000 {
// pi.titleManager.GrantTitle(playerID, killerTitleID, 0, 0)
// } else if stats.PlayerKills >= 1000 {
// pi.titleManager.GrantTitle(playerID, warlordTitleID, 0, 0)
// }
// if stats.MaxKillStreak >= 10 {
// pi.titleManager.GrantTitle(playerID, unstoppableTitleID, 0, 0)
// }
return nil
}
// EventIntegration handles title granting from special events
type EventIntegration struct {
titleManager *TitleManager
activeEvents map[string]*Event // Active events by name
eventTitles map[string]int32 // Maps event name to title ID
}
// Event represents a time-limited server event
type Event struct {
Name string
StartTime time.Time
EndTime time.Time
IsActive bool
Description string
TitleID int32 // Title granted for participation
}
// NewEventIntegration creates a new event integration handler
func NewEventIntegration(titleManager *TitleManager) *EventIntegration {
return &EventIntegration{
titleManager: titleManager,
activeEvents: make(map[string]*Event),
eventTitles: make(map[string]int32),
}
}
// StartEvent activates a special event
func (ei *EventIntegration) StartEvent(name, description string, duration time.Duration, titleID int32) error {
event := &Event{
Name: name,
StartTime: time.Now(),
EndTime: time.Now().Add(duration),
IsActive: true,
Description: description,
TitleID: titleID,
}
ei.activeEvents[name] = event
ei.eventTitles[name] = titleID
return nil
}
// EndEvent deactivates a special event
func (ei *EventIntegration) EndEvent(name string) error {
event, exists := ei.activeEvents[name]
if !exists {
return fmt.Errorf("event %s does not exist", name)
}
event.IsActive = false
delete(ei.activeEvents, name)
return nil
}
// OnEventParticipation is called when a player participates in an event
func (ei *EventIntegration) OnEventParticipation(playerID int32, eventName string) error {
event, exists := ei.activeEvents[eventName]
if !exists || !event.IsActive {
return fmt.Errorf("event %s is not active", eventName)
}
// Check if event is still within time bounds
now := time.Now()
if now.Before(event.StartTime) || now.After(event.EndTime) {
event.IsActive = false
delete(ei.activeEvents, eventName)
return fmt.Errorf("event %s has expired", eventName)
}
// Grant event participation title
if event.TitleID > 0 {
return ei.titleManager.GrantTitle(playerID, event.TitleID, 0, 0)
}
return nil
}
// GetActiveEvents returns all currently active events
func (ei *EventIntegration) GetActiveEvents() []*Event {
result := make([]*Event, 0, len(ei.activeEvents))
for _, event := range ei.activeEvents {
// Check if event is still valid
now := time.Now()
if now.After(event.EndTime) {
event.IsActive = false
continue
}
if event.IsActive {
result = append(result, event)
}
}
return result
}
// TitleEarnedCallback represents a callback function called when a title is earned
type TitleEarnedCallback func(playerID, titleID int32, source string)
// IntegrationManager coordinates all title integration systems
type IntegrationManager struct {
titleManager *TitleManager
achievementIntegration *AchievementIntegration
questIntegration *QuestIntegration
levelIntegration *LevelIntegration
guildIntegration *GuildIntegration
pvpIntegration *PvPIntegration
eventIntegration *EventIntegration
callbacks []TitleEarnedCallback
}
// NewIntegrationManager creates a comprehensive integration manager
func NewIntegrationManager(titleManager *TitleManager) *IntegrationManager {
return &IntegrationManager{
titleManager: titleManager,
achievementIntegration: NewAchievementIntegration(titleManager),
questIntegration: NewQuestIntegration(titleManager),
levelIntegration: NewLevelIntegration(titleManager),
guildIntegration: NewGuildIntegration(titleManager),
pvpIntegration: NewPvPIntegration(titleManager),
eventIntegration: NewEventIntegration(titleManager),
callbacks: make([]TitleEarnedCallback, 0),
}
}
// AddTitleEarnedCallback adds a callback to be notified when titles are earned
func (im *IntegrationManager) AddTitleEarnedCallback(callback TitleEarnedCallback) {
im.callbacks = append(im.callbacks, callback)
}
// NotifyTitleEarned calls all registered callbacks when a title is earned
func (im *IntegrationManager) NotifyTitleEarned(playerID, titleID int32, source string) {
for _, callback := range im.callbacks {
callback(playerID, titleID, source)
}
}
// GetAchievementIntegration returns the achievement integration handler
func (im *IntegrationManager) GetAchievementIntegration() *AchievementIntegration {
return im.achievementIntegration
}
// GetQuestIntegration returns the quest integration handler
func (im *IntegrationManager) GetQuestIntegration() *QuestIntegration {
return im.questIntegration
}
// GetLevelIntegration returns the level integration handler
func (im *IntegrationManager) GetLevelIntegration() *LevelIntegration {
return im.levelIntegration
}
// GetGuildIntegration returns the guild integration handler
func (im *IntegrationManager) GetGuildIntegration() *GuildIntegration {
return im.guildIntegration
}
// GetPvPIntegration returns the PvP integration handler
func (im *IntegrationManager) GetPvPIntegration() *PvPIntegration {
return im.pvpIntegration
}
// GetEventIntegration returns the event integration handler
func (im *IntegrationManager) GetEventIntegration() *EventIntegration {
return im.eventIntegration
}