feat: display turn countdown timer in combat HUD

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-24 00:53:17 +09:00
parent a1e9e0ef68
commit 7556073cb5
3 changed files with 96 additions and 32 deletions

View File

@@ -2,6 +2,7 @@ package game
import (
"sync"
"time"
"github.com/tolelom/catacombs/dungeon"
"github.com/tolelom/catacombs/entity"
@@ -43,7 +44,8 @@ type GameState struct {
GameOver bool
Victory bool
ShopItems []entity.Item
CombatLog []string // recent combat messages
CombatLog []string // recent combat messages
TurnDeadline time.Time
}
func (s *GameSession) addLog(msg string) {

View File

@@ -28,6 +28,9 @@ func (s *GameSession) RunTurn() {
// Collect actions with timeout
timer := time.NewTimer(TurnTimeout)
s.mu.Lock()
s.state.TurnDeadline = time.Now().Add(TurnTimeout)
s.mu.Unlock()
collected := 0
for collected < aliveCount {
select {
@@ -45,6 +48,7 @@ func (s *GameSession) RunTurn() {
resolve:
s.mu.Lock()
defer s.mu.Unlock()
s.state.TurnDeadline = time.Time{}
// Default action for players who didn't submit: Wait
for _, p := range s.state.Players {
@@ -71,28 +75,6 @@ func (s *GameSession) resolvePlayerActions() {
}
}
// Check if ALL alive players chose flee
fleeCount := 0
aliveCount := 0
for _, p := range s.state.Players {
if p.IsDead() {
continue
}
aliveCount++
if action, ok := s.actions[p.Name]; ok && action.Type == ActionFlee {
fleeCount++
}
}
if fleeCount == aliveCount && aliveCount > 0 {
if combat.AttemptFlee() {
s.addLog("Fled from battle!")
s.state.Phase = PhaseExploring
return
}
s.addLog("Failed to flee!")
return
}
for _, p := range s.state.Players {
if p.IsDead() {
continue
@@ -161,7 +143,15 @@ func (s *GameSession) resolvePlayerActions() {
s.addLog(fmt.Sprintf("%s has no items to use!", p.Name))
}
case ActionFlee:
s.addLog(fmt.Sprintf("%s tried to flee but party didn't agree", p.Name))
if combat.AttemptFlee() {
s.addLog(fmt.Sprintf("%s fled from battle!", p.Name))
if s.state.SoloMode {
s.state.Phase = PhaseExploring
return
}
} else {
s.addLog(fmt.Sprintf("%s failed to flee!", p.Name))
}
case ActionWait:
s.addLog(fmt.Sprintf("%s is defending", p.Name))
}