diff options
| -rw-r--r-- | src/analyzers/mod.rs | 3 | ||||
| -rw-r--r-- | src/analyzers/strikes.rs | 64 | 
2 files changed, 65 insertions, 2 deletions
| diff --git a/src/analyzers/mod.rs b/src/analyzers/mod.rs index ed0f157..7b375af 100644 --- a/src/analyzers/mod.rs +++ b/src/analyzers/mod.rs @@ -132,9 +132,10 @@ pub fn for_log<'l>(log: &'l Log) -> Option<Box<dyn Analyzer + 'l>> {          | Encounter::FraenirOfJormag          | Encounter::Boneskinner          | Encounter::WhisperOfJormag -        | Encounter::CaptainMaiTrin          | Encounter::Ankka          | Encounter::MinisterLi          | Encounter::Dragonvoid => Some(Box::new(strikes::GenericStrike::new(log))), + +        Encounter::CaptainMaiTrin => Some(Box::new(strikes::CaptainMaiTrin::new(log))),      }  } diff --git a/src/analyzers/strikes.rs b/src/analyzers/strikes.rs index 8c22c49..e12b8da 100644 --- a/src/analyzers/strikes.rs +++ b/src/analyzers/strikes.rs @@ -1,7 +1,8 @@  //! Analyzers for Strike Mission logs.  use crate::{      analyzers::{helpers, Analyzer, Outcome}, -    Log, +    gamedata::Boss, +    EventKind, Log,  };  /// Analyzer for strikes. @@ -36,3 +37,64 @@ impl<'log> Analyzer for GenericStrike<'log> {          Outcome::from_bool(helpers::boss_is_dead(self.log))      }  } + +/// Analyzer for the Captain Mai Trin/Aetherblade Hideout strike. +#[derive(Debug, Clone, Copy)] +pub struct CaptainMaiTrin<'log> { +    log: &'log 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. +    /// +    /// **Do not** use this method unless you know what you are doing. Instead, rely on +    /// [`Log::analyzer`]! +    pub fn new(log: &'log Log) -> Self { +        CaptainMaiTrin { log } +    } +} + +impl<'log> Analyzer for CaptainMaiTrin<'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 scarlet = self +            .log +            .characters() +            .find(|npc| npc.id() == Self::ECHO_OF_SCARLET_BRIAR)?; +        let mai = self +            .log +            .characters() +            .find(|npc| npc.id() == Boss::CaptainMaiTrin as u16)?; + +        for event in self.log.events() { +            if let EventKind::BuffApplication { +                destination_agent_addr, +                buff_id, +                .. +            } = event.kind() +            { +                if *buff_id == Self::WINNING_BUFF +                    && *destination_agent_addr == mai.addr() +                    && event.time() > scarlet.first_aware() +                { +                    return Some(Outcome::Success); +                } +            } +        } + +        Some(Outcome::Failure) +    } +} | 
