feat: multiplayer flee marks player as out for current combat
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -34,6 +34,7 @@ type Player struct {
|
||||
Inventory []Item
|
||||
Relics []Relic
|
||||
Dead bool
|
||||
Fled bool
|
||||
}
|
||||
|
||||
func NewPlayer(name string, class Class) *Player {
|
||||
@@ -67,6 +68,10 @@ func (p *Player) IsDead() bool {
|
||||
return p.Dead
|
||||
}
|
||||
|
||||
func (p *Player) IsOut() bool {
|
||||
return p.Dead || p.Fled
|
||||
}
|
||||
|
||||
func (p *Player) Revive(hpPercent float64) {
|
||||
p.Dead = false
|
||||
p.HP = int(float64(p.MaxHP) * hpPercent)
|
||||
|
||||
39
game/turn.go
39
game/turn.go
@@ -20,7 +20,7 @@ func (s *GameSession) RunTurn() {
|
||||
s.actions = make(map[string]PlayerAction)
|
||||
aliveCount := 0
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
aliveCount++
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,7 @@ resolve:
|
||||
|
||||
// Default action for players who didn't submit: Wait
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
if _, ok := s.actions[p.Name]; !ok {
|
||||
s.actions[p.Name] = PlayerAction{Type: ActionWait}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ func (s *GameSession) resolvePlayerActions() {
|
||||
}
|
||||
|
||||
for _, p := range s.state.Players {
|
||||
if p.IsDead() {
|
||||
if p.IsOut() {
|
||||
continue
|
||||
}
|
||||
action, ok := s.actions[p.Name]
|
||||
@@ -149,6 +149,7 @@ func (s *GameSession) resolvePlayerActions() {
|
||||
s.state.Phase = PhaseExploring
|
||||
return
|
||||
}
|
||||
p.Fled = true
|
||||
} else {
|
||||
s.addLog(fmt.Sprintf("%s failed to flee!", p.Name))
|
||||
}
|
||||
@@ -157,6 +158,24 @@ func (s *GameSession) resolvePlayerActions() {
|
||||
}
|
||||
}
|
||||
|
||||
// Check if all alive players have fled
|
||||
allFled := true
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() && !p.Fled {
|
||||
allFled = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if allFled && !s.state.SoloMode {
|
||||
s.state.Phase = PhaseExploring
|
||||
s.state.Floor.Rooms[s.state.Floor.CurrentRoom].Cleared = true
|
||||
s.addLog("All players fled!")
|
||||
for _, p := range s.state.Players {
|
||||
p.Fled = false
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if len(intents) > 0 && len(s.state.Monsters) > 0 {
|
||||
results := combat.ResolveAttacks(intents, s.state.Monsters)
|
||||
for i, r := range results {
|
||||
@@ -186,7 +205,7 @@ func (s *GameSession) resolvePlayerActions() {
|
||||
goldReward = 15
|
||||
}
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
bonus := 0
|
||||
for _, r := range p.Relics {
|
||||
if r.Effect == entity.RelicGoldBoost {
|
||||
@@ -220,6 +239,9 @@ func (s *GameSession) resolvePlayerActions() {
|
||||
if len(s.state.Monsters) == 0 {
|
||||
s.state.Floor.Rooms[s.state.Floor.CurrentRoom].Cleared = true
|
||||
s.addLog("Room cleared!")
|
||||
for _, p := range s.state.Players {
|
||||
p.Fled = false
|
||||
}
|
||||
if s.state.Floor.Rooms[s.state.Floor.CurrentRoom].Type == dungeon.RoomBoss {
|
||||
s.advanceFloor()
|
||||
} else {
|
||||
@@ -245,6 +267,7 @@ func (s *GameSession) advanceFloor() {
|
||||
if p.IsDead() {
|
||||
p.Revive(0.30)
|
||||
}
|
||||
p.Fled = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +279,7 @@ func (s *GameSession) grantBossRelic() {
|
||||
{Name: "Gold Charm", Effect: entity.RelicGoldBoost, Value: 5, Price: 150},
|
||||
}
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
r := relics[rand.Intn(len(relics))]
|
||||
p.Relics = append(p.Relics, r)
|
||||
s.addLog(fmt.Sprintf("%s obtained relic: %s", p.Name, r.Name))
|
||||
@@ -275,7 +298,7 @@ func (s *GameSession) resolveMonsterActions() {
|
||||
targetIdx, isAoE := combat.MonsterAI(m, s.state.Players, s.state.CombatTurn)
|
||||
if isAoE {
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
dmg := combat.CalcDamage(m.ATK, p.EffectiveDEF(), 0.5)
|
||||
p.TakeDamage(dmg)
|
||||
s.addLog(fmt.Sprintf("%s AoE hits %s for %d dmg", m.Name, p.Name, dmg))
|
||||
@@ -284,7 +307,7 @@ func (s *GameSession) resolveMonsterActions() {
|
||||
} else {
|
||||
if targetIdx >= 0 && targetIdx < len(s.state.Players) {
|
||||
p := s.state.Players[targetIdx]
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
dmg := combat.CalcDamage(m.ATK, p.EffectiveDEF(), 1.0)
|
||||
p.TakeDamage(dmg)
|
||||
s.addLog(fmt.Sprintf("%s attacks %s for %d dmg", m.Name, p.Name, dmg))
|
||||
@@ -296,7 +319,7 @@ func (s *GameSession) resolveMonsterActions() {
|
||||
|
||||
allPlayersDead := true
|
||||
for _, p := range s.state.Players {
|
||||
if !p.IsDead() {
|
||||
if !p.IsOut() {
|
||||
allPlayersDead = false
|
||||
break
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user