211 lines
4.2 KiB
Go
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
|
|
}
|