diff options
| author | historia <[not public]> | 2026-06-09 17:15:13 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-06-09 17:15:13 -0400 |
| commit | 9edc568e16741d443b67fbd23b0d91790085ced9 (patch) | |
| tree | d54be40531ba124dcf8299f9e94bfba4ece273ae /internal/world/mob.go | |
| parent | 56be6a3f45830594225a765b406816e6179ccde1 (diff) | |
| download | thehouseoficarus-9edc568e16741d443b67fbd23b0d91790085ced9.tar.gz | |
combat, mobs, parsing, toggles, hard disconnect handling
Diffstat (limited to 'internal/world/mob.go')
| -rw-r--r-- | internal/world/mob.go | 185 |
1 files changed, 148 insertions, 37 deletions
diff --git a/internal/world/mob.go b/internal/world/mob.go index 601cdc1..ebf97cf 100644 --- a/internal/world/mob.go +++ b/internal/world/mob.go @@ -2,8 +2,10 @@ package world import ( "fmt" + "math/rand" "os" "path/filepath" + "strings" "sync" "gopkg.in/yaml.v3" @@ -21,32 +23,89 @@ type DropTable struct { } 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"` + ID string `yaml:"id"` + Name string `yaml:"name"` + Description string `yaml:"description"` + IdleDescriptions []string `yaml:"idle_descriptions"` + CombatDescriptions []string `yaml:"combat_descriptions"` + Attack int `yaml:"attack"` + Strength int `yaml:"strength"` + Defense int `yaml:"defense"` + HP int `yaml:"hp"` + Speed int `yaml:"speed"` + Aggressive bool `yaml:"aggressive"` + Protected bool `yaml:"protected"` + Unique bool `yaml:"unique"` + RespawnTicks int `yaml:"respawn_ticks"` + Wander int `yaml:"wander"` + WanderTick int `yaml:"wander_tick"` + WanderChance float64 `yaml:"wander_chance"` + 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 + InstanceID string + DefID string + Name string + HP int + MaxHP int + Attack int + Strength int + Defense int + Speed int + Aggressive bool + Protected bool + Unique bool + RespawnTicks int + RoomID int + HomeRoomID int + Drops DropTable + IdleDescription string + Wander int + WanderTick int + WanderChance float64 + WanderTickCounter int + regenerateTick int +} + +const ( + MatchNone = 0 + MatchPrefix = 1 + MatchExact = 2 +) + +func WordPrefixMatch(input, name string) bool { + lower := strings.ToLower(input) + for _, word := range strings.Fields(name) { + if strings.HasPrefix(strings.ToLower(word), lower) { + return true + } + } + return false +} + +func (m *MobInstance) MatchQuality(input string) int { + lower := strings.ToLower(input) + if strings.ToLower(m.Name) == lower { + return MatchExact + } + if WordPrefixMatch(input, m.Name) { + return MatchPrefix + } + return MatchNone +} + +func pickIdleDescription(descriptions []string) string { + if len(descriptions) == 0 { + return "" + } + return descriptions[rand.Intn(len(descriptions))] +} + +func (m *MobInstance) StartRegen() { + if m.regenerateTick == 0 { + m.regenerateTick = 100 + } } type MobStore struct { @@ -126,6 +185,16 @@ func (s *MobStore) RemoveInstance(id string) { delete(s.instances, id) } +func (s *MobStore) AllInstances() []*MobInstance { + s.mu.Lock() + defer s.mu.Unlock() + var out []*MobInstance + for _, inst := range s.instances { + out = append(out, inst) + } + return out +} + func (s *MobStore) MobsInRoom(roomID int) []*MobInstance { s.mu.Lock() defer s.mu.Unlock() @@ -138,6 +207,40 @@ func (s *MobStore) MobsInRoom(roomID int) []*MobInstance { return out } +func (s *MobStore) Tick() { + s.mu.Lock() + defer s.mu.Unlock() + + for _, inst := range s.instances { + if inst.HP <= 0 || inst.HP >= inst.MaxHP { + inst.regenerateTick = 0 + continue + } + inst.regenerateTick-- + if inst.regenerateTick <= 0 { + inst.HP++ + if inst.HP >= inst.MaxHP { + inst.HP = inst.MaxHP + inst.regenerateTick = 0 + } else { + inst.regenerateTick = 100 + } + } + } +} + +func (s *MobStore) RollIdleDescription(inst *MobInstance) { + def, err := s.LoadDef(inst.DefID) + if err != nil { + return + } + inst.IdleDescription = pickIdleDescription(def.IdleDescriptions) + inst.Wander = def.Wander + inst.WanderTick = def.WanderTick + inst.WanderChance = def.WanderChance + inst.WanderTickCounter = 0 +} + func (s *MobStore) SeedMobs(roomID int, mobIDs []string) { type defWrapper struct { def *MobDef @@ -162,20 +265,28 @@ func (s *MobStore) SeedMobs(roomID int, mobIDs []string) { _ = 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, + inst := &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, + Protected: dw.def.Protected, + Unique: dw.def.Unique, + RespawnTicks: dw.def.RespawnTicks, + Wander: dw.def.Wander, + WanderTick: dw.def.WanderTick, + WanderChance: dw.def.WanderChance, + RoomID: roomID, + HomeRoomID: roomID, + Drops: dw.def.Drops, } + inst.IdleDescription = pickIdleDescription(dw.def.IdleDescriptions) + s.instances[instID] = inst } } |
