Files
bd2/go/internal/server/player/equipment_stats.go
T

82 lines
2.2 KiB
Go

package player
import (
"bd2server/internal/server/gamedata"
"errors"
"fmt"
"math"
)
func (s *EquipmentInventory) AttachStatDesign(design *gamedata.EquipmentStatDesign) error {
if design == nil {
return errors.New("player: nil equipment stat design")
}
s.mu.Lock()
defer s.mu.Unlock()
s.statDesign = design
return nil
}
// StatContributions resolves only maximum-health equipment effects. Snapshot
// options under the equipment lock and release it before calculating; callers
// may themselves be the CharacterStore maximum-health callback.
func (s *EquipmentInventory) StatContributions(character Character) ([]gamedata.StatContribution, error) {
if character.InvenIndex == 0 {
return nil, errors.New("player: invalid equipment stat character")
}
type query struct {
option gamedata.EquipmentOption
sub bool
}
var queries []query
s.mu.Lock()
design := s.statDesign
for _, equipment := range s.owned.Equipment {
if equipment.UseChar != character.InvenIndex {
continue
}
if equipment.Level > math.MaxInt32 {
s.mu.Unlock()
return nil, fmt.Errorf("player: invalid equipment %d level", equipment.InvenIndex)
}
var rank [3]int
for i, value := range equipment.Rank {
if i >= 3 || value > 4 {
s.mu.Unlock()
return nil, fmt.Errorf("player: invalid equipment %d ranks", equipment.InvenIndex)
}
rank[i] = int(value)
}
add := func(option EquipmentOption, sub bool) {
if option.ID == 1 || option.ID == 2 {
queries = append(queries, query{gamedata.EquipmentOption{GroupID: option.GroupID, ID: option.ID, Level: int(equipment.Level), Rank: rank}, sub})
}
}
for _, option := range equipment.MainOption {
add(option, false)
}
for _, option := range equipment.SubOption {
add(option, true)
}
if equipment.PrivateOption != nil {
add(*equipment.PrivateOption, false)
}
}
s.mu.Unlock()
if len(queries) == 0 {
return nil, nil
}
if design == nil {
return nil, errors.New("player: equipment stat design unavailable")
}
result := make([]gamedata.StatContribution, 0, len(queries))
for _, query := range queries {
contribution, err := design.HealthContribution(query.option, query.sub)
if err != nil {
return nil, err
}
result = append(result, contribution)
}
return result, nil
}