class stats

This commit is contained in:
Robin Appelman 2021-08-08 15:39:07 +02:00
commit 9c63c8b658
8 changed files with 354 additions and 8 deletions

146
src/module/classstats.rs Normal file
View file

@ -0,0 +1,146 @@
use crate::common::{Class, ClassMap, SteamId3, SubjectId};
use crate::event::{DamageEvent, GameEvent, RoleChangeEvent, SpawnEvent};
use crate::module::EventHandler;
use crate::raw_event::{RawEventType, RawSubject};
use crate::SubjectMap;
use serde::Serialize;
use std::collections::HashMap;
use std::ops::{Add, AddAssign};
#[derive(Debug, Serialize, Default, PartialEq)]
pub struct ClassStat {
kills: u8,
deaths: u8,
assists: u8,
damage: u16,
}
impl Add for ClassStat {
type Output = ClassStat;
fn add(self, rhs: Self) -> Self::Output {
ClassStat {
kills: self.kills + rhs.kills,
deaths: self.deaths + rhs.deaths,
assists: self.assists + rhs.assists,
damage: self.damage + rhs.damage,
}
}
}
impl AddAssign for ClassStat {
fn add_assign(&mut self, rhs: Self) {
self.kills += rhs.kills;
self.deaths += rhs.deaths;
self.assists += rhs.assists;
self.damage += rhs.damage;
}
}
#[derive(Default)]
pub struct ClassStatsHandler {
active: bool,
classes: HashMap<SubjectId, Class>,
stats: HashMap<SteamId3, ClassMap<ClassStat>>,
}
impl ClassStatsHandler {
fn handle_stats(&mut self, subject: SubjectId, target: &RawSubject, stats: ClassStat) {
if let Ok(target) = target.id() {
self.handle_stats_id(subject, target, stats)
}
}
fn handle_stats_id(&mut self, subject: SubjectId, target: SubjectId, stats: ClassStat) {
let subject = if let Some(steam_id) = subject.steam_id() {
steam_id
} else {
return;
};
if let Some(target_class) = self.classes.get(&target) {
self.stats.entry(SteamId3(subject)).or_default()[*target_class] += stats;
}
}
}
impl EventHandler for ClassStatsHandler {
type Output = HashMap<SteamId3, ClassMap<ClassStat>>;
fn does_handle(&self, ty: RawEventType) -> bool {
matches!(
ty,
RawEventType::Killed
| RawEventType::KillAssist
| RawEventType::Damage
| RawEventType::Spawned
| RawEventType::ChangedRole
| RawEventType::RoundWin
| RawEventType::RoundStart
)
}
fn handle(&mut self, _time: u32, subject: SubjectId, event: &GameEvent) {
match event {
GameEvent::Spawned(SpawnEvent { class: Some(class) })
| GameEvent::RoleChange(RoleChangeEvent { class: Some(class) }) => {
self.classes.insert(subject, *class);
}
GameEvent::RoundStart => {
self.active = true;
}
GameEvent::RoundWin(_) => {
self.active = false;
}
GameEvent::Kill(kill) if self.active => {
self.handle_stats(
subject,
&kill.target,
ClassStat {
kills: 1,
..Default::default()
},
);
if let Ok(target) = kill.target.id() {
self.handle_stats_id(
target,
subject,
ClassStat {
deaths: 1,
..Default::default()
},
);
}
}
GameEvent::KillAssist(kill) if self.active => {
self.handle_stats(
subject,
&kill.target,
ClassStat {
assists: 1,
..Default::default()
},
);
}
GameEvent::Damage(DamageEvent {
damage: Some(damage),
target,
..
}) if self.active => {
self.handle_stats(
subject,
target,
ClassStat {
damage: damage.get() as u16,
..Default::default()
},
);
}
_ => {}
}
}
fn finish(self, _subjects: &SubjectMap) -> Self::Output {
self.stats
}
}

View file

@ -3,6 +3,7 @@ use crate::event::GameEvent;
use crate::raw_event::RawEventType;
use crate::SubjectMap;
pub use chat::{ChatHandler, ChatMessage, ChatType};
pub use classstats::{ClassStat, ClassStatsHandler};
pub use healspread::HealSpreadHandler;
pub use lobbysettings::{
LobbySettingsError, LobbySettingsHandler, Location, Settings as LobbySettings,
@ -10,6 +11,7 @@ pub use lobbysettings::{
pub use medicstats::{MedicStats, MedicStatsHandler};
mod chat;
mod classstats;
mod healspread;
mod lobbysettings;
mod medicstats;