use sdk_raw::tf2::class::{
TF_CLASS_DEMOMAN, TF_CLASS_ENGINEER, TF_CLASS_HEAVYWEAPONS, TF_CLASS_MEDIC, TF_CLASS_PYRO,
TF_CLASS_SCOUT, TF_CLASS_SNIPER, TF_CLASS_SOLDIER, TF_CLASS_SPY,
};
use std::ffi::{CStr, c_int};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum PlayerClass {
#[doc(alias("TF_CLASS_SCOUT"))]
Scout = TF_CLASS_SCOUT as isize,
#[doc(alias("TF_CLASS_SNIPER"))]
Sniper = TF_CLASS_SNIPER as isize,
#[doc(alias("TF_CLASS_SOLDIER"))]
Soldier = TF_CLASS_SOLDIER as isize,
#[doc(alias("TF_CLASS_DEMOMAN"))]
Demoman = TF_CLASS_DEMOMAN as isize,
#[doc(alias("TF_CLASS_MEDIC"))]
Medic = TF_CLASS_MEDIC as isize,
#[doc(alias("TF_CLASS_HEAVYWEAPONS"))]
Heavy = TF_CLASS_HEAVYWEAPONS as isize,
#[doc(alias("TF_CLASS_PYRO"))]
Pyro = TF_CLASS_PYRO as isize,
#[doc(alias("TF_CLASS_SPY"))]
Spy = TF_CLASS_SPY as isize,
#[doc(alias("TF_CLASS_ENGINEER"))]
Engineer = TF_CLASS_ENGINEER as isize,
}
impl PlayerClass {
pub const ALL: [Self; 9] = [
Self::Scout,
Self::Sniper,
Self::Soldier,
Self::Demoman,
Self::Medic,
Self::Heavy,
Self::Pyro,
Self::Spy,
Self::Engineer,
];
pub const fn from_raw(raw: c_int) -> Option<Self> {
match raw {
TF_CLASS_SCOUT => Some(Self::Scout),
TF_CLASS_SNIPER => Some(Self::Sniper),
TF_CLASS_SOLDIER => Some(Self::Soldier),
TF_CLASS_DEMOMAN => Some(Self::Demoman),
TF_CLASS_MEDIC => Some(Self::Medic),
TF_CLASS_HEAVYWEAPONS => Some(Self::Heavy),
TF_CLASS_PYRO => Some(Self::Pyro),
TF_CLASS_SPY => Some(Self::Spy),
TF_CLASS_ENGINEER => Some(Self::Engineer),
_ => None,
}
}
#[doc(alias("TF2_GetClass", "joinclass"))]
pub fn from_name(name: &str) -> Option<Self> {
Self::ALL.into_iter().find(|class| {
name.eq_ignore_ascii_case(class.name()) || name.eq_ignore_ascii_case(class.short_name())
})
}
#[doc(alias("g_aRawPlayerClassNames"))]
pub const fn name(self) -> &'static str {
match self {
Self::Scout => "scout",
Self::Sniper => "sniper",
Self::Soldier => "soldier",
Self::Demoman => "demoman",
Self::Medic => "medic",
Self::Heavy => "heavyweapons",
Self::Pyro => "pyro",
Self::Spy => "spy",
Self::Engineer => "engineer",
}
}
#[doc(alias("g_aRawPlayerClassNamesShort"))]
pub const fn short_name(self) -> &'static str {
match self {
Self::Demoman => "demo",
Self::Heavy => "heavy",
class => class.name(),
}
}
#[doc(alias("m_szModelName"))]
pub const fn model(self) -> &'static CStr {
match self {
Self::Scout => c"models/player/scout.mdl",
Self::Sniper => c"models/player/sniper.mdl",
Self::Soldier => c"models/player/soldier.mdl",
Self::Demoman => c"models/player/demo.mdl",
Self::Medic => c"models/player/medic.mdl",
Self::Heavy => c"models/player/heavy.mdl",
Self::Pyro => c"models/player/pyro.mdl",
Self::Spy => c"models/player/spy.mdl",
Self::Engineer => c"models/player/engineer.mdl",
}
}
pub const fn scene_directory(self) -> &'static str {
match self {
Self::Scout => "Scout",
Self::Sniper => "Sniper",
Self::Soldier => "Soldier",
Self::Demoman => "Demoman",
Self::Medic => "Medic",
Self::Heavy => "Heavy",
Self::Pyro => "Pyro",
Self::Spy => "Spy",
Self::Engineer => "Engineer",
}
}
pub const fn to_raw(self) -> c_int {
self as c_int
}
}
impl FromStr for PlayerClass {
type Err = UnknownClassName;
fn from_str(name: &str) -> Result<Self, Self::Err> {
Self::from_name(name).ok_or_else(|| UnknownClassName(name.to_owned()))
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[error("{0:?} names none of TF2's playable classes")]
pub struct UnknownClassName(pub String);