d2_stampede/
combat_log.rs

1use crate::proto::{CMsgDotaCombatLogEntry, DotaCombatlogTypes};
2use crate::string_table::StringTable;
3
4/// Wrapper for [`CMsgDotaCombatLogEntry`]
5#[derive(Clone)]
6pub struct CombatLogEntry<'a> {
7    pub(crate) names: &'a StringTable,
8    pub(crate) log: CMsgDotaCombatLogEntry,
9}
10
11#[derive(thiserror::Error, Debug)]
12pub enum CombatLogError {
13    #[error("No {0} for {1}")]
14    EmptyProperty(String, String),
15    #[error("No {0} for {1}")]
16    EmptyName(String, String),
17}
18
19macro_rules! define_combat_log_getters {
20    ($($name:ident: $type:ty),*) => {
21        $(
22            pub fn $name(&self) -> Result<$type, CombatLogError> {
23                self.log.$name.ok_or_else(|| {
24                    CombatLogError::EmptyProperty(stringify!($name).into(), format!("{:?}", self.r#type()))
25                })
26            }
27        )*
28    };
29}
30
31macro_rules! define_name_getter {
32    ($($fn_name:ident: $log_prop:ident),*) => {
33        $(
34            pub fn $fn_name(&self) -> Result<&str, CombatLogError> {
35                self.log.$log_prop
36                    .and_then(|id| self.names.items.get(id as usize).map(|name| name.key.as_ref()))
37                    .ok_or_else(|| {
38                        CombatLogError::EmptyName(stringify!($fn_name).into(), format!("{:?}", self.r#type()))
39                    })
40            }
41        )*
42    };
43}
44
45impl<'a> CombatLogEntry<'a> {
46    pub fn r#type(&self) -> DotaCombatlogTypes {
47        self.log.r#type()
48    }
49
50    pub fn assist_players(&self) -> &[i32] {
51        self.log.assist_players.as_slice()
52    }
53
54    define_name_getter! {
55        target_name: target_name,
56        target_source_name: target_source_name,
57        attacker_name: attacker_name,
58        damage_source_name: damage_source_name,
59        inflictor_name: inflictor_name,
60        value_name: value
61    }
62
63    define_combat_log_getters! {
64        value: u32,
65        health: i32,
66        timestamp: f32,
67        stun_duration: f32,
68        slow_duration: f32,
69        ability_level: u32,
70        location_x: f32,
71        location_y: f32,
72        gold_reason: u32,
73        timestamp_raw: f32,
74        modifier_duration: f32,
75        xp_reason: u32,
76        last_hits: u32,
77        attacker_team: u32,
78        target_team: u32,
79        obs_wards_placed: u32,
80        assist_player0: u32,
81        assist_player1: u32,
82        assist_player2: u32,
83        assist_player3: u32,
84        stack_count: u32,
85        hidden_modifier: bool,
86        neutral_camp_type: u32,
87        rune_type: u32,
88        attacker_hero_level: u32,
89        target_hero_level: u32,
90        xpm: u32,
91        gpm: u32,
92        event_location: u32,
93        target_is_self: bool,
94        damage_type: u32,
95        invisibility_modifier: bool,
96        damage_category: u32,
97        networth: u32,
98        building_type: u32,
99        modifier_elapsed_duration: f32,
100        silence_modifier: bool,
101        heal_from_lifesteal: bool,
102        modifier_purged: bool,
103        spell_evaded: bool,
104        motion_controller_modifier: bool,
105        long_range_kill: bool,
106        modifier_purge_ability: u32,
107        modifier_purge_npc: u32,
108        root_modifier: bool,
109        total_unit_death_count: u32,
110        aura_modifier: bool,
111        armor_debuff_modifier: bool,
112        no_physical_damage_modifier: bool,
113        modifier_ability: u32,
114        modifier_hidden: bool,
115        inflictor_is_stolen_ability: bool,
116        kill_eater_event: u32,
117        unit_status_label: u32,
118        spell_generated_attack: bool,
119        is_attacker_illusion: bool,
120        is_attacker_hero: bool,
121        is_target_illusion: bool,
122        is_target_hero: bool,
123        is_visible_radiant: bool,
124        is_visible_dire: bool,
125        is_ability_toggle_on: bool,
126        is_ability_toggle_off: bool,
127        is_heal_save: bool,
128        is_ultimate_ability: bool,
129        uses_charges: bool,
130        will_reincarnate: bool,
131        regenerated_health: f32,
132        neutral_camp_team: u32,
133        at_night_time: bool,
134        is_target_building: bool,
135        attacker_has_scepter: bool
136    }
137}