2020-07-23 19:03:58 -04:00
|
|
|
package diablo2stats
|
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2stats"
|
|
|
|
)
|
|
|
|
|
2020-07-23 22:12:48 -04:00
|
|
|
// static check that diablo2Stat implements Stat
|
2020-07-23 19:03:58 -04:00
|
|
|
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
|
|
|
|
}
|