Files
Catacombs/entity/monster.go
tolelom 7f29995833 feat: add secret rooms and mini-bosses on floors 4/9/14/19
Add RoomSecret (5% chance) and RoomMiniBoss room types. Add 4 mini-boss
monsters at 60% of boss stats (Guardian's Herald, Warden's Shadow,
Overlord's Lieutenant, Archlich's Harbinger) with IsMiniBoss flag and
boss pattern logic. Secret rooms grant double treasure. Mini-boss rooms
are placed on floors 4/9/14/19 at room index 1.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 15:30:21 +09:00

111 lines
2.6 KiB
Go

package entity
import "math"
type MonsterType int
const (
MonsterSlime MonsterType = iota
MonsterSkeleton
MonsterOrc
MonsterDarkKnight
MonsterBoss5
MonsterBoss10
MonsterBoss15
MonsterBoss20
MonsterMiniBoss5
MonsterMiniBoss10
MonsterMiniBoss15
MonsterMiniBoss20
)
type monsterBase struct {
Name string
HP, ATK, DEF int
MinFloor int
IsBoss bool
}
var monsterDefs = map[MonsterType]monsterBase{
MonsterSlime: {"Slime", 20, 5, 1, 1, false},
MonsterSkeleton: {"Skeleton", 35, 10, 4, 3, false},
MonsterOrc: {"Orc", 55, 14, 6, 6, false},
MonsterDarkKnight: {"Dark Knight", 80, 18, 10, 12, false},
MonsterBoss5: {"Guardian", 150, 15, 8, 5, true},
MonsterBoss10: {"Warden", 250, 22, 12, 10, true},
MonsterBoss15: {"Overlord", 400, 30, 16, 15, true},
MonsterBoss20: {"Archlich", 600, 40, 20, 20, true},
MonsterMiniBoss5: {"Guardian's Herald", 90, 9, 5, 4, false},
MonsterMiniBoss10: {"Warden's Shadow", 150, 13, 7, 9, false},
MonsterMiniBoss15: {"Overlord's Lieutenant", 240, 18, 10, 14, false},
MonsterMiniBoss20: {"Archlich's Harbinger", 360, 24, 12, 19, false},
}
type BossPattern int
const (
PatternNone BossPattern = iota
PatternAoE // every 3 turns AoE
PatternPoison // applies poison
PatternBurn // applies burn to random player
PatternHeal // heals self
PatternFreeze // applies freeze to all players
)
type Monster struct {
Name string
Type MonsterType
HP, MaxHP int
ATK, DEF int
IsBoss bool
IsMiniBoss bool
IsElite bool
ElitePrefix ElitePrefixType
TauntTarget bool
TauntTurns int
Pattern BossPattern
}
func NewMonster(mt MonsterType, floor int, scaling float64) *Monster {
base := monsterDefs[mt]
isMiniBoss := mt == MonsterMiniBoss5 || mt == MonsterMiniBoss10 ||
mt == MonsterMiniBoss15 || mt == MonsterMiniBoss20
scale := 1.0
if !base.IsBoss && !isMiniBoss && floor > base.MinFloor {
scale = math.Pow(scaling, float64(floor-base.MinFloor))
}
hp := int(math.Round(float64(base.HP) * scale))
atk := int(math.Round(float64(base.ATK) * scale))
def := int(math.Round(float64(base.DEF) * scale))
return &Monster{
Name: base.Name,
Type: mt,
HP: hp,
MaxHP: hp,
ATK: atk,
DEF: def,
IsBoss: base.IsBoss,
IsMiniBoss: isMiniBoss,
}
}
func (m *Monster) TakeDamage(dmg int) {
m.HP -= dmg
if m.HP < 0 {
m.HP = 0
}
}
func (m *Monster) IsDead() bool {
return m.HP <= 0
}
func (m *Monster) TickTaunt() {
if m.TauntTurns > 0 {
m.TauntTurns--
if m.TauntTurns == 0 {
m.TauntTarget = false
}
}
}