diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/analyzers/raids/w5.rs | 2 | ||||
-rw-r--r-- | src/event.rs | 3 | ||||
-rw-r--r-- | src/lib.rs | 23 | ||||
-rw-r--r-- | src/raw/types.rs | 2 |
4 files changed, 24 insertions, 6 deletions
diff --git a/src/analyzers/raids/w5.rs b/src/analyzers/raids/w5.rs index 747bda2..d00eab8 100644 --- a/src/analyzers/raids/w5.rs +++ b/src/analyzers/raids/w5.rs @@ -46,7 +46,7 @@ impl<'log> Analyzer for SoullessHorror<'log> { .. } = event.kind() { - self.log.is_boss(*destination_agent_addr) && *buff_id == DESMINA_DEATH_BUFF + *buff_id == DESMINA_DEATH_BUFF && self.log.is_boss(*destination_agent_addr) } else { false } diff --git a/src/event.rs b/src/event.rs index ee561f8..b6caa5d 100644 --- a/src/event.rs +++ b/src/event.rs @@ -32,6 +32,7 @@ pub enum FromRawEventError { /// This makes dealing with [`CbtEvent`][raw::CbtEvent] a bit saner (and safer). #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] pub enum EventKind { // State change events /// The agent has entered combat. @@ -579,7 +580,7 @@ pub enum WeaponSet { Land1, /// An unknown weapon set. /// - /// This can be caused bundles or anything else that uses the "weapon swap" + /// This can be caused by bundles or anything else that uses the "weapon swap" /// event but is not a normal weapon set. Unknown(u8), } @@ -19,7 +19,7 @@ //! # Crate Structure //! //! The crate consists of two main parts: The [`raw`][raw] parser, which is used to read structured -//! data from binary input streams, and the higher-level abstrations provided in the root and +//! data from binary input streams, and the higher-level abstractions provided in the root and //! [`event`][event] submodules. //! //! Additionally, there are some defintions (such as IDs for various game items) in the @@ -88,6 +88,7 @@ //! While there are legitimate use cases for writing/modification support, they are currently not //! implemented (but might be in a future version). +use num_traits::FromPrimitive; use thiserror::Error; pub mod raw; @@ -102,6 +103,7 @@ mod processing; pub use processing::{process, process_file, process_stream, Compression}; pub mod gamedata; +use gamedata::Boss; pub use gamedata::{EliteSpec, Encounter, GameMode, Profession}; pub mod analyzers; @@ -138,6 +140,8 @@ pub enum EvtcError { #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] #[derive(Debug, Clone)] pub struct Log { + // evtclib assumes that the agents in this vector are sorted by their address. This information + // is used to speed up the agent_by_addr search. agents: Vec<Agent>, events: Vec<Event>, boss_id: u16, @@ -152,7 +156,12 @@ impl Log { /// Return an agent based on its address. pub fn agent_by_addr(&self, addr: u64) -> Option<&Agent> { - self.agents.iter().find(|a| a.addr() == addr) + // We know that the agents are sorted because processing::process puts them like that. We + // can use the same trick here to achieve a faster agent searching: + self.agents + .binary_search_by_key(&addr, Agent::addr) + .ok() + .map(|i| &self.agents[i]) } /// Return an agent based on the instance ID. @@ -217,7 +226,15 @@ impl Log { /// Check whether the given address is a boss agent. pub fn is_boss(&self, addr: u64) -> bool { - self.boss_agents().into_iter().any(|a| a.addr() == addr) + let bosses = self + .encounter() + .map(Encounter::bosses) + .unwrap_or(&[] as &[_]); + let agent = self + .agent_by_addr(addr) + .and_then(Agent::as_character) + .and_then(|c| Boss::from_u16(c.id())); + agent.map(|e| bosses.contains(&e)).unwrap_or(false) } /// Returns the encounter id. diff --git a/src/raw/types.rs b/src/raw/types.rs index 6339ed8..ce22f5f 100644 --- a/src/raw/types.rs +++ b/src/raw/types.rs @@ -382,7 +382,7 @@ pub struct Agent { pub addr: u64, /// Agent profession id. pub prof: u32, - /// Agent elite specialisation. + /// Agent elite specialization. pub is_elite: u32, /// Toughnes. pub toughness: i16, |