aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/analyzers/mod.rs2
-rw-r--r--src/analyzers/strikes.rs74
2 files changed, 73 insertions, 3 deletions
diff --git a/src/analyzers/mod.rs b/src/analyzers/mod.rs
index 7b375af..ba800a9 100644
--- a/src/analyzers/mod.rs
+++ b/src/analyzers/mod.rs
@@ -132,10 +132,10 @@ pub fn for_log<'l>(log: &'l Log) -> Option<Box<dyn Analyzer + 'l>> {
| Encounter::FraenirOfJormag
| Encounter::Boneskinner
| Encounter::WhisperOfJormag
- | Encounter::Ankka
| Encounter::MinisterLi
| Encounter::Dragonvoid => Some(Box::new(strikes::GenericStrike::new(log))),
Encounter::CaptainMaiTrin => Some(Box::new(strikes::CaptainMaiTrin::new(log))),
+ Encounter::Ankka => Some(Box::new(strikes::Ankka::new(log))),
}
}
diff --git a/src/analyzers/strikes.rs b/src/analyzers/strikes.rs
index e12b8da..5c43865 100644
--- a/src/analyzers/strikes.rs
+++ b/src/analyzers/strikes.rs
@@ -38,6 +38,13 @@ impl<'log> Analyzer for GenericStrike<'log> {
}
}
+/// The ID of the "Determined" buff.
+///
+/// This buff is applied to the strike mission bosses when they die instead or phase.
+///
+/// Teh chat link for this buff is `[&Bn8DAAA=]`.
+pub const DETERMINED_ID: u32 = 895;
+
/// Analyzer for the Captain Mai Trin/Aetherblade Hideout strike.
#[derive(Debug, Clone, Copy)]
pub struct CaptainMaiTrin<'log> {
@@ -46,7 +53,6 @@ pub struct CaptainMaiTrin<'log> {
impl<'log> CaptainMaiTrin<'log> {
pub const ECHO_OF_SCARLET_BRIAR: u16 = 24_768;
- pub const WINNING_BUFF: u32 = 895;
/// Create a new [`CaptainMaiTrin`] analyzer for the given log.
///
@@ -86,7 +92,7 @@ impl<'log> Analyzer for CaptainMaiTrin<'log> {
..
} = event.kind()
{
- if *buff_id == Self::WINNING_BUFF
+ if *buff_id == DETERMINED_ID
&& *destination_agent_addr == mai.addr()
&& event.time() > scarlet.first_aware()
{
@@ -98,3 +104,67 @@ impl<'log> Analyzer for CaptainMaiTrin<'log> {
Some(Outcome::Failure)
}
}
+
+/// Analyzer for the Ankka/Xunlai Jade Junkyard strike.
+#[derive(Debug, Clone, Copy)]
+pub struct Ankka<'log> {
+ log: &'log Log,
+}
+
+impl<'log> Ankka<'log> {
+ /// The minimum duration of [`DETERMINED_ID`] buff applications.
+ pub const DURATION_CUTOFF: i32 = i32::MAX;
+ /// The expected number of times that Ankka needs to phase before we consider it a success.
+ pub const EXPECTED_PHASE_COUNT: usize = 3;
+
+ /// Create a new [`Ankka`] analyzer for the given log.
+ ///
+ /// **Do not** use this method unless you know what you are doing. Instead, rely on
+ /// [`Log::analyzer`]!
+ pub fn new(log: &'log Log) -> Self {
+ Ankka { log }
+ }
+}
+
+impl<'log> Analyzer for Ankka<'log> {
+ fn log(&self) -> &Log {
+ self.log
+ }
+
+ fn is_cm(&self) -> bool {
+ // EoD strike CMs are not implemented yet as of 2022-03-31
+ false
+ }
+
+ fn outcome(&self) -> Option<Outcome> {
+ check_reward!(self.log);
+
+ let ankka = self
+ .log
+ .characters()
+ .find(|npc| npc.id() == Boss::Ankka as u16)?;
+
+ let phase_change_count = self
+ .log
+ .events()
+ .iter()
+ .filter(|event| {
+ if let EventKind::BuffApplication {
+ destination_agent_addr,
+ buff_id,
+ duration,
+ ..
+ } = event.kind()
+ {
+ *buff_id == DETERMINED_ID
+ && *destination_agent_addr == ankka.addr()
+ && *duration == Self::DURATION_CUTOFF
+ } else {
+ false
+ }
+ })
+ .count();
+
+ Outcome::from_bool(phase_change_count == Self::EXPECTED_PHASE_COUNT)
+ }
+}