Hall of the fallen: kills and causes of death, in the game and over all games in the profile

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Richard ZinkandClaude Opus 5.5 committed 2026-11-06 13:48:06 +01:00
1 parent 065fe80218
commit c52fc4c4ae
28 files changed
+534 -5

No files matched your search

+54 -1
View File
@@ -461,6 +461,7 @@ enum TBtn {
Learn(u8), // spend a point on a branch
OvRow(u32),
OvScroll(i32),
OvFallen, // switch the overview between the living and the fallen
GoldTo, // the next ally to receive gold
Gold(u32), // send that much gold to him
}
@@ -491,7 +492,8 @@ pub struct Ui {
pub show_talents: bool, // the master's talents
pub coop_end: Option<(bool, bool, bool)>, // end of an editor co-op mission: (host, a next mission, asked for it)
gold_to: usize, // the ally chosen in the creature overview
ov_scroll: usize,
pub ov_scroll: usize,
pub ov_fallen: bool, // the overview shows the hall of the fallen
ov_rect: Option<Rect>, // where the creature overview is (mouse wheel, swipe)
pub show_langsel: bool,
pub log: Vec<(Msg, f64)>,
@@ -603,6 +605,7 @@ impl Ui {
coop_end: None,
gold_to: 0,
ov_scroll: 0,
ov_fallen: false,
ov_rect: None,
show_langsel: false,
log: Vec::new(),
@@ -702,6 +705,11 @@ impl Ui {
UiAction::Consumed
}
TBtn::Learn(b) => UiAction::LearnTalent(b),
TBtn::OvFallen => {
self.ov_fallen = !self.ov_fallen;
self.ov_scroll = 0;
UiAction::Consumed
}
TBtn::OvScroll(d) => {
self.ov_scroll = (self.ov_scroll as i32 + d).max(0) as usize;
UiAction::Consumed
@@ -1343,6 +1351,36 @@ impl Ui {
}
}
// the hall of the fallen of this game: name, kind, level, heroes slain, how it fell
fn draw_hall(&mut self, g: &Game, gfx: &Gfx, x: f32, y: f32, cols: i32, rows: i32) {
gfx.text(&tr("hall.title"), x + CW() * 2.0, y + CH(), S(), GOLD);
let mut lines: Vec<(String, Color)> = Vec::new();
for f in g.hall.iter().rev() {
lines.push((format!("{:>2} {}", f.level, crate::names::full_name(f.kind, f.name, f.level)), FRAME_HI));
let kills = if f.kills > 0 { format!(" · {}", trf("hall.kills", &[f.kills.to_string()])) } else { String::new() };
lines.push((format!(" {} · {}{} · {}", tr(st(f.kind).name), crate::names::cause(f.bane), kills, mmss(f.time)), DIM));
}
if lines.is_empty() {
lines.push((tr("hall.empty"), DIM));
}
let first = y + CH() * 2.6;
let visible = (rows - 4).max(1) as usize;
self.ov_scroll = self.ov_scroll.min(lines.len().saturating_sub(visible));
let maxc = (cols - 4) as usize;
for (n, (text, col)) in lines.iter().enumerate().skip(self.ov_scroll).take(visible) {
let t: String = text.chars().take(maxc).collect();
gfx.text(&t, x + CW() * 2.0, first + (n - self.ov_scroll) as f32 * CH(), S(), *col);
}
if lines.len() > visible {
let up = Rect::new(x + (cols - 4) as f32 * CW(), y + CH() * 2.4, CW() * 2.0, CH() * 1.5);
let down = Rect::new(x + (cols - 4) as f32 * CW(), y + (rows - 2) as f32 * CH(), CW() * 2.0, CH() * 1.5);
gfx.text("\u{25b2}", up.x + CW() * 0.5, up.y, S(), FRAME_HI);
gfx.text("\u{25bc}", down.x + CW() * 0.5, down.y, S(), FRAME_HI);
self.touch_btns.push((up, TBtn::OvScroll(-2)));
self.touch_btns.push((down, TBtn::OvScroll(2)));
}
}
fn draw_overview(&mut self, g: &Game, gfx: &Gfx, bottom: f32) {
let (sw, _) = (sw(), sh());
let (mx, my) = mouse();
@@ -1357,6 +1395,21 @@ impl Ui {
let mine: Vec<&Ent> = g.ents.iter().filter(|e| e.alive && e.creature()).collect();
let wage: f32 = mine.iter().map(|e| st(e.kind).wage as f32 * (1.0 + 0.1 * (e.level - 1) as f32)).sum();
let mood = if mine.is_empty() { 0.0 } else { mine.iter().map(|e| e.happy.clamp(0.0, 1.0)).sum::<f32>() / mine.len() as f32 };
// the switch to the hall of the fallen (top right)
{
let label = if self.ov_fallen { tr("ov.living") } else { trf("ov.fallen", &[g.hall.len().to_string()]) };
let bw = gfx.measure(&label, SMALL()) + CW() * 2.0;
let r = Rect::new(x + (cols - 3) as f32 * CW() - bw, y + CH() * 0.8, bw, CH() * 1.4);
let hov = r.contains(vec2(mx, my));
draw_rectangle(r.x, r.y, r.w, r.h, if hov { Color::new(0.35, 0.22, 0.1, 1.0) } else { Color::new(0.15, 0.1, 0.08, 1.0) });
draw_rectangle_lines(r.x, r.y, r.w, r.h, 2.0, FRAME_HI);
gfx.text(&label, r.x + CW(), r.y + (r.h - GH * SMALL()) * 0.5, SMALL(), FRAME_HI);
self.touch_btns.push((r, TBtn::OvFallen));
}
if self.ov_fallen {
self.draw_hall(g, gfx, x, y, cols, rows);
return;
}
let head = trf("ov.summary", &[mine.len().to_string(), (wage as i32).to_string(), ((mood * 100.0) as i32).to_string()]);
gfx.text(&head, x + CW() * 2.0, y + CH(), S(), GOLD);
// a match with allies: a row to send them gold (the name switches between the allies)