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

+28 -1
View File
@@ -63,8 +63,13 @@ pub struct Profile {
pub totals: BTreeMap<String, f64>,
#[serde(default)]
pub unlocked: BTreeMap<String, u64>, // achievement id ("heroes.2", "flawless") -> unix time
#[serde(default)]
pub hall: Vec<crate::names::Fallen>, // the hall of the fallen over all games (newest last)
}
// the hall of the fallen keeps this many
pub const HALL_MAX: usize = 200;
impl Profile {
pub fn total(&self, id: &str) -> f64 {
self.totals.get(id).copied().unwrap_or(0.0)
@@ -80,6 +85,15 @@ impl Profile {
let e = self.unlocked.entry(k.clone()).or_insert(*t);
*e = (*e).min(*t);
}
// the fallen of both, once each, in the order they fell
for f in &other.hall {
if !self.hall.iter().any(|h| h.name == f.name && h.kind == f.kind && h.when == f.when) {
self.hall.push(f.clone());
}
}
self.hall.sort_by_key(|h| h.when);
let extra = self.hall.len().saturating_sub(HALL_MAX);
self.hall.drain(..extra);
}
// unlocks what the totals have reached; returns the new ones
@@ -117,6 +131,7 @@ pub struct Context {
pub struct Tracker {
pub profile: Profile,
flushed: Vec<f32>,
hall_seen: usize, // entries of the game's hall already in the profile
last_time: f32,
ended: bool,
t: f32,
@@ -126,12 +141,13 @@ pub struct Tracker {
impl Tracker {
pub fn new(profile: Profile) -> Tracker {
Tracker { profile, flushed: vec![0.0; k::COUNTERS], last_time: 0.0, ended: false, t: 0.0, dirty: false, upload: false }
Tracker { profile, flushed: vec![0.0; k::COUNTERS], hall_seen: 0, last_time: 0.0, ended: false, t: 0.0, dirty: false, upload: false }
}
// a different game started (new, loaded): nothing of it has been counted yet
fn restart(&mut self, g: &Game) {
self.flushed = (0..k::COUNTERS).map(|i| g.stats.get(i)).collect();
self.hall_seen = g.hall.len();
self.ended = g.state != 0;
}
@@ -154,6 +170,17 @@ impl Tracker {
let played = self.t;
self.t = 0.0;
let mut new = Vec::new();
// the newly fallen go into the profile's hall
if g.hall.len() > self.hall_seen {
for f in &g.hall[self.hall_seen..] {
self.profile.hall.push(crate::names::Fallen { when: now, ..f.clone() });
}
self.hall_seen = g.hall.len();
let extra = self.profile.hall.len().saturating_sub(HALL_MAX);
self.profile.hall.drain(..extra);
self.dirty = true;
self.upload = true;
}
// the counters of the game
for i in 0..k::COUNTERS {
let cur = g.stats.get(i);