diff --git a/README.md b/README.md index 5b9abaa..88c6128 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,20 @@ caves, rival masters, and me, telling you the story. With tea. campaigns. *Open the demo* in the editor shows every trigger at work. Details: [docs/CAMPAIGN_EDITOR.md](docs/CAMPAIGN_EDITOR.md), [docs/MISSION_SCRIPTING.md](docs/MISSION_SCRIPTING.md). +## Together + +- **Versus** for 2-4 masters, with teams, gold for allies and fallen masters watching the rest of the match. +- **Co-op**: the 20-mission campaign *League against the Lightwatch*, the built-in missions or any editor campaign, + each master with an own dungeon; empty seats are played by the AI. Hero waves march on the strongest master. +- **Offline with an AI partner**: every co-op mission also runs without the server - the partner builds his own + dungeon, follows your attack flag and helps out with gold. Interrupted runs go on with *Continue*. + Details: [docs/MULTIPLAYER.md](docs/MULTIPLAYER.md). + +

+ The Match page with the co-op league and the AI partner + The language dropdown with pixel flags for 18 languages +

+ ## Meet the household

diff --git a/docs/screenshots/coop-league.png b/docs/screenshots/coop-league.png new file mode 100644 index 0000000..b51948c Binary files /dev/null and b/docs/screenshots/coop-league.png differ diff --git a/docs/screenshots/languages.png b/docs/screenshots/languages.png new file mode 100644 index 0000000..9327095 Binary files /dev/null and b/docs/screenshots/languages.png differ diff --git a/docs/screenshots/title-battle.png b/docs/screenshots/title-battle.png index 8361647..937f091 100644 Binary files a/docs/screenshots/title-battle.png and b/docs/screenshots/title-battle.png differ diff --git a/src/main.rs b/src/main.rs index e7a3e68..ce1011d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1894,6 +1894,7 @@ app.pending_briefing = briefing_of(&campaign, i); | Some(Page::Login) | Some(Page::Account) | Some(Page::Bestiary { from_title: true, .. }) + | Some(Page::Match { from_title: true }) ); music.update(&app.game, on_title, (app.cam.rx, app.cam.rz)); for m in app.game.msgs.drain(..) { @@ -1973,6 +1974,7 @@ fn draw_frame(app: &mut App, gfx: &Gfx, r3d: &mut R3d, ui: &mut Ui, menu: &mut M | Some(Page::Login) | Some(Page::Account) | Some(Page::Bestiary { from_title: true, .. }) + | Some(Page::Match { from_title: true }) ); if !title_screen { let info = if over_ui || (touch && inp.inspect.is_none()) { diff --git a/src/menu.rs b/src/menu.rs index 67e60c4..42f4331 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -451,8 +451,24 @@ pub struct Menu { fn button(gfx: &Gfx, r: Rect, label: &str, hot: bool, accent: Color) { draw_rectangle(r.x, r.y, r.w, r.h, if hot { Color::new(0.35, 0.22, 0.1, 1.0) } else { Color::new(0.13, 0.09, 0.08, 1.0) }); draw_rectangle_lines(r.x, r.y, r.w, r.h, 2.0, if hot { FRAME_HI } else { accent }); - let s = S(); - gfx.text(label, r.x + (r.w - gfx.measure(label, s)) * 0.5, r.y + (r.h - GH * s) * 0.5, s, if hot { FRAME_HI } else { TXT }); + // a label too wide for the button gets the small font, and is cut short if that is not enough + let mut s = S(); + let room = r.w - 8.0; + let mut text = label.to_string(); + if gfx.measure(&text, s) > room { + s = SMALL(); + while gfx.measure(&text, s) > room && text.chars().count() > 2 { + text.pop(); + while text.ends_with(' ') { + text.pop(); + } + if gfx.measure(&format!("{text}…"), s) <= room { + text.push('…'); + break; + } + } + } + gfx.text(&text, r.x + (r.w - gfx.measure(&text, s)) * 0.5, r.y + (r.h - GH * s) * 0.5, s, if hot { FRAME_HI } else { TXT }); } impl Menu { @@ -2034,7 +2050,8 @@ impl Menu { items.push((Btn::MatchLeave, tr("net.leave"))); } items.push((Btn::Back, tr("menu.back"))); - let bw = 14.0 * CW(); + // three buttons a row over the whole width + let bw = ((w - 2.0 * CW()) / 3.0).max(14.0 * CW()); let shown = items.iter().take(9).count(); for (k, (b, label)) in items.iter().take(shown).enumerate() { let r = Rect::new(ix + (k % 3) as f32 * (bw + CW()), yy + (k / 3) as f32 * CH() * 2.4, bw, CH() * 2.0);