From abd612c15799f604e671e83dc7c410ed2b44185f Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Thu, 25 Jun 2026 15:40:48 -0400 Subject: slop refactor --- internal/combat/doc.go | 4 +++ internal/combat/state.go | 79 +++++++++++++++++++++++++++++------------------- 2 files changed, 52 insertions(+), 31 deletions(-) create mode 100644 internal/combat/doc.go (limited to 'internal/combat') diff --git a/internal/combat/doc.go b/internal/combat/doc.go new file mode 100644 index 0000000..aac6f32 --- /dev/null +++ b/internal/combat/doc.go @@ -0,0 +1,4 @@ +// Package combat tracks in-progress combat engagements (one player per mob) +// and provides the classic attack-roll, hit-chance, and damage formulas. The +// Tracker struct replaces the previous package-level globals. +package combat diff --git a/internal/combat/state.go b/internal/combat/state.go index 7a4f24c..8e4c68d 100644 --- a/internal/combat/state.go +++ b/internal/combat/state.go @@ -2,56 +2,73 @@ package combat import "sync" +// State captures a single player's active combat engagement. type State struct { - PlayerName string - MobID string - Active bool + PlayerName string + MobID string + Active bool DamageWarningShown bool } -var ( - mu sync.Mutex - combatants = make(map[string]*State) // player name -> state - mobTargets = make(map[string]string) // mob ID -> player name -) +// Tracker holds all in-progress combat engagements. One player fights one mob +// at a time; one mob is fought by one player at a time (the IsMobInCombat lock +// is reused by task/labor mobs too). Safe for concurrent use. +type Tracker struct { + mu sync.Mutex + combatants map[string]*State // player name -> state + mobTargets map[string]string // mob instance ID -> player name +} + +// NewTracker returns an empty combat tracker. +func NewTracker() *Tracker { + return &Tracker{ + combatants: make(map[string]*State), + mobTargets: make(map[string]string), + } +} -func EnterCombat(playerName, mobID string) { - mu.Lock() - defer mu.Unlock() - combatants[playerName] = &State{ +// Enter records that playerName is now fighting mobID. +func (t *Tracker) Enter(playerName, mobID string) { + t.mu.Lock() + defer t.mu.Unlock() + t.combatants[playerName] = &State{ PlayerName: playerName, MobID: mobID, Active: true, } - mobTargets[mobID] = playerName + t.mobTargets[mobID] = playerName } -func LeaveCombat(playerName string) { - mu.Lock() - defer mu.Unlock() - state, ok := combatants[playerName] +// Leave ends playerName's combat, freeing their target mob. +func (t *Tracker) Leave(playerName string) { + t.mu.Lock() + defer t.mu.Unlock() + state, ok := t.combatants[playerName] if !ok { return } - delete(mobTargets, state.MobID) - delete(combatants, playerName) + delete(t.mobTargets, state.MobID) + delete(t.combatants, playerName) } -func GetCombat(playerName string) *State { - mu.Lock() - defer mu.Unlock() - return combatants[playerName] +// Get returns the player's combat state, or nil if not in combat. +func (t *Tracker) Get(playerName string) *State { + t.mu.Lock() + defer t.mu.Unlock() + return t.combatants[playerName] } -func IsMobInCombat(mobID string) bool { - mu.Lock() - defer mu.Unlock() - _, ok := mobTargets[mobID] +// IsMobInCombat reports whether the mob instance is currently engaged. +func (t *Tracker) IsMobInCombat(mobID string) bool { + t.mu.Lock() + defer t.mu.Unlock() + _, ok := t.mobTargets[mobID] return ok } -func GetMobTarget(mobID string) string { - mu.Lock() - defer mu.Unlock() - return mobTargets[mobID] +// MobTarget returns the name of the player fighting the mob, or "". +func (t *Tracker) MobTarget(mobID string) string { + t.mu.Lock() + defer t.mu.Unlock() + return t.mobTargets[mobID] } -- cgit v1.2.3