eq2go/internal/skills/skill_bonuses.go

176 lines
4.4 KiB
Go

package skills
// AddSkillBonus adds a skill bonus from a spell
func (psl *PlayerSkillList) AddSkillBonus(spellID int32, skillID int32, value float32) {
if value == 0 {
return
}
psl.bonusMutex.Lock()
defer psl.bonusMutex.Unlock()
// Get or create skill bonus entry for this spell
skillBonus, exists := psl.skillBonusList[spellID]
if !exists {
skillBonus = &SkillBonus{
SpellID: spellID,
Skills: make(map[int32]*SkillBonusValue),
}
psl.skillBonusList[spellID] = skillBonus
}
// Add or update the skill bonus value
if skillBonus.Skills[skillID] == nil {
skillBonus.Skills[skillID] = &SkillBonusValue{
SkillID: skillID,
Value: value,
}
}
}
// GetSkillBonus returns skill bonus for a spell
func (psl *PlayerSkillList) GetSkillBonus(spellID int32) *SkillBonus {
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
if bonus, exists := psl.skillBonusList[spellID]; exists {
return bonus
}
return nil
}
// RemoveSkillBonus removes all skill bonuses from a spell
func (psl *PlayerSkillList) RemoveSkillBonus(spellID int32) {
psl.bonusMutex.Lock()
defer psl.bonusMutex.Unlock()
if skillBonus, exists := psl.skillBonusList[spellID]; exists {
// Clean up skill bonus values
for _, bonusValue := range skillBonus.Skills {
_ = bonusValue // In C++, this would be safe_delete(bonusValue)
}
delete(psl.skillBonusList, spellID)
}
}
// CalculateSkillValue calculates a skill's value including bonuses
func (psl *PlayerSkillList) CalculateSkillValue(skillID int32, currentVal int16) int16 {
if currentVal <= 5 {
return currentVal
}
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
newVal := currentVal
// Apply all skill bonuses
for _, skillBonus := range psl.skillBonusList {
if bonusValue, exists := skillBonus.Skills[skillID]; exists {
newVal += int16(bonusValue.Value)
}
}
return newVal
}
// CalculateSkillMaxValue calculates a skill's max value including bonuses
func (psl *PlayerSkillList) CalculateSkillMaxValue(skillID int32, maxVal int16) int16 {
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
newVal := maxVal
// Apply all skill bonuses to max value
for _, skillBonus := range psl.skillBonusList {
if bonusValue, exists := skillBonus.Skills[skillID]; exists {
newVal += int16(bonusValue.Value)
}
}
return newVal
}
// GetAllSkillBonuses returns all skill bonuses (for debugging/admin)
func (psl *PlayerSkillList) GetAllSkillBonuses() map[int32]*SkillBonus {
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
// Return a copy to prevent external modification
bonuses := make(map[int32]*SkillBonus)
for spellID, bonus := range psl.skillBonusList {
// Deep copy the skill bonus
newBonus := &SkillBonus{
SpellID: bonus.SpellID,
Skills: make(map[int32]*SkillBonusValue),
}
for skillID, bonusValue := range bonus.Skills {
newBonus.Skills[skillID] = &SkillBonusValue{
SkillID: bonusValue.SkillID,
Value: bonusValue.Value,
}
}
bonuses[spellID] = newBonus
}
return bonuses
}
// RemoveAllSkillBonuses removes all skill bonuses (for cleanup)
func (psl *PlayerSkillList) RemoveAllSkillBonuses() {
psl.bonusMutex.Lock()
defer psl.bonusMutex.Unlock()
// Clean up all skill bonuses
for spellID := range psl.skillBonusList {
if skillBonus, exists := psl.skillBonusList[spellID]; exists {
for _, bonusValue := range skillBonus.Skills {
_ = bonusValue // In C++, this would be safe_delete(bonusValue)
}
}
}
psl.skillBonusList = make(map[int32]*SkillBonus)
}
// GetSkillBonusTotal returns the total bonus for a specific skill
func (psl *PlayerSkillList) GetSkillBonusTotal(skillID int32) float32 {
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
var total float32
for _, skillBonus := range psl.skillBonusList {
if bonusValue, exists := skillBonus.Skills[skillID]; exists {
total += bonusValue.Value
}
}
return total
}
// HasSkillBonuses returns whether the player has any skill bonuses
func (psl *PlayerSkillList) HasSkillBonuses() bool {
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
return len(psl.skillBonusList) > 0
}
// GetSpellsWithSkillBonuses returns all spell IDs that provide skill bonuses
func (psl *PlayerSkillList) GetSpellsWithSkillBonuses() []int32 {
psl.bonusMutex.RLock()
defer psl.bonusMutex.RUnlock()
spellIDs := make([]int32, 0, len(psl.skillBonusList))
for spellID := range psl.skillBonusList {
spellIDs = append(spellIDs, spellID)
}
return spellIDs
}