You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
131 lines
4.4 KiB
Go
131 lines
4.4 KiB
Go
package model
|
|
|
|
// EnemyType names an archetype family (legacy consts for tuning / combat branches).
|
|
type EnemyType string
|
|
|
|
const (
|
|
EnemyWolf EnemyType = "wolf"
|
|
EnemyBoar EnemyType = "boar"
|
|
EnemyZombie EnemyType = "zombie"
|
|
EnemySpider EnemyType = "spider"
|
|
EnemyOrc EnemyType = "orc"
|
|
EnemySkeletonArcher EnemyType = "skeleton_archer"
|
|
EnemyBattleLizard EnemyType = "battle_lizard"
|
|
EnemyFireDemon EnemyType = "fire_demon"
|
|
EnemyIceGuardian EnemyType = "ice_guardian"
|
|
EnemySkeletonKing EnemyType = "skeleton_king"
|
|
EnemyWaterElement EnemyType = "water_element"
|
|
EnemyForestWarden EnemyType = "forest_warden"
|
|
EnemyLightningTitan EnemyType = "lightning_titan"
|
|
)
|
|
|
|
type SpecialAbility string
|
|
|
|
const (
|
|
AbilityBurn SpecialAbility = "burn"
|
|
AbilitySlow SpecialAbility = "slow"
|
|
AbilityCritical SpecialAbility = "critical"
|
|
AbilityPoison SpecialAbility = "poison"
|
|
AbilityFreeze SpecialAbility = "freeze"
|
|
AbilityIceSlow SpecialAbility = "ice_slow"
|
|
AbilityStun SpecialAbility = "stun"
|
|
AbilityDodge SpecialAbility = "dodge"
|
|
AbilityRegen SpecialAbility = "regen"
|
|
AbilityBurst SpecialAbility = "burst"
|
|
AbilityChainLightning SpecialAbility = "chain_lightning"
|
|
AbilitySummon SpecialAbility = "summon"
|
|
)
|
|
|
|
// Enemy is a DB template row or a runtime-scaled instance.
|
|
// Slug is the unique `enemies.type` column (JSON "type" for API — visual key).
|
|
// Archetype groups templates for quests and some combat logic.
|
|
type Enemy struct {
|
|
ID int64 `json:"id"`
|
|
Slug string `json:"type"` // DB `type` — unique template key
|
|
Archetype string `json:"archetype"`
|
|
Biome string `json:"biome,omitempty"` // canonical world band id (e.g. meadow, forest)
|
|
Name string `json:"name"`
|
|
HP int `json:"hp"`
|
|
MaxHP int `json:"maxHp"`
|
|
Attack int `json:"attack"`
|
|
Defense int `json:"defense"`
|
|
Speed float64 `json:"speed"`
|
|
CritChance float64 `json:"critChance"`
|
|
MinLevel int `json:"minLevel"`
|
|
MaxLevel int `json:"maxLevel"`
|
|
BaseLevel int `json:"baseLevel"`
|
|
LevelVariance float64 `json:"levelVariance"`
|
|
MaxHeroLevelDiff int `json:"maxHeroLevelDiff"`
|
|
HPPerLevel float64 `json:"hpPerLevel"`
|
|
AttackPerLevel float64 `json:"attackPerLevel"`
|
|
DefensePerLevel float64 `json:"defensePerLevel"`
|
|
XPPerLevel float64 `json:"xpPerLevel"`
|
|
GoldPerLevel float64 `json:"goldPerLevel"`
|
|
Level int `json:"level,omitempty"`
|
|
XPReward int64 `json:"xpReward"`
|
|
GoldReward int64 `json:"goldReward"`
|
|
SpecialAbilities []SpecialAbility `json:"specialAbilities,omitempty"`
|
|
IsElite bool `json:"isElite"`
|
|
AttackCount int `json:"-"`
|
|
}
|
|
|
|
func (e *Enemy) IsAlive() bool {
|
|
return e.HP > 0
|
|
}
|
|
|
|
func (e *Enemy) HasAbility(a SpecialAbility) bool {
|
|
for _, ab := range e.SpecialAbilities {
|
|
if ab == a {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// EnemyTemplates is all rows loaded from DB (order undefined).
|
|
var EnemyTemplates []Enemy
|
|
|
|
var enemyTemplatesBySlug map[string]Enemy
|
|
|
|
// SetEnemyTemplates replaces global templates and rebuilds slug index.
|
|
func SetEnemyTemplates(next []Enemy) {
|
|
EnemyTemplates = next
|
|
m := make(map[string]Enemy, len(next))
|
|
for _, e := range next {
|
|
if e.Slug != "" {
|
|
m[e.Slug] = e
|
|
}
|
|
}
|
|
enemyTemplatesBySlug = m
|
|
}
|
|
|
|
// EnemyBySlug returns a template by DB `type` (slug).
|
|
func EnemyBySlug(slug string) (Enemy, bool) {
|
|
if enemyTemplatesBySlug == nil {
|
|
return Enemy{}, false
|
|
}
|
|
e, ok := enemyTemplatesBySlug[slug]
|
|
return e, ok
|
|
}
|
|
|
|
// TemplatesByArchetype returns templates with the given archetype.
|
|
func TemplatesByArchetype(archetype string) []Enemy {
|
|
var out []Enemy
|
|
for _, e := range EnemyTemplates {
|
|
if e.Archetype == archetype {
|
|
out = append(out, e)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
// FirstTemplateByArchetype returns one template for archetype-keyed logic (e.g. loot/sim).
|
|
func FirstTemplateByArchetype(archetype string) (Enemy, bool) {
|
|
for _, e := range EnemyTemplates {
|
|
if e.Archetype == archetype {
|
|
return e, true
|
|
}
|
|
}
|
|
return Enemy{}, false
|
|
}
|