package skills import "fmt" // SkillAware interface for entities that have skills type SkillAware interface { GetSkillList() *PlayerSkillList GetSkillByName(name string) *Skill GetSkill(skillID int32) *Skill HasSkill(skillID int32) bool IncreaseSkill(skillName string, amount int32) error } // PacketSender interface for sending skill packets to clients type PacketSender interface { QueuePacket(packet []byte) GetVersion() int32 } // Database interface for skill persistence type Database interface { LoadPlayerSkills(characterID int32) ([]*Skill, error) SavePlayerSkill(characterID int32, skill *Skill) error LoadMasterSkills() ([]*Skill, error) SaveMasterSkill(skill *Skill) error } // Logger interface for skill system logging type Logger interface { LogInfo(message string, args ...interface{}) LogError(message string, args ...interface{}) LogDebug(message string, args ...interface{}) } // EntitySkillAdapter provides skill functionality for entities type EntitySkillAdapter struct { skillList *PlayerSkillList entityID int32 logger Logger } // NewEntitySkillAdapter creates a new entity skill adapter func NewEntitySkillAdapter(entityID int32, logger Logger) *EntitySkillAdapter { return &EntitySkillAdapter{ skillList: NewPlayerSkillList(), entityID: entityID, logger: logger, } } // GetSkillList returns the player's skill list func (esa *EntitySkillAdapter) GetSkillList() *PlayerSkillList { return esa.skillList } // GetSkillByName returns a skill by name func (esa *EntitySkillAdapter) GetSkillByName(name string) *Skill { return esa.skillList.GetSkillByName(name) } // GetSkill returns a skill by ID func (esa *EntitySkillAdapter) GetSkill(skillID int32) *Skill { return esa.skillList.GetSkill(skillID) } // HasSkill checks if the entity has a skill func (esa *EntitySkillAdapter) HasSkill(skillID int32) bool { return esa.skillList.HasSkill(skillID) } // IncreaseSkill increases a skill by name func (esa *EntitySkillAdapter) IncreaseSkill(skillName string, amount int32) error { skill := esa.skillList.GetSkillByName(skillName) if skill == nil { if esa.logger != nil { esa.logger.LogError("Entity %d: Skill '%s' not found for increase", esa.entityID, skillName) } return fmt.Errorf("skill '%s' not found", skillName) } esa.skillList.IncreaseSkill(skill, int16(amount)) if esa.logger != nil { esa.logger.LogDebug("Entity %d: Increased skill '%s' by %d (now %d/%d)", esa.entityID, skillName, amount, skill.CurrentVal, skill.MaxVal) } return nil } // AddSkill adds a new skill to the entity func (esa *EntitySkillAdapter) AddSkill(skill *Skill) { if skill == nil { return } esa.skillList.AddSkill(skill) if esa.logger != nil { esa.logger.LogDebug("Entity %d: Added skill '%s' (ID: %d)", esa.entityID, skill.Name.Data, skill.SkillID) } } // RemoveSkill removes a skill from the entity func (esa *EntitySkillAdapter) RemoveSkill(skill *Skill) { if skill == nil { return } esa.skillList.RemoveSkill(skill) if esa.logger != nil { esa.logger.LogDebug("Entity %d: Removed skill '%s' (ID: %d)", esa.entityID, skill.Name.Data, skill.SkillID) } } // GetSkillValue returns a skill's current value including bonuses func (esa *EntitySkillAdapter) GetSkillValue(skillID int32) int16 { skill := esa.skillList.GetSkill(skillID) if skill == nil { return 0 } return esa.skillList.CalculateSkillValue(skillID, skill.CurrentVal) } // GetSkillMaxValue returns a skill's max value including bonuses func (esa *EntitySkillAdapter) GetSkillMaxValue(skillID int32) int16 { skill := esa.skillList.GetSkill(skillID) if skill == nil { return 0 } return esa.skillList.CalculateSkillMaxValue(skillID, skill.MaxVal) } // ApplySkillBonus applies a skill bonus from a spell func (esa *EntitySkillAdapter) ApplySkillBonus(spellID int32, skillID int32, value float32) { esa.skillList.AddSkillBonus(spellID, skillID, value) if esa.logger != nil { esa.logger.LogDebug("Entity %d: Applied skill bonus from spell %d to skill %d: %f", esa.entityID, spellID, skillID, value) } } // RemoveSkillBonus removes skill bonuses from a spell func (esa *EntitySkillAdapter) RemoveSkillBonus(spellID int32) { esa.skillList.RemoveSkillBonus(spellID) if esa.logger != nil { esa.logger.LogDebug("Entity %d: Removed skill bonuses from spell %d", esa.entityID, spellID) } } // CheckSkillIncrease attempts to increase a skill func (esa *EntitySkillAdapter) CheckSkillIncrease(skillID int32) bool { skill := esa.skillList.GetSkill(skillID) if skill == nil { return false } increased := esa.skillList.CheckSkillIncrease(skill) if increased && esa.logger != nil { esa.logger.LogInfo("Entity %d: Skill '%s' increased to %d/%d", esa.entityID, skill.Name.Data, skill.CurrentVal, skill.MaxVal) } return increased } // GetSaveNeededSkills returns skills that need database saving func (esa *EntitySkillAdapter) GetSaveNeededSkills() []*Skill { return esa.skillList.GetSaveNeededSkills() } // GetSkillUpdates returns skills that need client updates func (esa *EntitySkillAdapter) GetSkillUpdates() []*Skill { return esa.skillList.GetSkillUpdates() } // HasSkillUpdates returns whether there are pending skill updates func (esa *EntitySkillAdapter) HasSkillUpdates() bool { return esa.skillList.HasSkillUpdates() } // SendSkillPacket sends skill updates to a client func (esa *EntitySkillAdapter) SendSkillPacket(sender PacketSender) error { if sender == nil { return fmt.Errorf("packet sender is nil") } packet, err := esa.skillList.GetSkillPacket(int16(sender.GetVersion())) if err != nil { return fmt.Errorf("failed to build skill packet: %w", err) } sender.QueuePacket(packet) if esa.logger != nil { esa.logger.LogDebug("Entity %d: Sent skill packet to client (version %d)", esa.entityID, sender.GetVersion()) } return nil } // LoadSkillsFromDatabase loads skills from database (placeholder) func (esa *EntitySkillAdapter) LoadSkillsFromDatabase(db Database, characterID int32) error { if db == nil { return fmt.Errorf("database is nil") } skills, err := db.LoadPlayerSkills(characterID) if err != nil { return fmt.Errorf("failed to load player skills: %w", err) } for _, skill := range skills { esa.skillList.AddSkill(skill) } if esa.logger != nil { esa.logger.LogInfo("Entity %d: Loaded %d skills from database", esa.entityID, len(skills)) } return nil } // SaveSkillsToDatabase saves skills to database (placeholder) func (esa *EntitySkillAdapter) SaveSkillsToDatabase(db Database, characterID int32) error { if db == nil { return fmt.Errorf("database is nil") } saveSkills := esa.GetSaveNeededSkills() for _, skill := range saveSkills { if err := db.SavePlayerSkill(characterID, skill); err != nil { if esa.logger != nil { esa.logger.LogError("Entity %d: Failed to save skill %s: %v", esa.entityID, skill.Name.Data, err) } return fmt.Errorf("failed to save skill %s: %w", skill.Name.Data, err) } } if len(saveSkills) > 0 && esa.logger != nil { esa.logger.LogInfo("Entity %d: Saved %d skills to database", esa.entityID, len(saveSkills)) } return nil }