211 lines
4.2 KiB
Go

package monsters
import (
"fmt"
nigiri "git.sharkk.net/Sharkk/Nigiri"
)
// Monster represents a monster in the game
type Monster struct {
ID int `json:"id"`
Name string `json:"name" db:"required"`
MaxHP int `json:"max_hp"`
MaxDmg int `json:"max_dmg"`
Armor int `json:"armor"`
Level int `json:"level" db:"index"`
MaxExp int `json:"max_exp"`
MaxGold int `json:"max_gold"`
Immune int `json:"immune" db:"index"`
}
// Immunity constants
const (
ImmuneNone = 0
ImmuneHurt = 1
ImmuneSleep = 2
)
// Global store
var store *nigiri.BaseStore[Monster]
var db *nigiri.Collection
// Init sets up the Nigiri store and indices
func Init(collection *nigiri.Collection) {
db = collection
store = nigiri.NewBaseStore[Monster]()
// Register custom indices
store.RegisterIndex("byLevel", nigiri.BuildIntGroupIndex(func(m *Monster) int {
return m.Level
}))
store.RegisterIndex("byImmunity", nigiri.BuildIntGroupIndex(func(m *Monster) int {
return m.Immune
}))
store.RegisterIndex("allByLevel", nigiri.BuildSortedListIndex(func(a, b *Monster) bool {
if a.Level == b.Level {
return a.ID < b.ID
}
return a.Level < b.Level
}))
store.RebuildIndices()
}
// GetStore returns the monsters store
func GetStore() *nigiri.BaseStore[Monster] {
if store == nil {
panic("monsters store not initialized - call Initialize first")
}
return store
}
// Creates a new Monster with sensible defaults
func New() *Monster {
return &Monster{
Name: "",
MaxHP: 10,
MaxDmg: 5,
Armor: 0,
Level: 1,
MaxExp: 10,
MaxGold: 5,
Immune: ImmuneNone,
}
}
// Validate checks if monster has valid values
func (m *Monster) Validate() error {
if m.Name == "" {
return fmt.Errorf("monster name cannot be empty")
}
if m.MaxHP < 1 {
return fmt.Errorf("monster MaxHP must be at least 1")
}
if m.Level < 1 {
return fmt.Errorf("monster Level must be at least 1")
}
if m.Immune < ImmuneNone || m.Immune > ImmuneSleep {
return fmt.Errorf("invalid immunity type: %d", m.Immune)
}
return nil
}
// CRUD operations
func (m *Monster) Save() error {
if m.ID == 0 {
id, err := store.Create(m)
if err != nil {
return err
}
m.ID = id
return nil
}
return store.Update(m.ID, m)
}
func (m *Monster) Delete() error {
store.Remove(m.ID)
return nil
}
// Insert with ID assignment
func (m *Monster) Insert() error {
id, err := store.Create(m)
if err != nil {
return err
}
m.ID = id
return nil
}
// Query functions
func Find(id int) (*Monster, error) {
monster, exists := store.Find(id)
if !exists {
return nil, fmt.Errorf("monster with ID %d not found", id)
}
return monster, nil
}
func All() ([]*Monster, error) {
return store.AllSorted("allByLevel"), nil
}
func ByLevel(level int) ([]*Monster, error) {
return store.GroupByIndex("byLevel", level), nil
}
func ByLevelRange(minLevel, maxLevel int) ([]*Monster, error) {
var result []*Monster
for level := minLevel; level <= maxLevel; level++ {
monsters := store.GroupByIndex("byLevel", level)
result = append(result, monsters...)
}
return result, nil
}
func ByImmunity(immunityType int) ([]*Monster, error) {
return store.GroupByIndex("byImmunity", immunityType), nil
}
// Helper methods
func (m *Monster) IsHurtImmune() bool {
return m.Immune == ImmuneHurt
}
func (m *Monster) IsSleepImmune() bool {
return m.Immune == ImmuneSleep
}
func (m *Monster) HasImmunity() bool {
return m.Immune != ImmuneNone
}
func (m *Monster) ImmunityName() string {
switch m.Immune {
case ImmuneNone:
return "None"
case ImmuneHurt:
return "Hurt Spells"
case ImmuneSleep:
return "Sleep Spells"
default:
return "Unknown"
}
}
func (m *Monster) DifficultyRating() float64 {
if m.Level == 0 {
return 0
}
return float64(m.MaxHP+m.MaxDmg+m.Armor) / float64(m.Level)
}
func (m *Monster) ExpPerHP() float64 {
if m.MaxHP == 0 {
return 0
}
return float64(m.MaxExp) / float64(m.MaxHP)
}
func (m *Monster) GoldPerHP() float64 {
if m.MaxHP == 0 {
return 0
}
return float64(m.MaxGold) / float64(m.MaxHP)
}
// 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
}