aboutsummaryrefslogtreecommitdiff
path: root/internal/world
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-01 19:41:34 -0400
committerhistoria <[not public]>2026-07-01 19:41:34 -0400
commit8eec7b75ff9c8c368b252373db45fb891732d2ca (patch)
tree528ab3f235e3082a51b8bd6c8e5ae269c41b4f2b /internal/world
parent78b522d57a9ebc691e075523910d7cdaa06b6493 (diff)
downloadthehouseoficarus-8eec7b75ff9c8c368b252373db45fb891732d2ca.tar.gz
mob combat stats overhauled and standardized
Diffstat (limited to 'internal/world')
-rw-r--r--internal/world/mob.go263
1 files changed, 179 insertions, 84 deletions
diff --git a/internal/world/mob.go b/internal/world/mob.go
index 58bf769..19ec935 100644
--- a/internal/world/mob.go
+++ b/internal/world/mob.go
@@ -17,55 +17,75 @@ type MobDropTable struct {
Loot []behavior.DropEntry `yaml:"loot"`
}
+type MobSteal struct {
+ Table string `yaml:"table"`
+ Level int `yaml:"level"`
+ XP int `yaml:"xp"`
+ Speed float64 `yaml:"speed"`
+}
+
+type MobTask struct {
+ Verb string `yaml:"verb"`
+ ProgressNoun string `yaml:"progress_noun"`
+ CompleteMessage string `yaml:"complete_message"`
+}
+
+type MobCombatBonuses struct {
+ AttackBonus int `yaml:"attack_bonus"`
+ StrengthBonus int `yaml:"strength_bonus"`
+ ScienceBonus int `yaml:"science_bonus"`
+ SciencePercentBonus int `yaml:"science_percent_bonus"`
+ RangedBonus int `yaml:"ranged_bonus"`
+ RangedStrengthBonus int `yaml:"ranged_strength_bonus"`
+}
+
+type MobCombatDefenses struct {
+ StabDefense int `yaml:"stab_defense"`
+ SlashDefense int `yaml:"slash_defense"`
+ CrushDefense int `yaml:"crush_defense"`
+ ScienceDefense int `yaml:"science_defense"`
+ RangedDefense int `yaml:"ranged_defense"`
+ Weakness string `yaml:"weakness"`
+}
+
+type MobCombatStats struct {
+ HP int `yaml:"hp"`
+ Attack int `yaml:"attack"`
+ Strength int `yaml:"strength"`
+ Defense int `yaml:"defense"`
+ Ranged int `yaml:"ranged"`
+ Science int `yaml:"science"`
+ AttackType string `yaml:"attack_type"`
+ Speed float64 `yaml:"speed"`
+ Aggressive bool `yaml:"aggressive"`
+ RespawnTicks float64 `yaml:"respawn_ticks"`
+ Bonuses MobCombatBonuses `yaml:"bonuses"`
+ Defenses MobCombatDefenses `yaml:"defenses"`
+}
+
+type MobCombat struct {
+ Kind string `yaml:"kind"`
+ Stats MobCombatStats `yaml:"stats"`
+ AssassinLevel int `yaml:"assassin_level"`
+ FinishingBlow string `yaml:"finishing_blow"`
+ DamageWithout string `yaml:"damage_without"`
+ Size string `yaml:"size"`
+ CombatDescriptions []string `yaml:"combat_descriptions"`
+}
+
type MobDef struct {
- 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"`
- Ranged int `yaml:"ranged"`
- Science int `yaml:"science"`
- Speed float64 `yaml:"speed"`
- Aggressive bool `yaml:"aggressive"`
- Protected bool `yaml:"protected"`
- Unique bool `yaml:"unique"`
- RespawnTicks float64 `yaml:"respawn_ticks"`
- Drops MobDropTable `yaml:"drops"`
-
- AttackBonus int `yaml:"attack_bonus"`
- StrengthBonus int `yaml:"strength_bonus"`
- AttackType string `yaml:"attack_type"`
-
- StabDefense int `yaml:"stab_defense"`
- SlashDefense int `yaml:"slash_defense"`
- CrushDefense int `yaml:"crush_defense"`
- ScienceDefense int `yaml:"science_defense"`
- RangedDefense int `yaml:"ranged_defense"`
-
- Weakness string `yaml:"weakness"`
- StealTable string `yaml:"steal_table"`
- StealLevel int `yaml:"steal_level"`
- StealXP int `yaml:"steal_xp"`
- StealSpeed float64 `yaml:"steal_speed"`
-
- AssassinLevel int `yaml:"assassin_level"`
- FinishingBlow string `yaml:"finishing_blow"`
- DamageWithout string `yaml:"damage_without"`
- Size string `yaml:"size"`
-
- // Kind discriminates a normal combat mob ("" or "combat") from a "task"
- // worksite (build a solar panel, survey a rock, etc.). A task mob reuses the
- // entire combat engine but its HP drains to 0 to COMPLETE the work; it never
- // attacks back (the room hazard, if any, supplies the danger). The progress
- // bar is displayed inverted (filling toward 100%).
- Kind string `yaml:"kind"`
- Verb string `yaml:"verb"` // flavor verb for messages (default "work")
- ProgressNoun string `yaml:"progress_noun"` // flavor noun, e.g. "construction"
- CompleteMessage string `yaml:"complete_message"` // shown on completion
+ ID string `yaml:"id"`
+ Name string `yaml:"name"`
+ Description string `yaml:"description"`
+ IdleDescriptions []string `yaml:"idle_descriptions"`
+ Protected bool `yaml:"protected"`
+ Unique bool `yaml:"unique"`
+ Drops MobDropTable `yaml:"drops"`
+
+ Steal *MobSteal `yaml:"steal,omitempty"`
+ Task *MobTask `yaml:"task,omitempty"`
+
+ Combat *MobCombat `yaml:"combat,omitempty"`
Talk *behavior.TalkConfig `yaml:"talk,omitempty"`
Shop *behavior.ShopConfig `yaml:"shop,omitempty"`
@@ -75,7 +95,7 @@ func (d *MobDef) IsTalkable() bool { return d.Talk != nil }
func (d *MobDef) HasShop() bool { return d.Shop != nil }
-func (d *MobDef) IsTask() bool { return d.Kind == "task" }
+func (d *MobDef) IsTask() bool { return d.Combat != nil && d.Combat.Kind == "task" }
type MobInstance struct {
InstanceID string
@@ -97,11 +117,12 @@ type MobInstance struct {
RoomID int
HomeRoomID int
Drops MobDropTable
- IdleDescription string
- WanderRooms []int
- WanderInterval float64
- WanderTickCounter int
- regenerateTick int
+ IdleDescription string
+ CombatDescriptions []string
+ WanderRooms []int
+ WanderInterval float64
+ WanderTickCounter int
+ regenerateTick int
AttackBonus int
StrengthBonus int
@@ -154,7 +175,80 @@ func (m *MobInstance) HasShop() bool { return m.Shop != nil }
func (m *MobInstance) IsTask() bool { return m.Kind == "task" }
func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []int, wanderInterval float64) *MobInstance {
- hp := def.HP
+ hp := 0
+ attack := 0
+ strength := 0
+ defense := 0
+ ranged := 0
+ science := 0
+ speed := 0.0
+ aggressive := false
+ respawnTicks := 0.0
+ attackBonus := 0
+ strengthBonus := 0
+ attackType := ""
+ stabDef := 0
+ slashDef := 0
+ crushDef := 0
+ scienceDef := 0
+ rangedDef := 0
+ weakness := ""
+ assassinLevel := 0
+ finishingBlow := ""
+ damageWithout := ""
+ size := ""
+ kind := ""
+ verb := ""
+ progressNoun := ""
+ completeMessage := ""
+ var combatDescriptions []string
+ stealTable := ""
+ stealLevel := 0
+ stealXP := 0
+ stealSpeed := 0.0
+
+ if def.Combat != nil {
+ cs := def.Combat.Stats
+ hp = cs.HP
+ attack = cs.Attack
+ strength = cs.Strength
+ defense = cs.Defense
+ ranged = cs.Ranged
+ science = cs.Science
+ speed = cs.Speed
+ aggressive = cs.Aggressive
+ respawnTicks = cs.RespawnTicks
+ attackBonus = cs.Bonuses.AttackBonus
+ strengthBonus = cs.Bonuses.StrengthBonus
+ attackType = cs.AttackType
+ stabDef = cs.Defenses.StabDefense
+ slashDef = cs.Defenses.SlashDefense
+ crushDef = cs.Defenses.CrushDefense
+ scienceDef = cs.Defenses.ScienceDefense
+ rangedDef = cs.Defenses.RangedDefense
+ weakness = cs.Defenses.Weakness
+
+ assassinLevel = def.Combat.AssassinLevel
+ finishingBlow = def.Combat.FinishingBlow
+ damageWithout = def.Combat.DamageWithout
+ size = def.Combat.Size
+ kind = def.Combat.Kind
+ combatDescriptions = def.Combat.CombatDescriptions
+ }
+
+ if def.Steal != nil {
+ stealTable = def.Steal.Table
+ stealLevel = def.Steal.Level
+ stealXP = def.Steal.XP
+ stealSpeed = def.Steal.Speed
+ }
+
+ if def.Task != nil {
+ verb = def.Task.Verb
+ progressNoun = def.Task.ProgressNoun
+ completeMessage = def.Task.CompleteMessage
+ }
+
if def.Protected && hp <= 0 {
hp = 1
}
@@ -165,42 +259,43 @@ func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []in
Description: def.Description,
HP: hp,
MaxHP: hp,
- Attack: def.Attack,
- Strength: def.Strength,
- Defense: def.Defense,
- Ranged: def.Ranged,
- Science: def.Science,
- Speed: def.Speed,
- Aggressive: def.Aggressive,
+ Attack: attack,
+ Strength: strength,
+ Defense: defense,
+ Ranged: ranged,
+ Science: science,
+ Speed: speed,
+ Aggressive: aggressive,
Protected: def.Protected,
Unique: def.Unique,
- RespawnTicks: def.RespawnTicks,
+ RespawnTicks: respawnTicks,
RoomID: roomID,
HomeRoomID: roomID,
WanderRooms: wanderRooms,
WanderInterval: wanderInterval,
Drops: def.Drops,
- AttackBonus: def.AttackBonus,
- StrengthBonus: def.StrengthBonus,
- AttackType: def.AttackType,
- StabDefense: def.StabDefense,
- SlashDefense: def.SlashDefense,
- CrushDefense: def.CrushDefense,
- ScienceDefense: def.ScienceDefense,
- RangedDefense: def.RangedDefense,
- Weakness: def.Weakness,
- StealTable: def.StealTable,
- StealLevel: def.StealLevel,
- StealXP: def.StealXP,
- StealSpeed: def.StealSpeed,
- AssassinLevel: def.AssassinLevel,
- FinishingBlow: def.FinishingBlow,
- DamageWithout: def.DamageWithout,
- Size: def.Size,
- Kind: def.Kind,
- Verb: def.Verb,
- ProgressNoun: def.ProgressNoun,
- CompleteMessage: def.CompleteMessage,
+ AttackBonus: attackBonus,
+ StrengthBonus: strengthBonus,
+ AttackType: attackType,
+ StabDefense: stabDef,
+ SlashDefense: slashDef,
+ CrushDefense: crushDef,
+ ScienceDefense: scienceDef,
+ RangedDefense: rangedDef,
+ Weakness: weakness,
+ StealTable: stealTable,
+ StealLevel: stealLevel,
+ StealXP: stealXP,
+ StealSpeed: stealSpeed,
+ AssassinLevel: assassinLevel,
+ FinishingBlow: finishingBlow,
+ DamageWithout: damageWithout,
+ Size: size,
+ Kind: kind,
+ Verb: verb,
+ ProgressNoun: progressNoun,
+ CompleteMessage: completeMessage,
+ CombatDescriptions: combatDescriptions,
TalkConfig: def.Talk,
}
if def.Shop != nil {