package spells import ( "fmt" "strings" nigiri "git.sharkk.net/Sharkk/Nigiri" ) // Spell represents a spell in the game type Spell struct { ID int `json:"id"` Name string `json:"name" db:"required,unique"` MP int `json:"mp" db:"index"` Attribute int `json:"attribute"` Type int `json:"type" db:"index"` } // SpellType constants for spell types const ( TypeHealing = 1 TypeHurt = 2 TypeSleep = 3 TypeAttackBoost = 4 TypeDefenseBoost = 5 ) // Global store var store *nigiri.BaseStore[Spell] var db *nigiri.Collection // Init sets up the Nigiri store and indices func Init(collection *nigiri.Collection) { db = collection store = nigiri.NewBaseStore[Spell]() // Register custom indices store.RegisterIndex("byType", nigiri.BuildIntGroupIndex(func(s *Spell) int { return s.Type })) store.RegisterIndex("byName", nigiri.BuildCaseInsensitiveLookupIndex(func(s *Spell) string { return s.Name })) store.RegisterIndex("byMP", nigiri.BuildIntGroupIndex(func(s *Spell) int { return s.MP })) store.RegisterIndex("allByTypeMP", nigiri.BuildSortedListIndex(func(a, b *Spell) bool { if a.Type != b.Type { return a.Type < b.Type } if a.MP != b.MP { return a.MP < b.MP } return a.ID < b.ID })) store.RebuildIndices() } // GetStore returns the spells store func GetStore() *nigiri.BaseStore[Spell] { if store == nil { panic("spells store not initialized - call Initialize first") } return store } // Creates a new Spell with sensible defaults func New() *Spell { return &Spell{ Name: "", MP: 5, // Default MP cost Attribute: 10, // Default attribute value Type: TypeHealing, // Default to healing spell } } // Validate checks if spell has valid values func (s *Spell) Validate() error { if s.Name == "" { return fmt.Errorf("spell name cannot be empty") } if s.MP < 0 { return fmt.Errorf("spell MP cannot be negative") } if s.Attribute < 0 { return fmt.Errorf("spell Attribute cannot be negative") } if s.Type < TypeHealing || s.Type > TypeDefenseBoost { return fmt.Errorf("invalid spell type: %d", s.Type) } return nil } // CRUD operations func (s *Spell) Save() error { if s.ID == 0 { id, err := store.Create(s) if err != nil { return err } s.ID = id return nil } return store.Update(s.ID, s) } func (s *Spell) Delete() error { store.Remove(s.ID) return nil } // Insert with ID assignment func (s *Spell) Insert() error { id, err := store.Create(s) if err != nil { return err } s.ID = id return nil } // Query functions func Find(id int) (*Spell, error) { spell, exists := store.Find(id) if !exists { return nil, fmt.Errorf("spell with ID %d not found", id) } return spell, nil } func All() ([]*Spell, error) { return store.AllSorted("allByTypeMP"), nil } func ByType(spellType int) ([]*Spell, error) { return store.GroupByIndex("byType", spellType), nil } func ByMaxMP(maxMP int) ([]*Spell, error) { return store.FilterByIndex("allByTypeMP", func(s *Spell) bool { return s.MP <= maxMP }), nil } func ByTypeAndMaxMP(spellType, maxMP int) ([]*Spell, error) { return store.FilterByIndex("allByTypeMP", func(s *Spell) bool { return s.Type == spellType && s.MP <= maxMP }), nil } func ByName(name string) (*Spell, error) { spell, exists := store.LookupByIndex("byName", strings.ToLower(name)) if !exists { return nil, fmt.Errorf("spell with name '%s' not found", name) } return spell, nil } // Helper methods func (s *Spell) IsHealing() bool { return s.Type == TypeHealing } func (s *Spell) IsHurt() bool { return s.Type == TypeHurt } func (s *Spell) IsSleep() bool { return s.Type == TypeSleep } func (s *Spell) IsAttackBoost() bool { return s.Type == TypeAttackBoost } func (s *Spell) IsDefenseBoost() bool { return s.Type == TypeDefenseBoost } func (s *Spell) TypeName() string { switch s.Type { case TypeHealing: return "Healing" case TypeHurt: return "Hurt" case TypeSleep: return "Sleep" case TypeAttackBoost: return "Attack Boost" case TypeDefenseBoost: return "Defense Boost" default: return "Unknown" } } func (s *Spell) CanCast(availableMP int) bool { return availableMP >= s.MP } func (s *Spell) Efficiency() float64 { if s.MP == 0 { return 0 } return float64(s.Attribute) / float64(s.MP) } func (s *Spell) IsOffensive() bool { return s.Type == TypeHurt || s.Type == TypeSleep } func (s *Spell) IsSupport() bool { return s.Type == TypeHealing || s.Type == TypeAttackBoost || s.Type == TypeDefenseBoost } // Legacy compatibility functions (will be removed later) func LoadData(dataPath string) error { // No longer needed - Nigiri handles this return nil } func SaveData(dataPath string) error { // No longer needed - Nigiri handles this return nil }