Multiplayer continues after a player leaves: AI side takeover, background match while menus are open, match chat, five-tile fog start

This commit is contained in:
Richard Zink committed 2026-11-04 18:07:02 +01:00
1 parent 2721638910
commit dc22e27184
11 files changed
+436 -70

No files matched your search

+12 -2
View File
@@ -607,6 +607,10 @@ pub struct Game {
#[serde(skip)]
pub netplay: Option<crate::netplay::Netplay>, // a match: turns come in, the world steps per turn
#[serde(skip)]
pub ai_sides: Vec<u8>, // match sides whose human master left: AI keeps them playing
#[serde(skip)]
pub ai_difficulty: u8, // difficulty used when a left side becomes an AI rival
#[serde(skip)]
pub hints: bool, // show hint messages (setting)
#[serde(skip, default = "hint_times")]
hint_t: [f32; 32], // last time each hint slot was shown
@@ -788,6 +792,8 @@ impl Game {
sim_steps: 0,
step_acc: 0.0,
netplay: None,
ai_sides: Vec::new(),
ai_difficulty: 1,
hint_t: hint_times(),
reserve: 0.0,
incoming: Vec::new(),
@@ -1265,6 +1271,10 @@ impl Game {
side == self.me_side || self.masters.iter().any(|m| m.side == side)
}
pub fn is_rival_side(&self, side: u8) -> bool {
self.rivals.iter().any(|r| r.alive && r.side == side)
}
fn take_active(&mut self) -> MasterState {
MasterState {
side: self.me_side,
@@ -2120,7 +2130,7 @@ impl Game {
self.demo_ai(e, dt);
} else if e.hero && e.captive != 0 {
self.captive_update(e, dt);
} else if e.rival() {
} else if self.is_rival_side(e.side) || (e.rival() && !self.is_master(e.side)) {
self.rival_ai(e, dt);
} else if e.dwarf() {
self.dwarf_ai(e, dt);
@@ -2181,7 +2191,7 @@ impl Game {
}
}
if !tile.walkable() && !(flies(e.kind) && tile.liquid()) {
if (e.hero || e.rival()) && tile.diggable() {
if (e.hero || self.is_rival_side(e.side) || (e.rival() && !self.is_master(e.side))) && tile.diggable() {
// heroes dig their way through
e.working = true;
let (tx, ty) = xy(next);