1
1
mirror of https://github.com/OpenDiablo2/OpenDiablo2 synced 2024-09-30 07:06:18 -04:00
OpenDiablo2/d2core/d2stats/diablo2stats/statlist.go

121 lines
2.8 KiB
Go
Raw Normal View History

package diablo2stats
import (
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2stats"
)
// static check that diablo2Stat implements Stat
var _ d2stats.StatList = &Diablo2StatList{}
// Diablo2StatList is a diablo 2 implementation of a stat list
type Diablo2StatList struct {
stats []d2stats.Stat
}
// Index returns a stat given with the given index
func (sl *Diablo2StatList) Index(idx int) d2stats.Stat {
if idx < 0 || idx > len(sl.stats) {
return nil
}
return sl.stats[idx]
}
// Stats returns a slice of stats
func (sl *Diablo2StatList) Stats() []d2stats.Stat {
return sl.stats
}
// SetStats sets the stats, given a slice of stats
func (sl *Diablo2StatList) SetStats(stats []d2stats.Stat) d2stats.StatList {
sl.stats = stats
return sl
}
// Pop removes the last stat from the stat list
func (sl *Diablo2StatList) Pop() d2stats.Stat {
num := len(sl.stats)
if num < 1 {
return nil
}
idx := num - 1
last := sl.stats[idx]
sl.stats = sl.stats[:idx]
return last
}
// Push adds a stat at the end of the stat list
func (sl *Diablo2StatList) Push(stat d2stats.Stat) d2stats.StatList {
sl.stats = append(sl.stats, stat)
return sl
}
// Clone returns a deep copy of the stat list
func (sl *Diablo2StatList) Clone() d2stats.StatList {
clone := &Diablo2StatList{}
clone.stats = make([]d2stats.Stat, len(sl.stats))
for idx := range sl.stats {
if stat := sl.Index(idx); stat != nil {
clone.stats[idx] = stat.Clone()
}
}
return clone
}
// ReduceStats combines like stats (does not alter this stat list, returns clone)
func (sl *Diablo2StatList) ReduceStats() d2stats.StatList {
clone := sl.Clone()
reduction := make([]d2stats.Stat, 0)
// for quick lookups
lookup := make(map[string]int)
for len(clone.Stats()) > 0 {
stat := clone.Pop()
// if we find it in the lookup, immediately try to combine
// if it doesn't combine, we append to the reduction
if idx, found := lookup[stat.Name()]; found {
if result, err := reduction[idx].Combine(stat); err == nil {
reduction[idx] = result
continue
}
}
// we didnt find it in the lookup, so we will try to combine with other stats
for idx := range reduction {
if _, err := reduction[idx].Combine(stat); err == nil {
continue
}
}
lookup[stat.Name()] = len(lookup)
reduction = append(reduction, stat)
}
return clone.SetStats(reduction)
}
// RemoveStatAtIndex removes the stat from the stat list, returns the stat
func (sl *Diablo2StatList) RemoveStatAtIndex(idx int) d2stats.Stat {
picked := sl.stats[idx]
sl.stats[idx] = sl.stats[len(sl.stats)-1]
sl.stats[len(sl.stats)-1] = nil
sl.stats = sl.stats[:len(sl.stats)-1]
return picked
}
// AppendStatList adds the stats from the other stat list to this stat list
func (sl *Diablo2StatList) AppendStatList(other d2stats.StatList) d2stats.StatList {
sl.stats = append(sl.stats, other.Stats()...)
return sl
}