aboutsummaryrefslogtreecommitdiff
path: root/internal/world/mob.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-09 05:59:20 -0400
committerhistoria <[not public]>2026-06-09 05:59:20 -0400
commit9eb5ab1818b6b19501fd7209db1987c9e06cc919 (patch)
tree76e046b0bf611dfe939a8c8f6507467de2e9e20f /internal/world/mob.go
downloadthehouseoficarus-9eb5ab1818b6b19501fd7209db1987c9e06cc919.tar.gz
first commit
Diffstat (limited to 'internal/world/mob.go')
-rw-r--r--internal/world/mob.go181
1 files changed, 181 insertions, 0 deletions
diff --git a/internal/world/mob.go b/internal/world/mob.go
new file mode 100644
index 0000000..601cdc1
--- /dev/null
+++ b/internal/world/mob.go
@@ -0,0 +1,181 @@
+package world
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "sync"
+
+ "gopkg.in/yaml.v3"
+)
+
+type LootEntry struct {
+ ItemID string `yaml:"item_id"`
+ Weight int `yaml:"weight"`
+ Quantity int `yaml:"quantity"`
+}
+
+type DropTable struct {
+ Remains string `yaml:"remains"`
+ Loot []LootEntry `yaml:"loot"`
+}
+
+type MobDef struct {
+ ID string `yaml:"id"`
+ Name string `yaml:"name"`
+ Attack int `yaml:"attack"`
+ Strength int `yaml:"strength"`
+ Defense int `yaml:"defense"`
+ HP int `yaml:"hp"`
+ Speed int `yaml:"speed"`
+ Aggressive bool `yaml:"aggressive"`
+ RespawnTicks int `yaml:"respawn_ticks"`
+ Drops DropTable `yaml:"drops"`
+}
+
+type MobInstance struct {
+ InstanceID string
+ DefID string
+ Name string
+ HP int
+ MaxHP int
+ Attack int
+ Strength int
+ Defense int
+ Speed int
+ Aggressive bool
+ RespawnTicks int
+ RoomID int
+ Drops DropTable
+}
+
+type MobStore struct {
+ dataDir string
+ mu sync.Mutex
+ defs map[string]*MobDef
+ instances map[string]*MobInstance
+}
+
+func NewMobStore(dataDir string) *MobStore {
+ return &MobStore{
+ dataDir: dataDir,
+ defs: make(map[string]*MobDef),
+ instances: make(map[string]*MobInstance),
+ }
+}
+
+func (s *MobStore) LoadDef(id string) (*MobDef, error) {
+ s.mu.Lock()
+ if def, ok := s.defs[id]; ok {
+ s.mu.Unlock()
+ return def, nil
+ }
+ s.mu.Unlock()
+
+ path := filepath.Join(s.dataDir, "mobs", id+".yaml")
+ data, err := os.ReadFile(path)
+ if err != nil {
+ return nil, fmt.Errorf("read mob %s: %w", id, err)
+ }
+ var def MobDef
+ if err := yaml.Unmarshal(data, &def); err != nil {
+ return nil, fmt.Errorf("parse mob %s: %w", id, err)
+ }
+
+ s.mu.Lock()
+ s.defs[id] = &def
+ s.mu.Unlock()
+ return &def, nil
+}
+
+func (s *MobStore) SpawnMob(defID string, roomID int, instanceID string) (*MobInstance, error) {
+ def, err := s.LoadDef(defID)
+ if err != nil {
+ return nil, err
+ }
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ inst := &MobInstance{
+ InstanceID: instanceID,
+ DefID: defID,
+ Name: def.Name,
+ HP: def.HP,
+ MaxHP: def.HP,
+ Attack: def.Attack,
+ Strength: def.Strength,
+ Defense: def.Defense,
+ Speed: def.Speed,
+ Aggressive: def.Aggressive,
+ RespawnTicks: def.RespawnTicks,
+ RoomID: roomID,
+ Drops: def.Drops,
+ }
+ s.instances[instanceID] = inst
+ return inst, nil
+}
+
+func (s *MobStore) GetInstance(id string) *MobInstance {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ return s.instances[id]
+}
+
+func (s *MobStore) RemoveInstance(id string) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ delete(s.instances, id)
+}
+
+func (s *MobStore) MobsInRoom(roomID int) []*MobInstance {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ var out []*MobInstance
+ for _, inst := range s.instances {
+ if inst.RoomID == roomID && inst.HP > 0 {
+ out = append(out, inst)
+ }
+ }
+ return out
+}
+
+func (s *MobStore) SeedMobs(roomID int, mobIDs []string) {
+ type defWrapper struct {
+ def *MobDef
+ err error
+ }
+ defs := make([]defWrapper, len(mobIDs))
+ for i, defID := range mobIDs {
+ d, err := s.LoadDef(defID)
+ defs[i] = defWrapper{d, err}
+ }
+
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ for i, dw := range defs {
+ if dw.err != nil {
+ continue
+ }
+ defID := mobIDs[i]
+ instID := fmt.Sprintf("%s_%d_%d", defID, roomID, i)
+ if inst, exists := s.instances[instID]; exists {
+ // Already exists — skip (respawn is handled by timers)
+ _ = inst
+ continue
+ }
+ s.instances[instID] = &MobInstance{
+ InstanceID: instID,
+ DefID: defID,
+ Name: dw.def.Name,
+ HP: dw.def.HP,
+ MaxHP: dw.def.HP,
+ Attack: dw.def.Attack,
+ Strength: dw.def.Strength,
+ Defense: dw.def.Defense,
+ Speed: dw.def.Speed,
+ Aggressive: dw.def.Aggressive,
+ RespawnTicks: dw.def.RespawnTicks,
+ RoomID: roomID,
+ Drops: dw.def.Drops,
+ }
+ }
+}