diff --git a/src/parser/src/e2e_test.rs b/src/parser/src/e2e_test.rs index d3b4766d..7bffadef 100644 --- a/src/parser/src/e2e_test.rs +++ b/src/parser/src/e2e_test.rs @@ -11792,47 +11792,47 @@ mod tests { let prop = ( "CCSPlayerController.m_iCompTeammateColor", PropColumn { - data: Some(I32(vec![ - Some(3), - Some(1), - Some(1), - Some(2), - Some(2), - Some(4), - Some(0), - Some(4), - Some(3), - Some(0), - Some(3), - Some(1), - Some(1), - Some(2), - Some(2), - Some(4), - Some(0), - Some(4), - Some(3), - Some(0), - Some(3), - Some(1), - Some(1), - Some(2), - Some(2), - Some(4), - Some(0), - Some(4), - Some(3), - Some(0), - Some(3), - Some(1), - Some(1), - Some(2), - Some(2), - Some(4), - Some(0), - Some(4), - Some(3), - Some(0), + data: Some(String(vec![ + Some("orange".to_string()), + Some("green".to_string()), + Some("green".to_string()), + Some("yellow".to_string()), + Some("yellow".to_string()), + Some("purple".to_string()), + Some("blue".to_string()), + Some("purple".to_string()), + Some("orange".to_string()), + Some("blue".to_string()), + Some("orange".to_string()), + Some("green".to_string()), + Some("green".to_string()), + Some("yellow".to_string()), + Some("yellow".to_string()), + Some("purple".to_string()), + Some("blue".to_string()), + Some("purple".to_string()), + Some("orange".to_string()), + Some("blue".to_string()), + Some("orange".to_string()), + Some("green".to_string()), + Some("green".to_string()), + Some("yellow".to_string()), + Some("yellow".to_string()), + Some("purple".to_string()), + Some("blue".to_string()), + Some("purple".to_string()), + Some("orange".to_string()), + Some("blue".to_string()), + Some("orange".to_string()), + Some("green".to_string()), + Some("green".to_string()), + Some("yellow".to_string()), + Some("yellow".to_string()), + Some("purple".to_string()), + Some("blue".to_string()), + Some("purple".to_string()), + Some("orange".to_string()), + Some("blue".to_string()), ])), num_nones: 0, }, @@ -15985,7 +15985,7 @@ mod tests { }, EventField { name: "hitgroup".to_string(), - data: Some(I32(1)), + data: Some(String("head".to_string())), }, EventField { name: "tick".to_string(), @@ -16091,7 +16091,7 @@ mod tests { }, EventField { name: "hitgroup".to_string(), - data: Some(I32(5)), + data: Some(String("right_arm".to_string())), }, EventField { name: "tick".to_string(), @@ -17093,7 +17093,7 @@ mod tests { }, EventField { name: "hitgroup".to_string(), - data: Some(I32(1)), + data: Some(String("head".to_string())), }, EventField { name: "tick".to_string(), @@ -17143,7 +17143,7 @@ mod tests { }, EventField { name: "hitgroup".to_string(), - data: Some(I32(2)), + data: Some(String("chest".to_string())), }, EventField { name: "tick".to_string(), diff --git a/src/parser/src/maps.rs b/src/parser/src/maps.rs index 9a2949df..24bceca4 100644 --- a/src/parser/src/maps.rs +++ b/src/parser/src/maps.rs @@ -41,6 +41,7 @@ pub static ROUND_WIN_REASON: phf::Map = phf_map! { 19_i32 => "t_planted", 20_i32 => "ct_reached_hostage", }; + pub static ROUND_WIN_REASON_TO_WINNER: phf::Map = phf_map! { 1_i32 => "T", 4_i32 => "CT", @@ -59,6 +60,119 @@ pub static ROUND_WIN_REASON_TO_WINNER: phf::Map = phf_map! { 20_i32 => "CT", }; +pub static HIT_GROUP: phf::Map = phf_map! { + 0_i32 => "generic", + 1_i32 => "head", + 2_i32 => "chest", + 3_i32 => "stomach", + 4_i32 => "left_arm", + 5_i32 => "right_arm", + 6_i32 => "left_leg", + 7_i32 => "right_leg", + 10_i32 => "gear", +}; + +pub static PLAYER_COLOR: phf::Map = phf_map! { + 0_i32 => "blue", + 1_i32 => "green", + 2_i32 => "yellow", + 3_i32 => "orange", + 4_i32 => "purple", +}; +// Found in scripts/items/items_game.txt +pub static WEAPINDICIES: phf::Map = phf_map! { + 1_u32 => "Desert Eagle", + 2_u32 => "Dual Berettas", + 3_u32 => "Five-SeveN", + 4_u32 => "Glock-18", + 7_u32 => "AK-47", + 8_u32 => "AUG", + 9_u32 => "AWP", + 10_u32 => "FAMAS", + 11_u32 => "G3SG1", + 13_u32 => "Galil AR", + 14_u32 => "M249", + 16_u32 => "M4A4", + 17_u32 => "MAC-10", + 19_u32 => "P90", + 20_u32 => "zone_repulsor", + 23_u32 => "MP5-SD", + 24_u32 => "UMP-45", + 25_u32 => "XM1014", + 26_u32 => "PP-Bizon", + 27_u32 => "MAG-7", + 28_u32 => "Negev", + 29_u32 => "Sawed-Off", + 30_u32 => "Tec-9", + 31_u32 => "Zeus x27", + 32_u32 => "P2000", + 33_u32 => "MP7", + 34_u32 => "MP9", + 35_u32 => "Nova", + 36_u32 => "P250", + 37_u32 => "shield", + 38_u32 => "Scar-20", + 39_u32 => "SG 553", + 40_u32=> "SSG 08", + 41_u32 => "knifegg", + 42_u32 => "knife", + 43_u32 => "Flashbang", + 44_u32 => "High Explosive Grenade", + 45_u32 => "Smoke Grenade", + 46_u32 => "Molotov", + 47_u32 => "Decoy Grenade", + 48_u32 => "Incendiary Grenade", + 49_u32 => "C4", + 50_u32 => "item_kevlar", + 51_u32 => "item_assaultsuit", + 52_u32 => "item_heavyassaultsuit", + 54_u32 => "item_nvg", + 55_u32 => "item_defuser", + 56_u32 => "item_cutters", + 57_u32 => "healthshot", + 58_u32 => "musickit_default", + 59_u32 => "knife_t", + 60_u32 => "M4A1-S", + 61_u32 => "USP-S", + 62_u32 => "Recipe Trade Up", + 63_u32 => "CZ75-Auto", + 64_u32 => "R8 Revolver", + 68_u32 => "tagrenade", + 69_u32 => "fists", + 70_u32 => "breachcharge", + 72_u32 => "tablet", + 74_u32 => "melee", + 75_u32 => "axe", + 76_u32 => "hammer", + 78_u32 => "spanner", + 80_u32 => "knife_ghost", + 81_u32 => "firebomb", + 82_u32 => "diversion", + 83_u32 => "frag_grenade", + 84_u32=> "snowball", + 85_u32 => "bumpmine", + 500_u32 => "bayonet", + 503_u32 => "knife_css", + 505_u32 => "knife_flip", + 506_u32 => "knife_gut", + 507_u32 => "knife_karambit", + 508_u32=> "knife_m9_bayonet", + 509_u32 => "knife_tactical", + 512_u32 => "knife_falchion", + 514_u32 => "knife_survival_bowie", + 515_u32 => "knife_butterfly", + 516_u32 => "knife_push", + 517_u32 => "knife_cord", + 518_u32 => "knife_canis", + 519_u32 => "knife_ursus", + 520_u32 => "knife_gypsy_jackknife", + 521_u32=> "knife_outdoor", + 522_u32 => "knife_stiletto", + 523_u32 => "knife_widowmaker", + 525_u32 => "knife_skeleton", + 526_u32 => "knife_kukri", +}; + pub static BASETYPE_DECODERS: phf::Map<&'static str, Decoder> = phf_map! { "bool" => BooleanDecoder, "char" => StringDecoder, @@ -541,97 +655,7 @@ pub static BUTTONMAP: phf::Map<&'static str, u64> = phf_map! { "ZOOM" => 1 << 24, "WALK" => 1 << 18, }; -pub static WANTED_CLS_NAMES: phf::Set<&'static str> = phf_set! { -"CAK47", -"CBaseCSGrenade", -"CBaseCSGrenadeProjectile", -"CBaseGrenade", -"CBasePlayerController", -"CPlayer_CameraServices", -"CBasePlayerPawn", -"CBasePlayerWeapon", -"CBRC4Target", -"CC4", -"CCSGameRules", -"CCSGameRulesProxy", -"CCSPlayer_WeaponServices", -"CCSPlayer_ObserverServices", -"CCSPlayer_UseServices", -"CCSPlayer_CameraServices", -"CCSPlayer_MovementServices", -"WeaponPurchaseCount_t", -"CCSPlayer_ActionTrackingServices", -"CCSPlayerController_InGameMoneyServices", -"CCSPlayerController_InventoryServices", -"CCSPlayerController_ActionTrackingServices", -"CCSPlayerController_DamageServices", -"CCSPlayerController", -"CCSPlayer_ItemServices", -"CCSPlayer_BulletServices", -"CCSPlayer_HostageServices", -"CCSPlayerPawn", -"CCSPlayerPawnBase", -"CCSPlayerResource", -"CCSTeam", -"CDEagle", -"CDecoyGrenade", -"CDecoyProjectile", -"CFlashbang", -"CGameRulesProxy", -"CHEGrenade", -"CIncendiaryGrenade", -"CInferno", -"CKnife", -"CKnifeGG", -"CMapVetoPickController", -"CMolotovGrenade", -"CMolotovProjectile", -"CPhysPropWeaponUpgrade", -"CPlantedC4", -"CPlantedC4Survival", -"CPlayerPing", -"CPlayerSprayDecal", -"CSensorGrenade", -"CSensorGrenadeProjectile", -"CSmokeGrenade", -"CSmokeGrenadeProjectile", -"CTeam", -"CTonemapController2", -"CVoteController", -"CWeaponAug", -"CWeaponAWP", -"CWeaponBaseItem", -"CWeaponBizon", -"CWeaponCSBase", -"CWeaponCSBaseGun", -"CWeaponElite", -"CWeaponFamas", -"CWeaponFiveSeven", -"CWeaponG3SG1", -"CWeaponGalilAR", -"CWeaponGlock", -"CWeaponHKP2000", -"CWeaponM249", -"CWeaponM4A1", -"CWeaponMAC10", -"CWeaponMag7", -"CWeaponMP7", -"CWeaponMP9", -"CWeaponNegev", -"CWeaponNOVA", -"CWeaponP250", -"CWeaponP90", -"CWeaponSawedoff", -"CWeaponSCAR20", -"CWeaponSG556", -"CWeaponShield", -"CWeaponSSG08", -"CWeaponTaser", -"CWeaponTec9", -"CWeaponUMP45", -"CWeaponXM1014", -"CWeaponZoneRepulsor", -}; + pub static AGENTSMAP: phf::Map = phf_map! { 5036_u32 => "customplayer_t_map_based", 5037_u32 => "customplayer_ct_map_based", @@ -776,99 +800,6 @@ pub static AGENTSMAP: phf::Map = phf_map! { 4781_u32 => "customplayer_tm_jungle_raider_variantf2", }; -// Found in scripts/items/items_game.txt -pub static WEAPINDICIES: phf::Map = phf_map! { - 1_u32 => "Desert Eagle", - 2_u32 => "Dual Berettas", - 3_u32 => "Five-SeveN", - 4_u32 => "Glock-18", - 7_u32 => "AK-47", - 8_u32 => "AUG", - 9_u32 => "AWP", - 10_u32 => "FAMAS", - 11_u32 => "G3SG1", - 13_u32 => "Galil AR", - 14_u32 => "M249", - 16_u32 => "M4A4", - 17_u32 => "MAC-10", - 19_u32 => "P90", - 20_u32 => "zone_repulsor", - 23_u32 => "MP5-SD", - 24_u32 => "UMP-45", - 25_u32 => "XM1014", - 26_u32 => "PP-Bizon", - 27_u32 => "MAG-7", - 28_u32 => "Negev", - 29_u32 => "Sawed-Off", - 30_u32 => "Tec-9", - 31_u32 => "Zeus x27", - 32_u32 => "P2000", - 33_u32 => "MP7", - 34_u32 => "MP9", - 35_u32 => "Nova", - 36_u32 => "P250", - 37_u32 => "shield", - 38_u32 => "Scar-20", - 39_u32 => "SG 553", - 40_u32=> "SSG 08", - 41_u32 => "knifegg", - 42_u32 => "knife", - 43_u32 => "Flashbang", - 44_u32 => "High Explosive Grenade", - 45_u32 => "Smoke Grenade", - 46_u32 => "Molotov", - 47_u32 => "Decoy Grenade", - 48_u32 => "Incendiary Grenade", - 49_u32 => "C4", - 50_u32 => "item_kevlar", - 51_u32 => "item_assaultsuit", - 52_u32 => "item_heavyassaultsuit", - 54_u32 => "item_nvg", - 55_u32 => "item_defuser", - 56_u32 => "item_cutters", - 57_u32 => "healthshot", - 58_u32 => "musickit_default", - 59_u32 => "knife_t", - 60_u32 => "M4A1-S", - 61_u32 => "USP-S", - 62_u32 => "Recipe Trade Up", - 63_u32 => "CZ75-Auto", - 64_u32 => "R8 Revolver", - 68_u32 => "tagrenade", - 69_u32 => "fists", - 70_u32 => "breachcharge", - 72_u32 => "tablet", - 74_u32 => "melee", - 75_u32 => "axe", - 76_u32 => "hammer", - 78_u32 => "spanner", - 80_u32 => "knife_ghost", - 81_u32 => "firebomb", - 82_u32 => "diversion", - 83_u32 => "frag_grenade", - 84_u32=> "snowball", - 85_u32 => "bumpmine", - 500_u32 => "bayonet", - 503_u32 => "knife_css", - 505_u32 => "knife_flip", - 506_u32 => "knife_gut", - 507_u32 => "knife_karambit", - 508_u32=> "knife_m9_bayonet", - 509_u32 => "knife_tactical", - 512_u32 => "knife_falchion", - 514_u32 => "knife_survival_bowie", - 515_u32 => "knife_butterfly", - 516_u32 => "knife_push", - 517_u32 => "knife_cord", - 518_u32 => "knife_canis", - 519_u32 => "knife_ursus", - 520_u32 => "knife_gypsy_jackknife", - 521_u32=> "knife_outdoor", - 522_u32 => "knife_stiletto", - 523_u32 => "knife_widowmaker", - 525_u32 => "knife_skeleton", - 526_u32 => "knife_kukri", -}; pub static PAINTKITS: phf::Map = phf_map! { 2_u32=>"Groundwater", 3_u32=>"CandyApple", @@ -2150,7 +2081,8 @@ pub static TYPEHM: phf::Map<&'static str, PropType> = phf_map! { "CCSPlayerController.m_szCrosshairCodes" => PropType::Controller, "CCSPlayerController.m_iPendingTeamNum" => PropType::Controller, "CCSPlayerController.m_flForceTeamTime" => PropType::Controller, - "CCSPlayerController.m_iCompTeammateColor" => PropType::Controller, + // Need to translate this one from integer + "CCSPlayerController.m_iCompTeammateColor" => PropType::Custom, "CCSPlayerController.m_bEverPlayedOnTeam" => PropType::Controller, "CCSPlayerController.m_szClan" => PropType::Controller, "CCSPlayerController.m_iCoachingTeam" => PropType::Controller, diff --git a/src/parser/src/second_pass/collect_data.rs b/src/parser/src/second_pass/collect_data.rs index 2747caf0..278fd297 100644 --- a/src/parser/src/second_pass/collect_data.rs +++ b/src/parser/src/second_pass/collect_data.rs @@ -7,6 +7,7 @@ use crate::maps::AGENTSMAP; use crate::maps::BUTTONMAP; use crate::maps::GRENADE_FRIENDLY_NAMES; use crate::maps::PAINTKITS; +use crate::maps::PLAYER_COLOR; use crate::maps::STICKER_ID_TO_NAME; use crate::maps::WEAPINDICIES; use crate::second_pass::entities::EntityType; @@ -447,6 +448,7 @@ impl<'a> SecondPassParser<'a> { "user_id" => return self.get_userid(player), "is_airborne" => self.find_is_airborne(player), "agent_skin" => return self.find_agent_skin(player), + "CCSPlayerController.m_iCompTeammateColor" => return self.find_player_color(player, prop_info), _ => Err(PropCollectionError::UnknownCustomPropName), } } @@ -458,6 +460,17 @@ impl<'a> SecondPassParser<'a> { } Err(PropCollectionError::UseridNotFound) } + pub fn find_player_color(&self, player: &PlayerMetaData, prop_info: &PropInfo) -> Result { + if let Ok(Variant::I32(v)) = self.get_controller_prop(&prop_info.id, player) { + let color = if let Some(col) = PLAYER_COLOR.get(&v) { + col.to_string() + } else { + v.to_string() + }; + return Ok(Variant::String(color)); + } + Err(PropCollectionError::UseridNotFound) + } pub fn find_is_airborne(&self, player: &PlayerMetaData) -> Result { if let Some(player_entity_id) = &player.player_entity_id { if let Some(id) = self.prop_controller.special_ids.is_airborn { diff --git a/src/parser/src/second_pass/entities.rs b/src/parser/src/second_pass/entities.rs index 61672f2c..63e89619 100644 --- a/src/parser/src/second_pass/entities.rs +++ b/src/parser/src/second_pass/entities.rs @@ -278,7 +278,7 @@ impl<'a> SecondPassParser<'a> { _entity_id: &i32, ) { if let Field::Value(_v) = field { - if _v.full_name.contains("Custom") { + if _v.full_name.contains("Punch") { println!("{:?} {:?} {:?}", field_info, _v.full_name, _result); } } diff --git a/src/parser/src/second_pass/game_events.rs b/src/parser/src/second_pass/game_events.rs index 43a1bc90..84338d5a 100644 --- a/src/parser/src/second_pass/game_events.rs +++ b/src/parser/src/second_pass/game_events.rs @@ -10,6 +10,7 @@ use crate::first_pass::read_bits::DemoParserError; use crate::first_pass::sendtables::Field; use crate::first_pass::sendtables::FieldInfo; use crate::first_pass::stringtables::UserInfo; +use crate::maps::HIT_GROUP; use crate::maps::ROUND_WIN_REASON; use crate::maps::ROUND_WIN_REASON_TO_WINNER; use crate::maps::WEAPINDICIES; @@ -115,15 +116,30 @@ impl<'a> SecondPassParser<'a> { event_fields.extend(self.find_extra(&event_fields)?); // Remove fields that user does nothing with like userid and user_pawn event_fields.retain(|ref x| !INTERNALEVENTFIELDS.contains(&x.name.as_str())); - let event = GameEvent { + let mut event = GameEvent { fields: event_fields, name: event_desc.name().to_string(), tick: self.tick, }; + self.cleanups(&mut event); self.game_events.push(event); } Ok(None) } + fn cleanups(&self, event: &mut GameEvent) { + // Contains some fixed like renaming weapons to be consitent. + for field in &mut event.fields { + if field.name == "hitgroup" { + if let Some(Variant::I32(i)) = field.data { + if let Some(str) = HIT_GROUP.get(&i) { + field.data = Some(Variant::String(str.to_string())) + } else { + field.data = Some(Variant::String(i.to_string())) + } + } + } + } + } pub fn resolve_wrong_order_event(&mut self, events: &mut Vec) -> Result<(), DemoParserError> { for event in events { event.fields.extend(self.find_extra(&event.fields)?);