diff options
| author | historia <[not public]> | 2026-06-09 05:59:20 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-09 05:59:20 -0400 |
| commit | 9eb5ab1818b6b19501fd7209db1987c9e06cc919 (patch) | |
| tree | 76e046b0bf611dfe939a8c8f6507467de2e9e20f /internal/world/mob.go | |
| download | thehouseoficarus-9eb5ab1818b6b19501fd7209db1987c9e06cc919.tar.gz | |
first commit
Diffstat (limited to 'internal/world/mob.go')
| -rw-r--r-- | internal/world/mob.go | 181 |
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, + } + } +} |
