Multiplayer step B: every player order is a command (dig, build, cast, hand, orders) and the simulation runs in fixed 50 ms steps, so single player and a match take the same path
This commit is contained in:
1 parent
d6bcce3a76
commit
1ec7492189
8 files changed
+635
-101
No files matched your search
+33
-29
@@ -3,6 +3,7 @@
|
||||
mod audio;
|
||||
mod campaign;
|
||||
mod cloud;
|
||||
mod commands;
|
||||
mod demo;
|
||||
mod dwarves;
|
||||
mod fog;
|
||||
@@ -35,10 +36,11 @@ mod wilds;
|
||||
mod xm;
|
||||
|
||||
use cloud::{Cloud, CloudEvent};
|
||||
use commands::Act;
|
||||
use game::{Game, Msg};
|
||||
use gfx::Gfx;
|
||||
use macroquad::prelude::*;
|
||||
use map::{idx, inb, mh, mw};
|
||||
use map::{inb, mh, mw};
|
||||
use menu::{Menu, MenuAction, Page};
|
||||
use render3d::{Cam, Overlay, R3d};
|
||||
use settings::{bindable_keys, Action, Settings};
|
||||
@@ -110,27 +112,32 @@ fn world_action(app: &mut App, ui: &mut Ui, r3d: &R3d, inp: &mut Input, mx: f32,
|
||||
(Tool::Dig | Tool::Room(_) | Tool::Sell | Tool::Bridge | Tool::Steel, Some(t)) => inp.ldown = Some(t),
|
||||
(Tool::Hand, _) => {
|
||||
let j = r3d.pick_ent(&app.game, &app.cam, mx, my, false);
|
||||
let Some(j) = j else { return };
|
||||
let (id, hero, dwarf) = (app.game.ents[j].id, app.game.ents[j].hero, app.game.ents[j].dwarf());
|
||||
if dwarf {
|
||||
return;
|
||||
}
|
||||
if slap {
|
||||
let kind = app.game.slap(j);
|
||||
if kind > 0 {
|
||||
ui.hand_anim = Some((kind, now));
|
||||
}
|
||||
// the punch/backhand animation at the pointer starts at once, the order follows at the next step
|
||||
ui.hand_anim = Some((if hero { 2 } else { 1 }, now));
|
||||
app.game.queue(Act::Slap { ent: id });
|
||||
} else {
|
||||
app.game.pickup(j);
|
||||
app.game.queue(Act::Pickup { ent: id });
|
||||
}
|
||||
}
|
||||
(Tool::Flag, Some((x, z))) => app.game.set_flag(x, z),
|
||||
(Tool::Lightning, _) => app.game.lightning(wx, wy),
|
||||
(Tool::Heal, _) => app.game.heal(wx, wy),
|
||||
(Tool::Summon, _) => app.game.summon(wx, wy),
|
||||
(Tool::Tower(k), Some((x, z))) => app.game.build_tower(k, x, z),
|
||||
(Tool::Trap(k), Some((x, z))) => app.game.place_trap(k, x, z),
|
||||
(Tool::Spell(sp), _) => app.game.cast(sp, wx, wy),
|
||||
(Tool::Flag, Some((x, z))) => app.game.queue(Act::Flag { x, y: z }),
|
||||
(Tool::Lightning, _) => app.game.queue(Act::Lightning { x: wx, y: wy }),
|
||||
(Tool::Heal, _) => app.game.queue(Act::Heal { x: wx, y: wy }),
|
||||
(Tool::Summon, _) => app.game.queue(Act::Summon { x: wx, y: wy }),
|
||||
(Tool::Tower(k), Some((x, z))) => app.game.queue(Act::Tower { kind: k, x, y: z }),
|
||||
(Tool::Trap(k), Some((x, z))) => app.game.queue(Act::Trap { kind: k, x, y: z }),
|
||||
(Tool::Spell(sp), _) => app.game.queue(Act::Cast { spell: sp, x: wx, y: wy }),
|
||||
(Tool::Order(0), _) => {
|
||||
let j = r3d.pick_ent(&app.game, &app.cam, mx, my, false);
|
||||
app.game.order_attack(j, wx, wy);
|
||||
let ent = j.filter(|&j| j < app.game.ents.len()).map(|j| app.game.ents[j].id);
|
||||
app.game.queue(Act::Attack { ent, x: wx, y: wy });
|
||||
}
|
||||
(Tool::Order(_), Some((x, z))) => app.game.order_guard(x, z),
|
||||
(Tool::Order(_), Some((x, z))) => app.game.queue(Act::Guard { x, y: z }),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -139,15 +146,13 @@ fn world_action(app: &mut App, ui: &mut Ui, r3d: &R3d, inp: &mut Input, mx: f32,
|
||||
fn finish_rect(app: &mut App, tool: Tool, start: (i32, i32), mx: f32, my: f32) {
|
||||
let Some((ex, ey)) = tool_tile(&app.cam, &app.game.map, tool, mx, my) else { return };
|
||||
let (sx, sy) = start;
|
||||
let r = commands::Rect::new(sx, sy, ex, ey);
|
||||
match tool {
|
||||
Tool::Dig => {
|
||||
let on = !app.game.map.t[idx(sx, sy)].marked;
|
||||
app.game.mark_rect(sx, sy, ex, ey, on);
|
||||
}
|
||||
Tool::Room(r) => app.game.build_rect(r, sx, sy, ex, ey),
|
||||
Tool::Sell => app.game.sell_rect(sx, sy, ex, ey),
|
||||
Tool::Bridge => app.game.build_bridges(sx, sy, ex, ey),
|
||||
Tool::Steel => app.game.build_steel(sx, sy, ex, ey),
|
||||
Tool::Dig => app.game.queue(Act::Dig(r)),
|
||||
Tool::Room(room) => app.game.queue(Act::Room { room: room as u8, r }),
|
||||
Tool::Sell => app.game.queue(Act::Sell(r)),
|
||||
Tool::Bridge => app.game.queue(Act::Bridge(r)),
|
||||
Tool::Steel => app.game.queue(Act::Steel(r)),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
@@ -731,9 +736,9 @@ async fn main() {
|
||||
if inp.ldown.is_some() {
|
||||
inp.ldown = None;
|
||||
} else if app.game.hand.is_empty() && matches!(ui.tool, Tool::Order(_)) {
|
||||
app.game.cancel_orders();
|
||||
app.game.queue(Act::CancelOrders);
|
||||
} else {
|
||||
app.game.drop(wx, wy);
|
||||
app.game.queue(Act::Drop { x: wx, y: wy });
|
||||
}
|
||||
}
|
||||
inp.rdown = None;
|
||||
@@ -929,7 +934,7 @@ async fn main() {
|
||||
inp.ldown = None;
|
||||
if ui.tool == Tool::Hand && !app.game.hand.is_empty() {
|
||||
let gp = app.cam.ground_point(p.x / d, p.y / d);
|
||||
app.game.drop(gp.x, gp.y);
|
||||
app.game.queue(Act::Drop { x: gp.x, y: gp.y });
|
||||
} else {
|
||||
inp.inspect = Some((p.x / d, p.y / d, now));
|
||||
}
|
||||
@@ -983,9 +988,8 @@ async fn main() {
|
||||
app.game.events.retain(|ev| ev.pos.is_none());
|
||||
}
|
||||
if playing {
|
||||
for _ in 0..(app.settings.game_speed.round().max(1.0) as usize) {
|
||||
app.game.update(dt);
|
||||
}
|
||||
// the world runs in fixed steps: the speed setting only feeds more time into them
|
||||
app.game.update(dt * app.settings.game_speed.max(1.0));
|
||||
// autosave: snapshot for leaving the tab + regular autosave
|
||||
if app.game.state == 0 {
|
||||
cache_t += dt;
|
||||
|
||||
Reference in new issue
Block a user