aboutsummaryrefslogtreecommitdiff
path: root/internal/combat/state.go
blob: 8e4c68dbd0ca477959ab239734e616cdb17007ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package combat

import "sync"

// State captures a single player's active combat engagement.
type State struct {
	PlayerName         string
	MobID              string
	Active             bool
	DamageWarningShown bool
}

// 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),
	}
}

// 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,
	}
	t.mobTargets[mobID] = 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(t.mobTargets, state.MobID)
	delete(t.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]
}

// 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
}

// 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]
}