67 lines
2.1 KiB
Go
67 lines
2.1 KiB
Go
package player
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
)
|
|
|
|
// AddTalentExperience applies the same clamp as the client: talent experience
|
|
// may reach the cumulative threshold of the current level, but this request
|
|
// never promotes the talent level itself.
|
|
func (s *CharacterStore) AddTalentExperience(index, gain, maximum uint64) (Character, error) {
|
|
if s == nil || index == 0 || maximum == 0 {
|
|
return Character{}, errors.New("player: invalid talent experience update")
|
|
}
|
|
s.mu.Lock()
|
|
for position, current := range s.characters {
|
|
if current.InvenIndex != index {
|
|
continue
|
|
}
|
|
if current.TalentExp > maximum {
|
|
s.mu.Unlock()
|
|
return Character{}, fmt.Errorf("player: character %d talent experience exceeds current threshold", index)
|
|
}
|
|
if gain > maximum-current.TalentExp {
|
|
gain = maximum - current.TalentExp
|
|
}
|
|
if current.TalentExp > math.MaxUint64-gain {
|
|
s.mu.Unlock()
|
|
return Character{}, errors.New("player: talent experience overflow")
|
|
}
|
|
current.TalentExp += gain
|
|
next := append([]Character(nil), s.characters...)
|
|
next[position] = current
|
|
if err := s.persist(next); err != nil {
|
|
s.mu.Unlock()
|
|
return Character{}, fmt.Errorf("player: persist equipment making talent experience: %w", err)
|
|
}
|
|
s.characters = next
|
|
s.mu.Unlock()
|
|
return current, nil
|
|
}
|
|
collection := s.collection
|
|
s.mu.Unlock()
|
|
if collection == nil {
|
|
return Character{}, fmt.Errorf("player: unknown equipment making character %d", index)
|
|
}
|
|
current, found := collection.FindCharacter(index)
|
|
if !found {
|
|
return Character{}, fmt.Errorf("player: unknown equipment making character %d", index)
|
|
}
|
|
if current.TalentExp > maximum {
|
|
return Character{}, fmt.Errorf("player: character %d talent experience exceeds current threshold", index)
|
|
}
|
|
if gain > maximum-current.TalentExp {
|
|
gain = maximum - current.TalentExp
|
|
}
|
|
if current.TalentExp > math.MaxUint64-gain {
|
|
return Character{}, errors.New("player: talent experience overflow")
|
|
}
|
|
current.TalentExp += gain
|
|
if err := collection.UpdateCharacter(current.ID, current); err != nil {
|
|
return Character{}, fmt.Errorf("player: persist collection equipment making talent experience: %w", err)
|
|
}
|
|
return current, nil
|
|
}
|