2025-08-07 12:47:52 -05:00

158 lines
4.6 KiB
Go

package alt_advancement
import (
"fmt"
"eq2emu/internal/common"
)
// MasterList manages the global list of all alternate advancements
type MasterList struct {
*common.MasterList[int32, *AltAdvancement]
}
// NewMasterList creates a new master alternate advancement list
func NewMasterList() *MasterList {
return &MasterList{
MasterList: common.NewMasterList[int32, *AltAdvancement](),
}
}
// AddAltAdvancement adds an alternate advancement to the master list
// Returns false if AA with same ID already exists
func (m *MasterList) AddAltAdvancement(aa *AltAdvancement) bool {
if aa == nil {
return false
}
return m.MasterList.Add(aa)
}
// GetAltAdvancement retrieves an alternate advancement by node ID
// Returns nil if not found
func (m *MasterList) GetAltAdvancement(nodeID int32) *AltAdvancement {
return m.MasterList.Get(nodeID)
}
// GetAltAdvancementClone retrieves a cloned copy of an alternate advancement by node ID
// Returns nil if not found. Safe for modification without affecting master list
func (m *MasterList) GetAltAdvancementClone(nodeID int32) *AltAdvancement {
aa := m.MasterList.Get(nodeID)
if aa == nil {
return nil
}
return aa.Clone()
}
// GetAllAltAdvancements returns a map of all alternate advancements (read-only access)
// The returned map should not be modified
func (m *MasterList) GetAllAltAdvancements() map[int32]*AltAdvancement {
return m.MasterList.GetAll()
}
// GetAltAdvancementsByGroup returns alternate advancements filtered by group/tab
func (m *MasterList) GetAltAdvancementsByGroup(group int8) []*AltAdvancement {
return m.MasterList.Filter(func(aa *AltAdvancement) bool {
return aa.Group == group
})
}
// GetAltAdvancementsByClass returns alternate advancements filtered by class requirement
func (m *MasterList) GetAltAdvancementsByClass(classID int8) []*AltAdvancement {
return m.MasterList.Filter(func(aa *AltAdvancement) bool {
return aa.ClassReq == 0 || aa.ClassReq == classID
})
}
// GetAltAdvancementsByLevel returns alternate advancements available at a specific level
func (m *MasterList) GetAltAdvancementsByLevel(level int8) []*AltAdvancement {
return m.MasterList.Filter(func(aa *AltAdvancement) bool {
return aa.MinLevel <= level
})
}
// RemoveAltAdvancement removes an alternate advancement from the master list
// Returns true if AA was found and removed
func (m *MasterList) RemoveAltAdvancement(nodeID int32) bool {
return m.MasterList.Remove(nodeID)
}
// UpdateAltAdvancement updates an existing alternate advancement
// Returns error if AA doesn't exist
func (m *MasterList) UpdateAltAdvancement(aa *AltAdvancement) error {
if aa == nil {
return fmt.Errorf("alternate advancement cannot be nil")
}
return m.MasterList.Update(aa)
}
// GetGroups returns all unique groups/tabs that have alternate advancements
func (m *MasterList) GetGroups() []int8 {
groups := make(map[int8]bool)
m.MasterList.ForEach(func(_ int32, aa *AltAdvancement) {
groups[aa.Group] = true
})
result := make([]int8, 0, len(groups))
for group := range groups {
result = append(result, group)
}
return result
}
// GetClasses returns all unique classes that have alternate advancements
func (m *MasterList) GetClasses() []int8 {
classes := make(map[int8]bool)
m.MasterList.ForEach(func(_ int32, aa *AltAdvancement) {
if aa.ClassReq > 0 {
classes[aa.ClassReq] = true
}
})
result := make([]int8, 0, len(classes))
for class := range classes {
result = append(result, class)
}
return result
}
// ValidateAll validates all alternate advancements in the master list
func (m *MasterList) ValidateAll() []error {
var errors []error
m.MasterList.ForEach(func(nodeID int32, aa *AltAdvancement) {
if !aa.IsValid() {
errors = append(errors, fmt.Errorf("invalid AA data: node_id=%d", nodeID))
}
// Validate prerequisites
if aa.RankPrereqID > 0 {
prereq := m.MasterList.Get(aa.RankPrereqID)
if prereq == nil {
errors = append(errors, fmt.Errorf("AA %d has invalid prerequisite node ID %d", nodeID, aa.RankPrereqID))
}
}
// Validate positioning
if aa.Col < MIN_AA_COL || aa.Col > MAX_AA_COL {
errors = append(errors, fmt.Errorf("AA %d has invalid column %d", nodeID, aa.Col))
}
if aa.Row < MIN_AA_ROW || aa.Row > MAX_AA_ROW {
errors = append(errors, fmt.Errorf("AA %d has invalid row %d", nodeID, aa.Row))
}
// Validate costs and ranks
if aa.RankCost < MIN_RANK_COST || aa.RankCost > MAX_RANK_COST {
errors = append(errors, fmt.Errorf("AA %d has invalid rank cost %d", nodeID, aa.RankCost))
}
if aa.MaxRank < MIN_MAX_RANK || aa.MaxRank > MAX_MAX_RANK {
errors = append(errors, fmt.Errorf("AA %d has invalid max rank %d", nodeID, aa.MaxRank))
}
})
return errors
}