aboutsummaryrefslogtreecommitdiff
path: root/internal/game/safespot_manager.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-24 22:55:35 -0400
committerhistoria <[not public]>2026-06-24 22:55:35 -0400
commit15b7e221b799ef107dec44ecdb294026dfd3d059 (patch)
tree3748e464a77f0f082bea1567e9d6990052054961 /internal/game/safespot_manager.go
parent9d4b799db4868bcab291b83599ff088763cd4ed6 (diff)
downloadthehouseoficarus-15b7e221b799ef107dec44ecdb294026dfd3d059.tar.gz
refactor: pulled techs out to yaml files, unified numerous combat functions, broke up game object
Diffstat (limited to 'internal/game/safespot_manager.go')
-rw-r--r--internal/game/safespot_manager.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/internal/game/safespot_manager.go b/internal/game/safespot_manager.go
new file mode 100644
index 0000000..1520bc7
--- /dev/null
+++ b/internal/game/safespot_manager.go
@@ -0,0 +1,85 @@
+package game
+
+import "sync"
+
+// SafespotState tracks a player's active safespot (cover) in a room.
+type SafespotState struct {
+ Active bool
+ ObjectDefID string
+ ObjectIndex int
+ RoomID int
+ HideCountdown int
+}
+
+// SafespotManager owns the per-player safespot state map and its mutex.
+// Callers receive value copies via Get/Peek so they cannot mutate state
+// outside the lock — this avoids the lock-copy-pointer-unlock anti-pattern.
+type SafespotManager struct {
+ mu sync.Mutex
+ states map[string]*SafespotState
+}
+
+func NewSafespotManager() *SafespotManager {
+ return &SafespotManager{states: make(map[string]*SafespotState)}
+}
+
+// Get returns a value copy of the player's safespot state.
+func (m *SafespotManager) Get(name string) (SafespotState, bool) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ ss, ok := m.states[name]
+ if !ok {
+ return SafespotState{}, false
+ }
+ return *ss, true
+}
+
+// Has reports whether any safespot state exists for the player.
+func (m *SafespotManager) Has(name string) bool {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ _, ok := m.states[name]
+ return ok
+}
+
+// IsActive reports whether the player has an active, fully-hidden safespot
+// (hide countdown complete).
+func (m *SafespotManager) IsActive(name string) bool {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ ss, ok := m.states[name]
+ return ok && ss.Active && ss.HideCountdown <= 0
+}
+
+// Set stores a safespot state for the player.
+func (m *SafespotManager) Set(name string, ss SafespotState) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ m.states[name] = &ss
+}
+
+// Delete removes the player's safespot state. Returns true if a state existed.
+func (m *SafespotManager) Delete(name string) bool {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ _, ok := m.states[name]
+ delete(m.states, name)
+ return ok
+}
+
+// DecrementHideCountdown decrements the hide countdown for a player who is
+// transitioning from hiding to hidden. Returns (newCountdown, ok). A return of
+// ok=true with newCountdown > 0 means the player is still counting down;
+// newCountdown == 0 means the safespot just activated.
+func (m *SafespotManager) DecrementHideCountdown(name string) (int, bool) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ ss, ok := m.states[name]
+ if !ok || !ss.Active {
+ return 0, false
+ }
+ if ss.HideCountdown > 0 {
+ ss.HideCountdown--
+ }
+ return ss.HideCountdown, true
+}