Co-op campaign matches and command markers: mission relay, allied masters, temporary flags
This commit is contained in:
1 parent
dc22e27184
commit
5928acf7f6
12 files changed
+433
-27
No files matched your search
+74
-5
@@ -611,11 +611,43 @@ pub struct Game {
|
||||
#[serde(skip)]
|
||||
pub ai_difficulty: u8, // difficulty used when a left side becomes an AI rival
|
||||
#[serde(skip)]
|
||||
pub coop: bool, // co-op match: the playable master sides are on one side against the heroes
|
||||
#[serde(skip)]
|
||||
pub marks: Vec<Mark>, // short-lived markers for commands given by the masters
|
||||
#[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
|
||||
}
|
||||
|
||||
pub const MARK_DIG: u8 = 0;
|
||||
pub const MARK_ROOM: u8 = 1;
|
||||
pub const MARK_SELL: u8 = 2;
|
||||
pub const MARK_BRIDGE: u8 = 3;
|
||||
pub const MARK_STEEL: u8 = 4;
|
||||
pub const MARK_TOWER: u8 = 5;
|
||||
pub const MARK_TRAP: u8 = 6;
|
||||
pub const MARK_SPELL: u8 = 7;
|
||||
pub const MARK_LIGHTNING: u8 = 8;
|
||||
pub const MARK_HEAL: u8 = 9;
|
||||
pub const MARK_SUMMON: u8 = 10;
|
||||
pub const MARK_FLAG: u8 = 11;
|
||||
pub const MARK_PICKUP: u8 = 12;
|
||||
pub const MARK_DROP: u8 = 13;
|
||||
pub const MARK_SLAP: u8 = 14;
|
||||
pub const MARK_ATTACK: u8 = 15;
|
||||
pub const MARK_GUARD: u8 = 16;
|
||||
pub const MARK_CANCEL: u8 = 17;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Mark {
|
||||
pub x: f32,
|
||||
pub y: f32,
|
||||
pub kind: u8,
|
||||
pub side: u8,
|
||||
pub until: u64,
|
||||
}
|
||||
|
||||
fn hint_times() -> [f32; 32] {
|
||||
[-1000.0; 32]
|
||||
}
|
||||
@@ -794,6 +826,8 @@ impl Game {
|
||||
netplay: None,
|
||||
ai_sides: Vec::new(),
|
||||
ai_difficulty: 1,
|
||||
coop: false,
|
||||
marks: Vec::new(),
|
||||
hint_t: hint_times(),
|
||||
reserve: 0.0,
|
||||
incoming: Vec::new(),
|
||||
@@ -1237,6 +1271,9 @@ impl Game {
|
||||
std::mem::take(&mut self.pending)
|
||||
};
|
||||
self.apply_turn(&cmds, steps);
|
||||
if !self.marks.is_empty() {
|
||||
self.marks.retain(|m| self.sim_steps < m.until);
|
||||
}
|
||||
// what only the camera cares about runs in real time: it is not part of the shared state
|
||||
self.update_particles(dt);
|
||||
for f in self.fx.iter_mut() {
|
||||
@@ -1271,6 +1308,14 @@ impl Game {
|
||||
side == self.me_side || self.masters.iter().any(|m| m.side == side)
|
||||
}
|
||||
|
||||
fn is_hostile_master(&self, side: u8) -> bool {
|
||||
self.coop && Owner::MASTER_SIDES.contains(&self.me_side) && Owner::MASTER_SIDES.contains(&side)
|
||||
}
|
||||
|
||||
pub(crate) fn is_hostile(&self, e: &Ent) -> bool {
|
||||
e.alive && !e.held && e.captive == 0 && !e.chained && e.side() != self.me_side && !self.is_hostile_master(e.side())
|
||||
}
|
||||
|
||||
pub fn is_rival_side(&self, side: u8) -> bool {
|
||||
self.rivals.iter().any(|r| r.alive && r.side == side)
|
||||
}
|
||||
@@ -2316,8 +2361,9 @@ impl Game {
|
||||
let mut best = None;
|
||||
let mut bd = radius * radius;
|
||||
for o in &self.ents {
|
||||
// every other side is an enemy
|
||||
if !o.alive || o.held || o.side() == e.side() || o.captive != 0 || o.chained || o.invis > 0.0 {
|
||||
// every other side is an enemy; co-op master sides fight the heroes, not each other
|
||||
let coop_allies = self.coop && Owner::MASTER_SIDES.contains(&e.side()) && Owner::MASTER_SIDES.contains(&o.side());
|
||||
if !o.alive || o.held || o.side() == e.side() || coop_allies || o.captive != 0 || o.chained || o.invis > 0.0 {
|
||||
continue;
|
||||
}
|
||||
let d = (o.x - e.x).powi(2) + (o.y - e.y).powi(2);
|
||||
@@ -2789,8 +2835,9 @@ impl Game {
|
||||
self.contested.iter_mut().for_each(|c| *c = false);
|
||||
}
|
||||
for e in &self.ents {
|
||||
// any enemy of the player (heroes and the rivals' units) keeps ground from being claimed
|
||||
if !e.alive || e.held || e.captive != 0 || e.side() == 0 {
|
||||
// any enemy of the player (heroes and the rivals' units) keeps ground from being claimed.
|
||||
// In co-op matches, allied master sides do not block the player's own ground claims.
|
||||
if !e.alive || e.held || e.captive != 0 || e.side() == 0 || (self.coop && Owner::MASTER_SIDES.contains(&e.side())) {
|
||||
continue;
|
||||
}
|
||||
let (x, y) = (e.x as i32, e.y as i32);
|
||||
@@ -3788,6 +3835,21 @@ impl Game {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add_mark(&mut self, x: f32, y: f32, kind: u8, side: u8, duration: f32) {
|
||||
if duration <= 0.0 || !x.is_finite() || !y.is_finite() {
|
||||
return;
|
||||
}
|
||||
let until = self.sim_steps + (duration / STEP).ceil() as u64;
|
||||
if let Some(m) = self.marks.iter_mut().find(|m| (m.x - x).abs() < 0.75 && (m.y - y).abs() < 0.75 && m.kind == kind && m.side == side) {
|
||||
m.until = m.until.max(until);
|
||||
return;
|
||||
}
|
||||
if self.marks.len() >= 80 {
|
||||
self.marks.remove(0);
|
||||
}
|
||||
self.marks.push(Mark { x, y, kind, side, until });
|
||||
}
|
||||
|
||||
fn creature_choose(&mut self, e: &mut Ent) {
|
||||
let me = e.id + 1;
|
||||
let cur = e.tile();
|
||||
@@ -4928,7 +4990,14 @@ impl Game {
|
||||
|
||||
// a unit the tower shoots at
|
||||
fn tower_enemy(&self, t: &Tower, e: &Ent) -> bool {
|
||||
e.captive == 0 && !e.chained && if t.hero { e.side() != 1 } else { e.side() != 0 }
|
||||
let target = if t.hero {
|
||||
e.side() != 1
|
||||
} else if self.coop {
|
||||
e.side() == 1
|
||||
} else {
|
||||
e.side() != 0
|
||||
};
|
||||
e.captive == 0 && !e.chained && target
|
||||
}
|
||||
|
||||
// a hero attacks a tower; false = tower gone or unreachable
|
||||
|
||||
Reference in new issue
Block a user