Skip to content

Commit 1ed70c5

Browse files
committed
add is_airbone prop
1 parent 8cdf50d commit 1ed70c5

File tree

5 files changed

+89
-1
lines changed

5 files changed

+89
-1
lines changed

src/parser/src/e2e_test.rs

+60
Original file line numberDiff line numberDiff line change
@@ -293,6 +293,7 @@ pub fn _create_ge_tests() {
293293
"is_alive".to_string(),
294294
"user_id".to_string(),
295295
"agent_skin".to_string(),
296+
"is_airborne".to_string(),
296297
];
297298

298299
let wanted_events = vec!["all".to_string()];
@@ -667,6 +668,7 @@ pub fn _create_tests() {
667668
"is_alive".to_string(),
668669
"user_id".to_string(),
669670
"agent_skin".to_string(),
671+
"is_airborne".to_string(),
670672
];
671673
let huf = create_huffman_lookup_table();
672674

@@ -717,6 +719,7 @@ pub fn _create_tests() {
717719
custom.insert(STEAMID_ID, "steamid");
718720
custom.insert(NAME_ID, "name");
719721
custom.insert(WEAPON_STICKERS_ID, "weapon_stickers");
722+
custom.insert(IS_AIRBORNE_ID, "is_airborne");
720723

721724
for (k, v) in d.df {
722725
if let Some(real_name) = d.prop_controller.id_to_name.get(&k) {
@@ -1032,6 +1035,7 @@ fn create_data() -> (DemoOutput, PropController, BTreeMap<String, Vec<GameEvent>
10321035
"weapon_stickers".to_string(),
10331036
"weapon_float".to_string(),
10341037
"weapon_paint_seed".to_string(),
1038+
"is_airborne".to_string(),
10351039
];
10361040

10371041
let wanted_events = vec![];
@@ -1309,6 +1313,62 @@ mod tests {
13091313
let prop_id = out.1.name_to_id[prop.0];
13101314
assert_eq!(out.0.df[&prop_id], prop.1);
13111315
}
1316+
#[test]
1317+
fn is_airborne() {
1318+
let prop = (
1319+
"is_airborne",
1320+
PropColumn {
1321+
data: Some(Bool(
1322+
[
1323+
Some(false),
1324+
Some(false),
1325+
Some(false),
1326+
Some(false),
1327+
Some(false),
1328+
Some(false),
1329+
Some(false),
1330+
Some(false),
1331+
Some(false),
1332+
Some(false),
1333+
Some(false),
1334+
Some(true),
1335+
Some(false),
1336+
Some(false),
1337+
Some(false),
1338+
Some(false),
1339+
Some(false),
1340+
Some(false),
1341+
Some(false),
1342+
Some(false),
1343+
Some(false),
1344+
Some(false),
1345+
Some(false),
1346+
Some(false),
1347+
Some(true),
1348+
Some(false),
1349+
Some(false),
1350+
Some(false),
1351+
Some(false),
1352+
Some(false),
1353+
Some(false),
1354+
Some(false),
1355+
Some(false),
1356+
Some(false),
1357+
Some(false),
1358+
Some(false),
1359+
Some(false),
1360+
Some(false),
1361+
Some(false),
1362+
Some(false),
1363+
]
1364+
.to_vec(),
1365+
)),
1366+
num_nones: 0,
1367+
},
1368+
);
1369+
assert_eq!(out.0.df[&IS_AIRBORNE_ID], prop.1);
1370+
}
1371+
13121372
#[test]
13131373
fn CCSPlayerController_m_nQuestProgressReason() {
13141374
let prop = (

src/parser/src/first_pass/prop_controller.rs

+11
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ pub const PLAYER_Y_ID: u32 = 100000017;
3636
pub const PLAYER_Z_ID: u32 = 100000018;
3737
pub const WEAPON_STICKERS_ID: u32 = 100000019;
3838
pub const INVENTORY_AS_IDS_ID: u32 = 100000020;
39+
pub const IS_AIRBORNE_ID: u32 = 100000021;
3940

4041
pub const WEAPON_SKIN_ID: u32 = 10000000;
4142
pub const WEAPON_PAINT_SEED: u32 = 10000001;
@@ -337,6 +338,15 @@ impl PropController {
337338
is_player_prop: true,
338339
});
339340
}
341+
if self.wanted_player_props.contains(&("is_airborne".to_string())) {
342+
self.prop_infos.push(PropInfo {
343+
id: IS_AIRBORNE_ID,
344+
prop_type: PropType::Custom,
345+
prop_name: "is_airborne".to_string(),
346+
prop_friendly_name: "is_airborne".to_string(),
347+
is_player_prop: true,
348+
});
349+
}
340350
self.prop_infos.push(PropInfo {
341351
id: TICK_ID,
342352
prop_type: PropType::Tick,
@@ -518,6 +528,7 @@ impl PropController {
518528
"CCSPlayerPawn.m_lifeState" => self.special_ids.life_state = Some(id),
519529
"CCSPlayerController.m_nPawnCharacterDefIndex" => self.special_ids.agent_skin_idx = Some(id),
520530
"CCSPlayerPawn.m_bInBuyZone" => self.special_ids.in_buy_zone = Some(id),
531+
"CCSPlayerPawn.m_hGroundEntity" => self.special_ids.is_airborn = Some(id),
521532
_ => {}
522533
};
523534
}

src/parser/src/maps.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -2342,7 +2342,6 @@ pub static TYPEHM: phf::Map<&'static str, PropType> = phf_map! {
23422342
"CCSPlayerPawn.m_vHeadConstraintOffset" => PropType::Player,
23432343
"CCSPlayerPawn.m_angEyeAngles" => PropType::Player,
23442344
"CCSPlayerPawn.m_fFlags" => PropType::Player,
2345-
"CCSPlayerPawn.m_hGroundEntity" => PropType::Player,
23462345
"CCSPlayerPawn.CBodyComponentBaseAnimGraph.m_flLastTeleportTime" => PropType::Player,
23472346
"CCSPlayerPawn.m_flCreateTime" => PropType::Player,
23482347
"CCSPlayerPawn.m_bClientSideRagdoll" => PropType::Player,
@@ -2409,6 +2408,7 @@ pub static TYPEHM: phf::Map<&'static str, PropType> = phf_map! {
24092408
"weapon_paint_seed" => PropType::Custom,
24102409
"weapon_float" => PropType::Custom,
24112410
"weapon_stickers" => PropType::Custom,
2411+
"is_airborne" => PropType::Custom,
24122412
// Weapon
24132413
"m_flAnimTime" => PropType::Weapon,
24142414
"m_flSimulationTime"=> PropType::Weapon,
@@ -2873,6 +2873,7 @@ pub static FRIENDLY_NAMES_MAPPING: phf::Map<&'static str, &'static str> = phf_ma
28732873
"next_primary_attack_tick_ratio"=> "m_flNextPrimaryAttackTickRatio",
28742874
"next_secondary_attack_tick" => "m_nNextSecondaryAttackTick",
28752875
"next_secondary_attack_tick_ratio"=> "m_flNextSecondaryAttackTickRatio",
2876+
"is_airborne" => "is_airborne",
28762877
};
28772878

28782879
pub static GRENADE_FRIENDLY_NAMES: phf::Map<&'static str, &'static str> = phf_map! {

src/parser/src/second_pass/collect_data.rs

+13
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ pub enum PropType {
3333
// DONT KNOW IF THESE ARE CORRECT. SEEMS TO GIVE CORRECT VALUES
3434
const CELL_BITS: i32 = 9;
3535
const MAX_COORD: f32 = (1 << 14) as f32;
36+
// https://github.com/markus-wa/demoinfocs-golang/blob/master/pkg/demoinfocs/constants/constants.go#L11
37+
const IS_AIRBORNE_CONST: u32 = 0xFFFFFF;
3638

3739
#[derive(Debug, Clone)]
3840
pub struct ProjectileRecord {
@@ -442,6 +444,7 @@ impl<'a> SecondPassParser<'a> {
442444
"entity_id" => return Ok(Variant::I32(*entity_id)),
443445
"is_alive" => return self.find_is_alive(entity_id),
444446
"user_id" => return self.get_userid(player),
447+
"is_airborne" => self.find_is_airborne(player),
445448
"agent_skin" => return self.find_agent_skin(player),
446449
_ => Err(PropCollectionError::UnknownCustomPropName),
447450
}
@@ -454,6 +457,16 @@ impl<'a> SecondPassParser<'a> {
454457
}
455458
Err(PropCollectionError::UseridNotFound)
456459
}
460+
pub fn find_is_airborne(&self, player: &PlayerMetaData) -> Result<Variant, PropCollectionError> {
461+
if let Some(player_entity_id) = &player.player_entity_id {
462+
if let Some(id) = self.prop_controller.special_ids.is_airborn {
463+
if let Ok(Variant::U32(airborn_h)) = self.get_prop_from_ent(&id, &player_entity_id) {
464+
return Ok(Variant::Bool(airborn_h == IS_AIRBORNE_CONST));
465+
}
466+
}
467+
}
468+
Ok(Variant::Bool(false))
469+
}
457470
pub fn find_skin_float(&self, player: &PlayerMetaData) -> Result<Variant, PropCollectionError> {
458471
if let Some(player_entity_id) = &player.player_entity_id {
459472
return self.find_weapon_prop(&WEAPON_FLOAT, &player_entity_id);

src/parser/src/second_pass/parser_settings.rs

+3
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ pub struct SpecialIDs {
261261
pub weapon_purchase_count: Option<u32>,
262262
pub in_buy_zone: Option<u32>,
263263
pub custom_name: Option<u32>,
264+
265+
pub is_airborn: Option<u32>,
264266
}
265267
impl SpecialIDs {
266268
pub fn new() -> Self {
@@ -308,6 +310,7 @@ impl SpecialIDs {
308310
weapon_purchase_count: None,
309311
in_buy_zone: None,
310312
custom_name: None,
313+
is_airborn: None,
311314
}
312315
}
313316
}

0 commit comments

Comments
 (0)