1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
//! Bindings & utilities for any form of strikes (direct damage).
use crate::{
event::{impl_common, CommonEvent},
extract::Extract,
Event, EventCategory, TryExtract,
};
use num_enum::{FromPrimitive, IntoPrimitive};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "strum")]
use strum::{Display, EnumCount, EnumIter, IntoStaticStr, VariantNames};
/// Strike (direct damage) event.
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct StrikeEvent {
/// Common combat event information.
#[cfg_attr(feature = "serde", serde(flatten))]
pub common: CommonEvent,
/// Kind of strike.
pub strike: Strike,
/// Total damage inflicted.
pub total_damage: i32,
/// Damage inflicted to shields (barrier).
pub shield_damage: u32,
/// Whether target is currently downed.
pub target_downed: bool,
}
impl_common!(StrikeEvent);
impl Extract for StrikeEvent {
#[inline]
unsafe fn extract(event: &Event) -> Self {
Self {
common: event.into(),
strike: event.result.into(),
total_damage: event.value,
shield_damage: event.overstack_value,
target_downed: event.is_offcycle == 1,
}
}
}
impl TryExtract for StrikeEvent {
#[inline]
fn can_extract(event: &Event) -> bool {
event.categorize() == EventCategory::Strike
}
}
/// Strike types.
///
/// *Arc calls this "combat result".*
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, IntoPrimitive, FromPrimitive,
)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(
feature = "strum",
derive(Display, EnumCount, EnumIter, IntoStaticStr, VariantNames)
)]
#[repr(u8)]
pub enum Strike {
/// Normal damage strike.
///
/// No crit, no glance.
Normal = 0,
/// Strike was critical.
Crit = 1,
/// Strike was glancing.
Glance = 2,
/// Strike was blocked.
///
/// Due to Aegis, Chrono Shield 4 etc.
Block = 3,
/// Strike was evaded.
///
/// Due to dodge, Mesmer Sword 2 etc.
Evade = 4,
/// Strike interrupted something.
Interrupt = 5,
/// Strike was absorbed.
///
/// Usually due to an invulnerability like Guardian Renewed Focus.
Absorb = 6,
/// Strike missed.
///
/// Due to blind etc.
Blind = 7,
/// Skill killed the target.
///
/// Not a damage strike.
KillingBlow = 8,
/// Skill downed the target.
///
/// Not a damage strike.
Downed = 9,
/// Skill dealt breakbar damage.
///
/// Not a damage strike.
Breakbar = 10,
/// On-activation event.
///
/// Not a damage strike.
///
/// *Arc: Source hit target if damaging buff.*
Activation = 11,
/// Unknown.
#[num_enum(catch_all)]
Unknown(u8),
}
impl Strike {
/// Whether the strike dealt health damage to the target.
#[inline]
pub const fn dealt_damage(&self) -> bool {
matches!(self, Self::Normal | Self::Crit | Self::Glance)
}
}