aboutsummaryrefslogtreecommitdiff
path: root/internal/world/mob.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-07-01 22:30:31 -0400
committerhistoria <[not public]>2026-07-01 22:30:31 -0400
commitc14c2e403c75a913e1a6d962fb6fe64f013adae5 (patch)
tree75070293fe2535b594ac72e501cbf08a3f1146e0 /internal/world/mob.go
parent8eec7b75ff9c8c368b252373db45fb891732d2ca (diff)
downloadthehouseoficarus-c14c2e403c75a913e1a6d962fb6fe64f013adae5.tar.gz
fix: combat formulas and mob attack types (mobs switch attack styles if safespotting)
Diffstat (limited to 'internal/world/mob.go')
-rw-r--r--internal/world/mob.go268
1 files changed, 157 insertions, 111 deletions
diff --git a/internal/world/mob.go b/internal/world/mob.go
index 19ec935..05650c0 100644
--- a/internal/world/mob.go
+++ b/internal/world/mob.go
@@ -40,47 +40,51 @@ type MobCombatBonuses struct {
}
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"`
+ 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"`
+ WeaknessPercent int `yaml:"weakness_percent"`
}
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"`
+ HP int `yaml:"hp"`
+ Attack int `yaml:"attack"`
+ Strength int `yaml:"strength"`
+ Defense int `yaml:"defense"`
+ Ranged int `yaml:"ranged"`
+ Science int `yaml:"science"`
+ Speed float64 `yaml:"speed"`
+ MaxMeleeHit int `yaml:"max_melee_hit"`
+ MaxRangedHit int `yaml:"max_ranged_hit"`
+ MaxScienceHit int `yaml:"max_science_hit"`
+ 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"`
+ Kind string `yaml:"kind"`
+ AttackTypes []string `yaml:"attack_types"`
+ Aggressive bool `yaml:"aggressive"`
+ RespawnTicks float64 `yaml:"respawn_ticks"`
+ 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"`
- Protected bool `yaml:"protected"`
- Unique bool `yaml:"unique"`
- Drops MobDropTable `yaml:"drops"`
+ 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"`
@@ -98,35 +102,39 @@ func (d *MobDef) HasShop() bool { return d.Shop != nil }
func (d *MobDef) IsTask() bool { return d.Combat != nil && d.Combat.Kind == "task" }
type MobInstance struct {
- InstanceID string
- DefID string
- Name string
- Description string
- HP int
- MaxHP int
- Attack int
- Strength int
- Defense int
- Ranged int
- Science int
- Speed float64
- Aggressive bool
- Protected bool
- Unique bool
- RespawnTicks float64
- RoomID int
- HomeRoomID int
- Drops MobDropTable
- IdleDescription string
- CombatDescriptions []string
- WanderRooms []int
- WanderInterval float64
- WanderTickCounter int
- regenerateTick int
+ InstanceID string
+ DefID string
+ Name string
+ Description string
+ HP int
+ MaxHP int
+ Attack int
+ Strength int
+ Defense int
+ Ranged int
+ Science int
+ Speed float64
+ Aggressive bool
+ Protected bool
+ Unique bool
+ RespawnTicks float64
+ RoomID int
+ HomeRoomID int
+ Drops MobDropTable
+ IdleDescription string
+ CombatDescriptions []string
+ WanderRooms []int
+ WanderInterval float64
+ WanderTickCounter int
+ regenerateTick int
AttackBonus int
StrengthBonus int
- AttackType string
+ AttackTypes []string
+
+ RangedBonus int
+ ScienceBonus int
+ SciencePercentBonus int
StabDefense int
SlashDefense int
@@ -134,11 +142,16 @@ type MobInstance struct {
ScienceDefense int
RangedDefense int
- Weakness string
- StealTable string
- StealLevel int
- StealXP int
- StealSpeed float64
+ Weakness string
+ WeaknessPercent int
+
+ MaxMeleeHit int
+ MaxRangedHit int
+ MaxScienceHit int
+ StealTable string
+ StealLevel int
+ StealXP int
+ StealSpeed float64
AssassinLevel int
FinishingBlow string
@@ -186,13 +199,20 @@ func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []in
respawnTicks := 0.0
attackBonus := 0
strengthBonus := 0
- attackType := ""
+ rangedBonus := 0
+ scienceBonus := 0
+ sciencePercentBonus := 0
+ var attackType []string
stabDef := 0
slashDef := 0
crushDef := 0
scienceDef := 0
rangedDef := 0
weakness := ""
+ weaknessPercent := 0
+ maxMeleeHit := 0
+ maxRangedHit := 0
+ maxScienceHit := 0
assassinLevel := 0
finishingBlow := ""
damageWithout := ""
@@ -208,6 +228,10 @@ func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []in
stealSpeed := 0.0
if def.Combat != nil {
+ aggressive = def.Combat.Aggressive
+ respawnTicks = def.Combat.RespawnTicks
+ attackType = append([]string(nil), def.Combat.AttackTypes...)
+
cs := def.Combat.Stats
hp = cs.HP
attack = cs.Attack
@@ -216,17 +240,21 @@ func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []in
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
+ rangedBonus = cs.Bonuses.RangedBonus
+ scienceBonus = cs.Bonuses.ScienceBonus
+ sciencePercentBonus = cs.Bonuses.SciencePercentBonus
stabDef = cs.Defenses.StabDefense
slashDef = cs.Defenses.SlashDefense
crushDef = cs.Defenses.CrushDefense
scienceDef = cs.Defenses.ScienceDefense
rangedDef = cs.Defenses.RangedDefense
weakness = cs.Defenses.Weakness
+ weaknessPercent = cs.Defenses.WeaknessPercent
+ maxMeleeHit = cs.MaxMeleeHit
+ maxRangedHit = cs.MaxRangedHit
+ maxScienceHit = cs.MaxScienceHit
assassinLevel = def.Combat.AssassinLevel
finishingBlow = def.Combat.FinishingBlow
@@ -253,50 +281,57 @@ func NewMobInstance(def *MobDef, instanceID string, roomID int, wanderRooms []in
hp = 1
}
inst := &MobInstance{
- InstanceID: instanceID,
- DefID: def.ID,
- Name: def.Name,
- Description: def.Description,
- HP: hp,
- MaxHP: hp,
- Attack: attack,
- Strength: strength,
- Defense: defense,
- Ranged: ranged,
- Science: science,
- Speed: speed,
- Aggressive: aggressive,
- Protected: def.Protected,
- Unique: def.Unique,
- RespawnTicks: respawnTicks,
- RoomID: roomID,
- HomeRoomID: roomID,
- WanderRooms: wanderRooms,
- WanderInterval: wanderInterval,
- Drops: def.Drops,
- 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,
+ InstanceID: instanceID,
+ DefID: def.ID,
+ Name: def.Name,
+ Description: def.Description,
+ HP: hp,
+ MaxHP: hp,
+ Attack: attack,
+ Strength: strength,
+ Defense: defense,
+ Ranged: ranged,
+ Science: science,
+ Speed: speed,
+ Aggressive: aggressive,
+ Protected: def.Protected,
+ Unique: def.Unique,
+ RespawnTicks: respawnTicks,
+ RoomID: roomID,
+ HomeRoomID: roomID,
+ WanderRooms: wanderRooms,
+ WanderInterval: wanderInterval,
+ Drops: def.Drops,
+ AttackBonus: attackBonus,
+ StrengthBonus: strengthBonus,
+ AttackTypes: attackType,
+ RangedBonus: rangedBonus,
+ ScienceBonus: scienceBonus,
+ SciencePercentBonus: sciencePercentBonus,
+ StabDefense: stabDef,
+ SlashDefense: slashDef,
+ CrushDefense: crushDef,
+ ScienceDefense: scienceDef,
+ RangedDefense: rangedDef,
+ Weakness: weakness,
+ WeaknessPercent: weaknessPercent,
+ MaxMeleeHit: maxMeleeHit,
+ MaxRangedHit: maxRangedHit,
+ MaxScienceHit: maxScienceHit,
+ 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 {
inst.Shop = def.Shop
@@ -434,6 +469,17 @@ func (s *MobStore) AllInstances() []*MobInstance {
return out
}
+// SetInstanceRoom updates a mob instance's room under the store lock, so it is
+// safe against concurrent readers (MobsInRoom, RemoveMobsInRoom) in other
+// goroutines.
+func (s *MobStore) SetInstanceRoom(instanceID string, roomID int) {
+ s.mu.Lock()
+ defer s.mu.Unlock()
+ if inst := s.instances[instanceID]; inst != nil {
+ inst.RoomID = roomID
+ }
+}
+
func (s *MobStore) MobsInRoom(roomID int) []*MobInstance {
s.mu.Lock()
defer s.mu.Unlock()