1
2use crate::{
3 Attributes,
4 AttributeDef,
5 EffectType,
6 HasItemDefindex,
7 KillEaterScoreType,
8 TryFromIntAttributeValue,
9};
10use crate::error::TryFromPrimitiveError;
11use num_enum::{IntoPrimitive, TryFromPrimitive};
12use serde_repr::{Deserialize_repr, Serialize_repr};
13use strum::{Display, EnumCount, EnumIter, EnumString};
14
15const STR_SCOUTS_KILLED: &str = "Strange Part: Scouts Killed";
17const STR_SNIPERS_KILLED: &str = "Strange Part: Snipers Killed";
18const STR_SOLDIERS_KILLED: &str = "Strange Part: Soldiers Killed";
19const STR_DEMOMEN_KILLED: &str = "Strange Part: Demomen Killed";
20const STR_HEAVIES_KILLED: &str = "Strange Part: Heavies Killed";
21const STR_PYROS_KILLED: &str = "Strange Part: Pyros Killed";
22const STR_SPIES_KILLED: &str = "Strange Part: Spies Killed";
23const STR_ENGINEERS_KILLED: &str = "Strange Part: Engineers Killed";
24const STR_MEDICS_KILLED: &str = "Strange Part: Medics Killed";
25const STR_BUILDINGS_DESTROYED: &str = "Strange Part: Buildings Destroyed";
26const STR_PROJECTILES_REFLECTED: &str = "Strange Part: Projectiles Reflected";
27const STR_HEADSHOT_KILLS: &str = "Strange Part: Headshot Kills";
28const STR_AIRBORNE_ENEMY_KILLS: &str = "Strange Part: Airborne Enemies Killed";
29const STR_GIB_KILLS: &str = "Strange Part: Gib Kills";
30const STR_KILLS_UNDER_A_FULL_MOON: &str = "Strange Part: Full Moon Kills";
31const STR_DOMINATIONS: &str = "Strange Part: Domination Kills";
32const STR_REVENGES: &str = "Strange Part: Revenge Kills";
33const STR_POSTHUMOUS_KILLS: &str = "Strange Part: Posthumous Kills";
34const STR_TEAMMATES_EXTINGUISHED: &str = "Strange Part: Teammates Extinguished";
35const STR_CRITICAL_KILLS: &str = "Strange Part: Critical Kills";
36const STR_KILLS_WHILE_EXPLOSIVE_JUMPING: &str = "Strange Part: Kills While Explosive Jumping";
37const STR_SAPPERS_REMOVED: &str = "Strange Part: Sappers Destroyed";
38const STR_CLOAKED_SPIES_KILLED: &str = "Strange Part: Cloaked Spies Killed";
39const STR_MEDICS_KILLED_THAT_HAVE_FULL_UBER_CHARGE: &str = "Strange Part: Medics Killed That Have Full ÜberCharge";
40const STR_ROBOTS_DESTROYED: &str = "Strange Part: Robots Destroyed";
41const STR_GIANT_ROBOTS_DESTROYED: &str = "Strange Part: Giant Robots Destroyed";
42const STR_KILLS_WHILE_LOW_HEALTH: &str = "Strange Part: Low-Health Kills";
43const STR_KILLS_DURING_HALLOWEEN: &str = "Strange Part: Halloween Kills";
44const STR_ROBOTS_KILLED_DURING_HALLOWEEN: &str = "Strange Part: Robots Destroyed During Halloween";
45const STR_DEFENDER_KILLS: &str = "Strange Part: Defender Kills";
46const STR_SUBMERGED_ENEMY_KILLS: &str = "Strange Part: Underwater Kills";
47const STR_KILLS_WHILE_INVULN_UBER_CHARGED: &str = "Strange Part: Kills While Übercharged";
48const STR_TANKS_DESTROYED: &str = "Strange Part: Tanks Destroyed";
49const STR_LONG_DISTANCE_KILLS: &str = "Strange Part: Long-Distance Kills";
50const STR_KILLS_DURING_VICTORY_TIME: &str = "Strange Part: Kills During Victory Time";
51const STR_ROBOT_SCOUTS_DESTROYED: &str = "Strange Part: Robot Scouts Destroyed";
52const STR_ROBOT_SPIES_DESTROYED: &str = "Strange Part: Robot Spies Destroyed";
53const STR_TAUNT_KILLS: &str = "Strange Part: Kills with a Taunt Attack";
54const STR_UNUSUAL_WEARING_PLAYER_KILLS: &str = "Strange Part: Unusual-Wearing Player Kills";
55const STR_BURNING_PLAYER_KILLS: &str = "Strange Part: Burning Enemy Kills";
56const STR_KILLSTREAKS_ENDED: &str = "Strange Part: Killstreaks Ended";
57const STR_FREEZECAM_TAUNT_APPEARANCES: &str = "Strange Cosmetic Part: Freezecam Taunt Appearances";
58const STR_DAMAGE_DEALT: &str = "Strange Part: Damage Dealt";
59const STR_FIRES_SURVIVED: &str = "Strange Cosmetic Part: Fires Survived";
60const STR_ALLIED_HEALING_DONE: &str = "Strange Part: Allied Healing Done";
61const STR_POINT_BLANK_KILLS: &str = "Strange Part: Point-Blank Kills";
62const STR_KILLS: &str = "Strange Cosmetic Part: Kills";
63const STR_FULL_HEALTH_KILLS: &str = "Strange Part: Full Health Kills";
64const STR_TAUNTING_PLAYER_KILLS: &str = "Strange Part: Taunting Player Kills";
65const STR_NOT_CRIT_NOR_MINI_CRIT_KILLS: &str = "Strange Part: Not Crit nor MiniCrit Kills";
66const STR_PLAYER_HITS: &str = "Strange Part: Player Hits";
67const STR_ASSISTS: &str = "Strange Cosmetic Part: Assists";
68
69#[derive(
72 Debug,
73 Clone,
74 Copy,
75 Eq,
76 PartialEq,
77 Ord,
78 PartialOrd,
79 Hash,
80 Display,
81 Serialize_repr,
82 Deserialize_repr,
83 EnumString,
84 EnumIter,
85 EnumCount,
86 TryFromPrimitive,
87 IntoPrimitive,
88)]
89#[repr(u32)]
90#[allow(missing_docs)]
91pub enum StrangePart {
92 #[strum(serialize = "Scouts Killed")]
93 ScoutsKilled = 10,
94 #[strum(serialize = "Snipers Killed")]
95 SnipersKilled = 11,
96 #[strum(serialize = "Soldiers Killed")]
97 SoldiersKilled = 12,
98 #[strum(serialize = "Demomen Killed")]
99 DemomenKilled = 13,
100 #[strum(serialize = "Heavies Killed")]
101 HeaviesKilled = 14,
102 #[strum(serialize = "Pyros Killed")]
103 PyrosKilled = 15,
104 #[strum(serialize = "Spies Killed")]
105 SpiesKilled = 16,
106 #[strum(serialize = "Engineers Killed")]
107 EngineersKilled = 17,
108 #[strum(serialize = "Medics Killed")]
109 MedicsKilled = 18,
110 #[strum(serialize = "Buildings Destroyed")]
111 BuildingsDestroyed = 19,
112 #[strum(serialize = "Projectiles Reflected")]
113 ProjectilesReflected = 20,
114 #[strum(serialize = "Headshot Kills")]
115 HeadshotKills = 21,
116 #[strum(serialize = "Airborne Enemy Kills")]
117 AirborneEnemyKills = 22,
118 #[strum(serialize = "Gib Kills")]
119 GibKills = 23,
120 #[strum(serialize = "Kills Under A Full Moon")]
121 KillsUnderAFullMoon = 27,
122 #[strum(serialize = "Dominations")]
123 Dominations = 28,
124 #[strum(serialize = "Revenges")]
125 Revenges = 30,
126 #[strum(serialize = "Posthumous Kills")]
127 PosthumousKills = 31,
128 #[strum(serialize = "Teammates Extinguished")]
129 TeammatesExtinguished = 32,
130 #[strum(serialize = "Critical Kills")]
131 CriticalKills = 33,
132 #[strum(serialize = "Kills While Explosive-Jumping")]
133 KillsWhileExplosiveJumping = 34,
134 #[strum(serialize = "Sappers Removed")]
135 SappersRemoved = 36,
136 #[strum(serialize = "Cloaked Spies Killed")]
137 CloakedSpiesKilled = 37,
138 #[strum(serialize = "Medics Killed That Have Full ÜberCharge")]
139 MedicsKilledThatHaveFullUberCharge = 38,
140 #[strum(serialize = "Robots Destroyed")]
141 RobotsDestroyed = 39,
142 #[strum(serialize = "Giant Robots Destroyed")]
143 GiantRobotsDestroyed = 40,
144 #[strum(serialize = "Kills While Low Health")]
145 KillsWhileLowHealth = 44,
146 #[strum(serialize = "Kills During Halloween")]
147 KillsDuringHalloween = 45,
148 #[strum(serialize = "Robots Killed During Halloween")]
149 RobotsKilledDuringHalloween = 46,
150 #[strum(serialize = "Defender Kills")]
151 #[serde(alias = "Defenders Killed")]
152 DefenderKills = 47,
153 #[strum(serialize = "Submerged Enemy Kills")]
154 SubmergedEnemyKills = 48,
155 #[strum(serialize = "Kills While Invuln ÜberCharged")]
156 KillsWhileInvulnUberCharged = 49,
157 #[strum(serialize = "Tanks Destroyed")]
158 TanksDestroyed = 61,
159 #[strum(serialize = "Long-Distance Kills")]
160 LongDistanceKills = 62,
161 #[strum(serialize = "Kills during Victory Time")]
162 KillsDuringVictoryTime = 67,
163 #[strum(serialize = "Robot Scouts Destroyed")]
164 RobotScoutsDestroyed = 68,
165 #[strum(serialize = "Robot Spies Destroyed")]
166 RobotSpiesDestroyed = 74,
167 #[strum(serialize = "Taunt Kills")]
168 TauntKills = 77,
169 #[strum(serialize = "Unusual-Wearing Player Kills")]
170 UnusualWearingPlayerKills = 78,
171 #[strum(serialize = "Burning Player Kills")]
172 BurningPlayerKills = 79,
173 #[strum(serialize = "Killstreaks Ended")]
174 KillstreaksEnded = 80,
175 #[strum(serialize = "Freezecam Taunt Appearances")]
176 FreezecamTauntAppearances = 81,
177 #[strum(serialize = "Damage Dealt")]
178 DamageDealt = 82,
179 #[strum(serialize = "Fires Survived")]
180 FiresSurvived = 83,
181 #[strum(serialize = "Allied Healing Done")]
182 AlliedHealingDone = 84,
183 #[strum(serialize = "Point Blank Kills")]
184 PointBlankKills = 85,
185 #[strum(serialize = "Kills")]
186 Kills = 87,
187 #[strum(serialize = "Full Health Kills")]
188 FullHealthKills = 88,
189 #[strum(serialize = "Taunting Player Kills")]
190 TauntingPlayerKills = 89,
191 #[strum(serialize = "Not Crit nor MiniCrit Kills")]
192 NotCritNorMiniCritKills = 93,
193 #[strum(serialize = "Player Hits")]
194 #[serde(alias = "Players Hit")]
195 PlayerHits = 94,
196 #[strum(serialize = "Assists")]
197 Assists = 95,
198}
199
200impl StrangePart {
201 pub fn score_type(&self) -> u32 {
203 u32::from(*self)
204 }
205
206 pub fn from_score_type(score_type: u32) -> Option<Self> {
208 Self::try_from(score_type).ok()
209 }
210
211 pub fn strange_part_name(&self) -> &'static str {
213 match self {
214 Self::ScoutsKilled => STR_SCOUTS_KILLED,
215 Self::SnipersKilled => STR_SNIPERS_KILLED,
216 Self::SoldiersKilled => STR_SOLDIERS_KILLED,
217 Self::DemomenKilled => STR_DEMOMEN_KILLED,
218 Self::HeaviesKilled => STR_HEAVIES_KILLED,
219 Self::PyrosKilled => STR_PYROS_KILLED,
220 Self::SpiesKilled => STR_SPIES_KILLED,
221 Self::EngineersKilled => STR_ENGINEERS_KILLED,
222 Self::MedicsKilled => STR_MEDICS_KILLED,
223 Self::BuildingsDestroyed => STR_BUILDINGS_DESTROYED,
224 Self::ProjectilesReflected => STR_PROJECTILES_REFLECTED,
225 Self::HeadshotKills => STR_HEADSHOT_KILLS,
226 Self::AirborneEnemyKills => STR_AIRBORNE_ENEMY_KILLS,
227 Self::GibKills => STR_GIB_KILLS,
228 Self::KillsUnderAFullMoon => STR_KILLS_UNDER_A_FULL_MOON,
229 Self::Dominations => STR_DOMINATIONS,
230 Self::Revenges => STR_REVENGES,
231 Self::PosthumousKills => STR_POSTHUMOUS_KILLS,
232 Self::TeammatesExtinguished => STR_TEAMMATES_EXTINGUISHED,
233 Self::CriticalKills => STR_CRITICAL_KILLS,
234 Self::KillsWhileExplosiveJumping => STR_KILLS_WHILE_EXPLOSIVE_JUMPING,
235 Self::SappersRemoved => STR_SAPPERS_REMOVED,
236 Self::CloakedSpiesKilled => STR_CLOAKED_SPIES_KILLED,
237 Self::MedicsKilledThatHaveFullUberCharge => STR_MEDICS_KILLED_THAT_HAVE_FULL_UBER_CHARGE,
238 Self::RobotsDestroyed => STR_ROBOTS_DESTROYED,
239 Self::GiantRobotsDestroyed => STR_GIANT_ROBOTS_DESTROYED,
240 Self::KillsWhileLowHealth => STR_KILLS_WHILE_LOW_HEALTH,
241 Self::KillsDuringHalloween => STR_KILLS_DURING_HALLOWEEN,
242 Self::RobotsKilledDuringHalloween => STR_ROBOTS_KILLED_DURING_HALLOWEEN,
243 Self::DefenderKills => STR_DEFENDER_KILLS,
244 Self::SubmergedEnemyKills => STR_SUBMERGED_ENEMY_KILLS,
245 Self::KillsWhileInvulnUberCharged => STR_KILLS_WHILE_INVULN_UBER_CHARGED,
246 Self::TanksDestroyed => STR_TANKS_DESTROYED,
247 Self::LongDistanceKills => STR_LONG_DISTANCE_KILLS,
248 Self::KillsDuringVictoryTime => STR_KILLS_DURING_VICTORY_TIME,
249 Self::RobotScoutsDestroyed => STR_ROBOT_SCOUTS_DESTROYED,
250 Self::RobotSpiesDestroyed => STR_ROBOT_SPIES_DESTROYED,
251 Self::TauntKills => STR_TAUNT_KILLS,
252 Self::UnusualWearingPlayerKills => STR_UNUSUAL_WEARING_PLAYER_KILLS,
253 Self::BurningPlayerKills => STR_BURNING_PLAYER_KILLS,
254 Self::KillstreaksEnded => STR_KILLSTREAKS_ENDED,
255 Self::FreezecamTauntAppearances => STR_FREEZECAM_TAUNT_APPEARANCES,
256 Self::DamageDealt => STR_DAMAGE_DEALT,
257 Self::FiresSurvived => STR_FIRES_SURVIVED,
258 Self::AlliedHealingDone => STR_ALLIED_HEALING_DONE,
259 Self::PointBlankKills => STR_POINT_BLANK_KILLS,
260 Self::Kills => STR_KILLS,
261 Self::FullHealthKills => STR_FULL_HEALTH_KILLS,
262 Self::TauntingPlayerKills => STR_TAUNTING_PLAYER_KILLS,
263 Self::NotCritNorMiniCritKills => STR_NOT_CRIT_NOR_MINI_CRIT_KILLS,
264 Self::PlayerHits => STR_PLAYER_HITS,
265 Self::Assists => STR_ASSISTS,
266 }
267 }
268
269 pub fn from_strange_part_name(name: &str) -> Option<StrangePart> {
271 match name {
272 STR_SCOUTS_KILLED => Some(Self::ScoutsKilled),
273 STR_SNIPERS_KILLED => Some(Self::SnipersKilled),
274 STR_SOLDIERS_KILLED => Some(Self::SoldiersKilled),
275 STR_DEMOMEN_KILLED => Some(Self::DemomenKilled),
276 STR_HEAVIES_KILLED => Some(Self::HeaviesKilled),
277 STR_PYROS_KILLED => Some(Self::PyrosKilled),
278 STR_SPIES_KILLED => Some(Self::SpiesKilled),
279 STR_ENGINEERS_KILLED => Some(Self::EngineersKilled),
280 STR_MEDICS_KILLED => Some(Self::MedicsKilled),
281 STR_BUILDINGS_DESTROYED => Some(Self::BuildingsDestroyed),
282 STR_PROJECTILES_REFLECTED => Some(Self::ProjectilesReflected),
283 STR_HEADSHOT_KILLS => Some(Self::HeadshotKills),
284 STR_AIRBORNE_ENEMY_KILLS => Some(Self::AirborneEnemyKills),
285 STR_GIB_KILLS => Some(Self::GibKills),
286 STR_KILLS_UNDER_A_FULL_MOON => Some(Self::KillsUnderAFullMoon),
287 STR_DOMINATIONS => Some(Self::Dominations),
288 STR_REVENGES => Some(Self::Revenges),
289 STR_POSTHUMOUS_KILLS => Some(Self::PosthumousKills),
290 STR_TEAMMATES_EXTINGUISHED => Some(Self::TeammatesExtinguished),
291 STR_CRITICAL_KILLS => Some(Self::CriticalKills),
292 STR_KILLS_WHILE_EXPLOSIVE_JUMPING => Some(Self::KillsWhileExplosiveJumping),
293 STR_SAPPERS_REMOVED => Some(Self::SappersRemoved),
294 STR_CLOAKED_SPIES_KILLED => Some(Self::CloakedSpiesKilled),
295 STR_MEDICS_KILLED_THAT_HAVE_FULL_UBER_CHARGE => Some(Self::MedicsKilledThatHaveFullUberCharge),
296 STR_ROBOTS_DESTROYED => Some(Self::RobotsDestroyed),
297 STR_GIANT_ROBOTS_DESTROYED => Some(Self::GiantRobotsDestroyed),
298 STR_KILLS_WHILE_LOW_HEALTH => Some(Self::KillsWhileLowHealth),
299 STR_KILLS_DURING_HALLOWEEN => Some(Self::KillsDuringHalloween),
300 STR_ROBOTS_KILLED_DURING_HALLOWEEN => Some(Self::RobotsKilledDuringHalloween),
301 STR_DEFENDER_KILLS => Some(Self::DefenderKills),
302 STR_SUBMERGED_ENEMY_KILLS => Some(Self::SubmergedEnemyKills),
303 STR_KILLS_WHILE_INVULN_UBER_CHARGED => Some(Self::KillsWhileInvulnUberCharged),
304 STR_TANKS_DESTROYED => Some(Self::TanksDestroyed),
305 STR_LONG_DISTANCE_KILLS => Some(Self::LongDistanceKills),
306 STR_KILLS_DURING_VICTORY_TIME => Some(Self::KillsDuringVictoryTime),
307 STR_ROBOT_SCOUTS_DESTROYED => Some(Self::RobotScoutsDestroyed),
308 STR_ROBOT_SPIES_DESTROYED => Some(Self::RobotSpiesDestroyed),
309 STR_TAUNT_KILLS => Some(Self::TauntKills),
310 STR_UNUSUAL_WEARING_PLAYER_KILLS => Some(Self::UnusualWearingPlayerKills),
311 STR_BURNING_PLAYER_KILLS => Some(Self::BurningPlayerKills),
312 STR_KILLSTREAKS_ENDED => Some(Self::KillstreaksEnded),
313 STR_FREEZECAM_TAUNT_APPEARANCES => Some(Self::FreezecamTauntAppearances),
314 STR_DAMAGE_DEALT => Some(Self::DamageDealt),
315 STR_FIRES_SURVIVED => Some(Self::FiresSurvived),
316 STR_ALLIED_HEALING_DONE => Some(Self::AlliedHealingDone),
317 STR_POINT_BLANK_KILLS => Some(Self::PointBlankKills),
318 STR_KILLS => Some(Self::Kills),
319 STR_FULL_HEALTH_KILLS => Some(Self::FullHealthKills),
320 STR_TAUNTING_PLAYER_KILLS => Some(Self::TauntingPlayerKills),
321 STR_NOT_CRIT_NOR_MINI_CRIT_KILLS => Some(Self::NotCritNorMiniCritKills),
322 STR_PLAYER_HITS => Some(Self::PlayerHits),
323 STR_ASSISTS => Some(Self::Assists),
324 _ => None,
325 }
326 }
327
328 pub fn is_cosmetic_part(&self) -> bool {
330 matches!(self, Self::Kills | Self::FullHealthKills | Self::Assists | Self::FreezecamTauntAppearances)
331 }
332
333 pub fn kill_eater_score_type(&self) -> Option<KillEaterScoreType> {
335 KillEaterScoreType::try_from(*self).ok()
336 }
337}
338
339impl Attributes for StrangePart {
340 const DEFINDEX: &'static [u32] = &[
341 380,
342 382,
343 384,
344 ];
345 const USES_FLOAT_VALUE: bool = true;
346 const ATTRIBUTES: &'static [AttributeDef] = &[
349 AttributeDef {
350 defindex: 380,
351 name: "kill eater user score type 1",
352 attribute_class: Some("kill_eater_user_score_type_1"),
353 description_string: None,
354 description_format: None,
355 effect_type: EffectType::Positive,
356 hidden: true,
357 stored_as_integer: false,
358 },
359 AttributeDef {
360 defindex: 382,
361 name: "kill eater user score type 2",
362 attribute_class: Some("kill_eater_user_score_type_2"),
363 description_string: None,
364 description_format: None,
365 effect_type: EffectType::Positive,
366 hidden: true,
367 stored_as_integer: false,
368 },
369 AttributeDef {
370 defindex: 384,
371 name: "kill eater user score type 3",
372 attribute_class: Some("kill_eater_user_score_type_3"),
373 description_string: None,
374 description_format: None,
375 effect_type: EffectType::Positive,
376 hidden: true,
377 stored_as_integer: false,
378 },
379 ];
380
381 fn attribute_float_value(&self) -> Option<f32> {
383 Some((*self as u32) as f32)
384 }
385}
386
387impl TryFromIntAttributeValue for StrangePart {}
388
389impl HasItemDefindex for StrangePart {
390 fn defindex(&self) -> u32 {
392 match self {
393 Self::ScoutsKilled => 6003,
394 Self::SnipersKilled => 6005,
395 Self::SoldiersKilled => 6002,
396 Self::DemomenKilled => 6001,
397 Self::HeaviesKilled => 6000,
398 Self::PyrosKilled => 6006,
399 Self::SpiesKilled => 6008,
400 Self::EngineersKilled => 6004,
401 Self::MedicsKilled => 6007,
402 Self::BuildingsDestroyed => 6009,
403 Self::ProjectilesReflected => 6010,
404 Self::HeadshotKills => 6011,
405 Self::AirborneEnemyKills => 6012,
406 Self::GibKills => 6013,
407 Self::KillsUnderAFullMoon => 6015,
408 Self::Dominations => 6016,
409 Self::Revenges => 6018,
410 Self::PosthumousKills => 6019,
411 Self::TeammatesExtinguished => 6020,
412 Self::CriticalKills => 6021,
413 Self::KillsWhileExplosiveJumping => 6022,
414 Self::SappersRemoved => 6025,
415 Self::CloakedSpiesKilled => 6024,
416 Self::MedicsKilledThatHaveFullUberCharge => 6023,
417 Self::RobotsDestroyed => 6026,
418 Self::GiantRobotsDestroyed => 6028,
419 Self::KillsWhileLowHealth => 6032,
420 Self::KillsDuringHalloween => 6033,
421 Self::RobotsKilledDuringHalloween => 6034,
422 Self::DefenderKills => 6035,
423 Self::SubmergedEnemyKills => 6036,
424 Self::KillsWhileInvulnUberCharged => 6037,
425 Self::TanksDestroyed => 6038,
426 Self::LongDistanceKills => 6039,
427 Self::KillsDuringVictoryTime => 6041,
428 Self::RobotScoutsDestroyed => 6042,
429 Self::RobotSpiesDestroyed => 6048,
430 Self::TauntKills => 6051,
431 Self::UnusualWearingPlayerKills => 6052,
432 Self::BurningPlayerKills => 6053,
433 Self::KillstreaksEnded => 6054,
434 Self::FreezecamTauntAppearances => 6055,
435 Self::DamageDealt => 6056,
436 Self::FiresSurvived => 6057,
437 Self::AlliedHealingDone => 6058,
438 Self::PointBlankKills => 6059,
439 Self::Kills => 6060,
440 Self::FullHealthKills => 6061,
441 Self::TauntingPlayerKills => 6062,
442 Self::NotCritNorMiniCritKills => 6063,
443 Self::PlayerHits => 6064,
444 Self::Assists => 6065,
445 }
446 }
447
448 fn from_defindex(defindex: u32) -> Option<Self> {
450 match defindex {
451 6003 => Some(Self::ScoutsKilled),
452 6005 => Some(Self::SnipersKilled),
453 6002 => Some(Self::SoldiersKilled),
454 6001 => Some(Self::DemomenKilled),
455 6000 => Some(Self::HeaviesKilled),
456 6006 => Some(Self::PyrosKilled),
457 6008 => Some(Self::SpiesKilled),
458 6004 => Some(Self::EngineersKilled),
459 6007 => Some(Self::MedicsKilled),
460 6009 => Some(Self::BuildingsDestroyed),
461 6010 => Some(Self::ProjectilesReflected),
462 6011 => Some(Self::HeadshotKills),
463 6012 => Some(Self::AirborneEnemyKills),
464 6013 => Some(Self::GibKills),
465 6015 => Some(Self::KillsUnderAFullMoon),
466 6016 => Some(Self::Dominations),
467 6018 => Some(Self::Revenges),
468 6019 => Some(Self::PosthumousKills),
469 6020 => Some(Self::TeammatesExtinguished),
470 6021 => Some(Self::CriticalKills),
471 6022 => Some(Self::KillsWhileExplosiveJumping),
472 6025 => Some(Self::SappersRemoved),
473 6024 => Some(Self::CloakedSpiesKilled),
474 6023 => Some(Self::MedicsKilledThatHaveFullUberCharge),
475 6026 => Some(Self::RobotsDestroyed),
476 6028 => Some(Self::GiantRobotsDestroyed),
477 6032 => Some(Self::KillsWhileLowHealth),
478 6033 => Some(Self::KillsDuringHalloween),
479 6034 => Some(Self::RobotsKilledDuringHalloween),
480 6035 => Some(Self::DefenderKills),
481 6036 => Some(Self::SubmergedEnemyKills),
482 6037 => Some(Self::KillsWhileInvulnUberCharged),
483 6038 => Some(Self::TanksDestroyed),
484 6039 => Some(Self::LongDistanceKills),
485 6041 => Some(Self::KillsDuringVictoryTime),
486 6042 => Some(Self::RobotScoutsDestroyed),
487 6048 => Some(Self::RobotSpiesDestroyed),
488 6051 => Some(Self::TauntKills),
489 6052 => Some(Self::UnusualWearingPlayerKills),
490 6053 => Some(Self::BurningPlayerKills),
491 6054 => Some(Self::KillstreaksEnded),
492 6055 => Some(Self::FreezecamTauntAppearances),
493 6056 => Some(Self::DamageDealt),
494 6057 => Some(Self::FiresSurvived),
495 6058 => Some(Self::AlliedHealingDone),
496 6059 => Some(Self::PointBlankKills),
497 6060 => Some(Self::Kills),
498 6061 => Some(Self::FullHealthKills),
499 6062 => Some(Self::TauntingPlayerKills),
500 6063 => Some(Self::NotCritNorMiniCritKills),
501 6064 => Some(Self::PlayerHits),
502 6065 => Some(Self::Assists),
503 _ => None,
504 }
505 }
506}
507
508impl TryFrom<KillEaterScoreType> for StrangePart {
509 type Error = TryFromPrimitiveError<Self>;
510
511 fn try_from(part: KillEaterScoreType) -> Result<Self, Self::Error> {
512 StrangePart::try_from(part as u32)
513 }
514}
515
516impl TryFrom<&KillEaterScoreType> for StrangePart {
517 type Error = TryFromPrimitiveError<Self>;
518
519 fn try_from(part: &KillEaterScoreType) -> Result<Self, Self::Error> {
520 StrangePart::try_from(*part as u32)
521 }
522}
523
524#[cfg(test)]
525mod tests {
526 use super::*;
527 use std::str::FromStr;
528
529 #[test]
530 fn from_str_converts() {
531 assert_eq!(
532 StrangePart::MedicsKilledThatHaveFullUberCharge,
533 StrangePart::from_str("Medics Killed That Have Full ÜberCharge").unwrap()
534 );
535 }
536
537 #[test]
538 fn serializes_player_hits_correctly() {
539 let player_hits = StrangePart::PlayerHits;
540 let serialized = player_hits.to_string();
541
542 assert_eq!(serialized, "Player Hits");
543 assert_eq!(StrangePart::from_str("Player Hits").unwrap(), StrangePart::PlayerHits);
544 }
545
546 #[test]
547 fn serializes_defender_kills_correctly() {
548 let defender_kills = StrangePart::DefenderKills;
549 let serialized = defender_kills.to_string();
550
551 assert_eq!(serialized, "Defender Kills");
552 assert_eq!(StrangePart::from_str("Defender Kills").unwrap(), StrangePart::DefenderKills);
553 }
554
555 #[test]
556 fn attribute_slices_are_equal_length() {
557 assert_eq!(StrangePart::DEFINDEX.len(), StrangePart::ATTRIBUTES.len());
558 }
559}