aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/analyzers/mod.rs56
-rw-r--r--src/analyzers/raids/mod.rs2
-rw-r--r--src/analyzers/raids/w6.rs10
-rw-r--r--src/gamedata.rs197
-rw-r--r--src/lib.rs16
5 files changed, 138 insertions, 143 deletions
diff --git a/src/analyzers/mod.rs b/src/analyzers/mod.rs
index 28724a2..ff04728 100644
--- a/src/analyzers/mod.rs
+++ b/src/analyzers/mod.rs
@@ -24,7 +24,7 @@
//! [`Log::analyzer`][Log::analyzer] (or [`for_log`][for_log]) and the methods defined in
//! [`Analyzer`][Analyzer].
-use crate::{Boss, Log};
+use crate::{Encounter, Log};
pub mod fractals;
pub mod helpers;
@@ -82,41 +82,43 @@ pub fn for_log<'l>(log: &'l Log) -> Option<Box<dyn Analyzer + 'l>> {
let boss = log.encounter()?;
match boss {
- Boss::ValeGuardian | Boss::Gorseval | Boss::Sabetha => {
+ Encounter::ValeGuardian | Encounter::Gorseval | Encounter::Sabetha => {
Some(Box::new(raids::GenericRaid::new(log)))
}
- Boss::Slothasor | Boss::Matthias => Some(Box::new(raids::GenericRaid::new(log))),
+ Encounter::Slothasor | Encounter::Matthias => Some(Box::new(raids::GenericRaid::new(log))),
- Boss::KeepConstruct => Some(Box::new(raids::GenericRaid::new(log))),
- Boss::Xera => Some(Box::new(raids::Xera::new(log))),
+ Encounter::KeepConstruct => Some(Box::new(raids::GenericRaid::new(log))),
+ Encounter::Xera => Some(Box::new(raids::Xera::new(log))),
- Boss::Cairn => Some(Box::new(raids::Cairn::new(log))),
- Boss::MursaatOverseer => Some(Box::new(raids::MursaatOverseer::new(log))),
- Boss::Samarog => Some(Box::new(raids::Samarog::new(log))),
- Boss::Deimos => Some(Box::new(raids::Deimos::new(log))),
+ Encounter::Cairn => Some(Box::new(raids::Cairn::new(log))),
+ Encounter::MursaatOverseer => Some(Box::new(raids::MursaatOverseer::new(log))),
+ Encounter::Samarog => Some(Box::new(raids::Samarog::new(log))),
+ Encounter::Deimos => Some(Box::new(raids::Deimos::new(log))),
- Boss::SoullessHorror => Some(Box::new(raids::SoullessHorror::new(log))),
- Boss::Dhuum => Some(Box::new(raids::Dhuum::new(log))),
+ Encounter::SoullessHorror => Some(Box::new(raids::SoullessHorror::new(log))),
+ Encounter::VoiceInTheVoid => Some(Box::new(raids::Dhuum::new(log))),
- Boss::ConjuredAmalgamate => Some(Box::new(raids::ConjuredAmalgamate::new(log))),
- Boss::LargosTwins => Some(Box::new(raids::LargosTwins::new(log))),
- Boss::Qadim => Some(Box::new(raids::Qadim::new(log))),
+ Encounter::ConjuredAmalgamate => Some(Box::new(raids::ConjuredAmalgamate::new(log))),
+ Encounter::TwinLargos => Some(Box::new(raids::TwinLargos::new(log))),
+ Encounter::Qadim => Some(Box::new(raids::Qadim::new(log))),
- Boss::CardinalAdina => Some(Box::new(raids::CardinalAdina::new(log))),
- Boss::CardinalSabir => Some(Box::new(raids::CardinalSabir::new(log))),
- Boss::QadimThePeerless => Some(Box::new(raids::QadimThePeerless::new(log))),
+ Encounter::CardinalAdina => Some(Box::new(raids::CardinalAdina::new(log))),
+ Encounter::CardinalSabir => Some(Box::new(raids::CardinalSabir::new(log))),
+ Encounter::QadimThePeerless => Some(Box::new(raids::QadimThePeerless::new(log))),
- Boss::Ai => Some(Box::new(fractals::Ai::new(log))),
- Boss::Skorvald => Some(Box::new(fractals::Skorvald::new(log))),
- Boss::Artsariiv | Boss::Arkk | Boss::MAMA | Boss::Siax | Boss::Ensolyss => {
- Some(Box::new(fractals::GenericFractal::new(log)))
- }
+ Encounter::Ai => Some(Box::new(fractals::Ai::new(log))),
+ Encounter::Skorvald => Some(Box::new(fractals::Skorvald::new(log))),
+ Encounter::Artsariiv
+ | Encounter::Arkk
+ | Encounter::MAMA
+ | Encounter::Siax
+ | Encounter::Ensolyss => Some(Box::new(fractals::GenericFractal::new(log))),
- Boss::IcebroodConstruct
- | Boss::VoiceOfTheFallen
- | Boss::FraenirOfJormag
- | Boss::Boneskinner
- | Boss::WhisperOfJormag => Some(Box::new(strikes::GenericStrike::new(log))),
+ Encounter::IcebroodConstruct
+ | Encounter::SuperKodanBrothers
+ | Encounter::FraenirOfJormag
+ | Encounter::Boneskinner
+ | Encounter::WhisperOfJormag => Some(Box::new(strikes::GenericStrike::new(log))),
}
}
diff --git a/src/analyzers/raids/mod.rs b/src/analyzers/raids/mod.rs
index bb3824b..a0602b0 100644
--- a/src/analyzers/raids/mod.rs
+++ b/src/analyzers/raids/mod.rs
@@ -19,7 +19,7 @@ mod w5;
pub use w5::{Dhuum, SoullessHorror};
mod w6;
-pub use w6::{ConjuredAmalgamate, LargosTwins, Qadim};
+pub use w6::{ConjuredAmalgamate, TwinLargos, Qadim};
mod w7;
pub use w7::{CardinalAdina, CardinalSabir, QadimThePeerless};
diff --git a/src/analyzers/raids/w6.rs b/src/analyzers/raids/w6.rs
index 8701a63..11fd02e 100644
--- a/src/analyzers/raids/w6.rs
+++ b/src/analyzers/raids/w6.rs
@@ -59,21 +59,21 @@ pub const LARGOS_CM_HEALTH: u64 = 19_200_000;
///
/// The CM is detected by the boss's health, which is higher in the challenge mote.
#[derive(Debug, Clone, Copy)]
-pub struct LargosTwins<'log> {
+pub struct TwinLargos<'log> {
log: &'log Log,
}
-impl<'log> LargosTwins<'log> {
- /// Create a new [`LargosTwins`] analyzer for the given log.
+impl<'log> TwinLargos<'log> {
+ /// Create a new [`TwinLargos`] 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 {
- LargosTwins { log }
+ TwinLargos { log }
}
}
-impl<'log> Analyzer for LargosTwins<'log> {
+impl<'log> Analyzer for TwinLargos<'log> {
fn log(&self) -> &Log {
self.log
}
diff --git a/src/gamedata.rs b/src/gamedata.rs
index 392bd01..d307802 100644
--- a/src/gamedata.rs
+++ b/src/gamedata.rs
@@ -6,9 +6,17 @@ use std::{
};
use thiserror::Error;
-/// Enum containing all bosses with their IDs.
+/// Enum containing all encounters with their IDs.
+///
+/// An encounter is a fight or event, consisting of no, one or multiple bosses. Most encounters map
+/// 1:1 to a boss (like Vale Guardian), however there are some encounters with multiple bosses
+/// (like Twin Largos), and even encounters without bosses (like the River of Souls).
+///
+/// This enum is non-exhaustive to ensure that future added encounters can be added without
+/// inducing a breaking change.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
-pub enum Boss {
+#[non_exhaustive]
+pub enum Encounter {
// Wing 1
ValeGuardian = 0x3C4E,
Gorseval = 0x3C45,
@@ -20,11 +28,6 @@ pub enum Boss {
// Wing 3
KeepConstruct = 0x3F6B,
- /// Xera ID for phase 1.
- ///
- /// This is only half of Xera's ID, as there will be a second agent for the
- /// second phase. This agent will have another ID, see
- /// [`XERA_PHASE2_ID`](constant.XERA_PHASE2_ID.html).
Xera = 0x3F76,
// Wing 4
@@ -35,15 +38,11 @@ pub enum Boss {
// Wing 5
SoullessHorror = 0x4D37,
- Dhuum = 0x4BFA,
+ VoiceInTheVoid = 0x4BFA,
// Wing 6
ConjuredAmalgamate = 0xABC6,
- /// This is the ID of Nikare, as that is what the Twin Largos logs are identified by.
- ///
- /// If you want Nikare specifically, consider using [`NIKARE_ID`][NIKARE_ID], and similarly, if
- /// you need Kenut, you can use [`KENUT_ID`][KENUT_ID].
- LargosTwins = 0x5271,
+ TwinLargos = 0x5271,
Qadim = 0x51C6,
// Wing 7
@@ -66,110 +65,104 @@ pub enum Boss {
// Strike missions
IcebroodConstruct = 0x568A,
- /// This is the ID of the Voice of the Fallen.
- ///
- /// The strike mission itself contains two bosses, the Voice of the Fallen and the Claw of the
- /// Fallen. Consider using either [`VOICE_OF_THE_FALLEN_ID`][VOICE_OF_THE_FALLEN_ID] or
- /// [`CLAW_OF_THE_FALLEN_ID`][CLAW_OF_THE_FALLEN_ID] if you refer to one of those bosses
- /// specifically.
- VoiceOfTheFallen = 0x5747,
+ SuperKodanBrothers = 0x5747,
FraenirOfJormag = 0x57DC,
Boneskinner = 0x57F9,
WhisperOfJormag = 0x58B7,
}
-/// Error for when converting a string to the boss fails.
+/// Error for when converting a string to an encounter fails.
#[derive(Debug, Clone, Hash, PartialEq, Eq, Error)]
-#[error("Invalid boss identifier: {0}")]
-pub struct ParseBossError(String);
+#[error("Invalid encounter identifier: {0}")]
+pub struct ParseEncounterError(String);
-impl FromStr for Boss {
- type Err = ParseBossError;
+impl FromStr for Encounter {
+ type Err = ParseEncounterError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let lower = s.to_lowercase();
match &lower as &str {
- "vg" | "vale guardian" => Ok(Boss::ValeGuardian),
- "gorse" | "gorseval" => Ok(Boss::Gorseval),
- "sab" | "sabetha" => Ok(Boss::Sabetha),
+ "vg" | "vale guardian" => Ok(Encounter::ValeGuardian),
+ "gorse" | "gorseval" => Ok(Encounter::Gorseval),
+ "sab" | "sabetha" => Ok(Encounter::Sabetha),
- "sloth" | "slothasor" => Ok(Boss::Slothasor),
- "matthias" => Ok(Boss::Matthias),
+ "sloth" | "slothasor" => Ok(Encounter::Slothasor),
+ "matthias" => Ok(Encounter::Matthias),
- "kc" | "keep construct" => Ok(Boss::KeepConstruct),
- "xera" => Ok(Boss::Xera),
+ "kc" | "keep construct" => Ok(Encounter::KeepConstruct),
+ "xera" => Ok(Encounter::Xera),
- "cairn" => Ok(Boss::Cairn),
- "mo" | "mursaat overseer" => Ok(Boss::MursaatOverseer),
- "sam" | "sama" | "samarog" => Ok(Boss::Samarog),
- "deimos" => Ok(Boss::Deimos),
+ "cairn" => Ok(Encounter::Cairn),
+ "mo" | "mursaat overseer" => Ok(Encounter::MursaatOverseer),
+ "sam" | "sama" | "samarog" => Ok(Encounter::Samarog),
+ "deimos" => Ok(Encounter::Deimos),
- "desmina" | "sh" | "soulless horror" => Ok(Boss::SoullessHorror),
- "dhuum" => Ok(Boss::Dhuum),
+ "desmina" | "sh" | "soulless horror" => Ok(Encounter::SoullessHorror),
+ "dhuum" | "voice in the void" => Ok(Encounter::VoiceInTheVoid),
- "ca" | "conjured amalgamate" => Ok(Boss::ConjuredAmalgamate),
- "largos" | "twins" | "largos twins" => Ok(Boss::LargosTwins),
- "qadim" => Ok(Boss::Qadim),
+ "ca" | "conjured amalgamate" => Ok(Encounter::ConjuredAmalgamate),
+ "largos" | "twins" | "largos twins" => Ok(Encounter::TwinLargos),
+ "qadim" => Ok(Encounter::Qadim),
- "adina" | "cardinal adina" => Ok(Boss::CardinalAdina),
- "sabir" | "cardinal sabir" => Ok(Boss::CardinalSabir),
- "qadimp" | "peerless qadim" | "qadim the peerless" => Ok(Boss::QadimThePeerless),
+ "adina" | "cardinal adina" => Ok(Encounter::CardinalAdina),
+ "sabir" | "cardinal sabir" => Ok(Encounter::CardinalSabir),
+ "qadimp" | "peerless qadim" | "qadim the peerless" => Ok(Encounter::QadimThePeerless),
- "ai" | "ai keeper of the peak" => Ok(Boss::Ai),
+ "ai" | "ai keeper of the peak" => Ok(Encounter::Ai),
- "skorvald" => Ok(Boss::Skorvald),
- "artsariiv" => Ok(Boss::Artsariiv),
- "arkk" => Ok(Boss::Arkk),
+ "skorvald" => Ok(Encounter::Skorvald),
+ "artsariiv" => Ok(Encounter::Artsariiv),
+ "arkk" => Ok(Encounter::Arkk),
- "mama" => Ok(Boss::MAMA),
- "siax" => Ok(Boss::Siax),
- "ensolyss" | "ensolyss of the endless torment" => Ok(Boss::Ensolyss),
+ "mama" => Ok(Encounter::MAMA),
+ "siax" => Ok(Encounter::Siax),
+ "ensolyss" | "ensolyss of the endless torment" => Ok(Encounter::Ensolyss),
- "icebrood" | "icebrood construct" => Ok(Boss::IcebroodConstruct),
- "kodans" | "super kodan brothers" => Ok(Boss::VoiceOfTheFallen),
- "fraenir" | "fraenir of jormag" => Ok(Boss::FraenirOfJormag),
- "boneskinner" => Ok(Boss::Boneskinner),
- "whisper" | "whisper of jormag" => Ok(Boss::WhisperOfJormag),
+ "icebrood" | "icebrood construct" => Ok(Encounter::IcebroodConstruct),
+ "kodans" | "super kodan brothers" => Ok(Encounter::SuperKodanBrothers),
+ "fraenir" | "fraenir of jormag" => Ok(Encounter::FraenirOfJormag),
+ "boneskinner" => Ok(Encounter::Boneskinner),
+ "whisper" | "whisper of jormag" => Ok(Encounter::WhisperOfJormag),
- _ => Err(ParseBossError(s.to_owned())),
+ _ => Err(ParseEncounterError(s.to_owned())),
}
}
}
-impl Display for Boss {
+impl Display for Encounter {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
let name = match *self {
- Boss::ValeGuardian => "Vale Guardian",
- Boss::Gorseval => "Gorseval",
- Boss::Sabetha => "Sabetha",
- Boss::Slothasor => "Slothasor",
- Boss::Matthias => "Matthias Gabrel",
- Boss::KeepConstruct => "Keep Construct",
- Boss::Xera => "Xera",
- Boss::Cairn => "Cairn the Indomitable",
- Boss::MursaatOverseer => "Mursaat Overseer",
- Boss::Samarog => "Samarog",
- Boss::Deimos => "Deimos",
- Boss::SoullessHorror => "Soulless Horror",
- Boss::Dhuum => "Dhuum",
- Boss::ConjuredAmalgamate => "Conjured Amalgamate",
- Boss::LargosTwins => "Twin Largos",
- Boss::Qadim => "Qadim",
- Boss::CardinalAdina => "Cardinal Adina",
- Boss::CardinalSabir => "Cardinal Sabir",
- Boss::QadimThePeerless => "Qadim the Peerless",
- Boss::Ai => "Ai Keeper of the Peak",
- Boss::Skorvald => "Skorvald the Shattered",
- Boss::Artsariiv => "Artsariiv",
- Boss::Arkk => "Arkk",
- Boss::MAMA => "MAMA",
- Boss::Siax => "Siax the Corrupted",
- Boss::Ensolyss => "Ensolyss of the Endless Torment",
- Boss::IcebroodConstruct => "Icebrood Construct",
- Boss::VoiceOfTheFallen => "Super Kodan Brothers",
- Boss::FraenirOfJormag => "Fraenir of Jormag",
- Boss::Boneskinner => "Boneskinner",
- Boss::WhisperOfJormag => "Whisper of Jormag",
+ Encounter::ValeGuardian => "Vale Guardian",
+ Encounter::Gorseval => "Gorseval",
+ Encounter::Sabetha => "Sabetha",
+ Encounter::Slothasor => "Slothasor",
+ Encounter::Matthias => "Matthias Gabrel",
+ Encounter::KeepConstruct => "Keep Construct",
+ Encounter::Xera => "Xera",
+ Encounter::Cairn => "Cairn the Indomitable",
+ Encounter::MursaatOverseer => "Mursaat Overseer",
+ Encounter::Samarog => "Samarog",
+ Encounter::Deimos => "Deimos",
+ Encounter::SoullessHorror => "Soulless Horror",
+ Encounter::VoiceInTheVoid => "Voice in the Void",
+ Encounter::ConjuredAmalgamate => "Conjured Amalgamate",
+ Encounter::TwinLargos => "Twin Largos",
+ Encounter::Qadim => "Qadim",
+ Encounter::CardinalAdina => "Cardinal Adina",
+ Encounter::CardinalSabir => "Cardinal Sabir",
+ Encounter::QadimThePeerless => "Qadim the Peerless",
+ Encounter::Ai => "Ai Keeper of the Peak",
+ Encounter::Skorvald => "Skorvald the Shattered",
+ Encounter::Artsariiv => "Artsariiv",
+ Encounter::Arkk => "Arkk",
+ Encounter::MAMA => "MAMA",
+ Encounter::Siax => "Siax the Corrupted",
+ Encounter::Ensolyss => "Ensolyss of the Endless Torment",
+ Encounter::IcebroodConstruct => "Icebrood Construct",
+ Encounter::SuperKodanBrothers => "Super Kodan Brothers",
+ Encounter::FraenirOfJormag => "Fraenir of Jormag",
+ Encounter::Boneskinner => "Boneskinner",
+ Encounter::WhisperOfJormag => "Whisper of Jormag",
};
write!(f, "{}", name)
}
@@ -184,12 +177,12 @@ impl Display for Boss {
pub const XERA_PHASE2_ID: u16 = 0x3F9E;
/// The ID of Nikare in the Twin Largos fight.
-pub const NIKARE_ID: u16 = Boss::LargosTwins as u16;
+pub const NIKARE_ID: u16 = Encounter::TwinLargos as u16;
/// The ID of Kenut in the Twin Largos fight.
pub const KENUT_ID: u16 = 21089;
/// The ID of the Voice of the Fallen.
-pub const VOICE_OF_THE_FALLEN_ID: u16 = Boss::VoiceOfTheFallen as u16;
+pub const VOICE_OF_THE_FALLEN_ID: u16 = Encounter::SuperKodanBrothers as u16;
/// The ID of the Claw of the Fallen.
pub const CLAW_OF_THE_FALLEN_ID: u16 = 22481;
@@ -369,9 +362,9 @@ mod tests {
use super::*;
#[test]
- fn test_boss_parsing_ok() {
- use Boss::*;
- let tests: &[(&'static str, Boss)] = &[
+ fn test_encounter_parsing_ok() {
+ use Encounter::*;
+ let tests: &[(&'static str, Encounter)] = &[
("vg", ValeGuardian),
("VG", ValeGuardian),
("vale guardian", ValeGuardian),
@@ -408,14 +401,14 @@ mod tests {
("soulless horror", SoullessHorror),
("desmina", SoullessHorror),
("Desmina", SoullessHorror),
- ("dhuum", Dhuum),
- ("Dhuum", Dhuum),
+ ("dhuum", VoiceInTheVoid),
+ ("Dhuum", VoiceInTheVoid),
("ca", ConjuredAmalgamate),
("conjured amalgamate", ConjuredAmalgamate),
("Conjured Amalgamate", ConjuredAmalgamate),
- ("largos", LargosTwins),
- ("twins", LargosTwins),
- ("largos twins", LargosTwins),
+ ("largos", TwinLargos),
+ ("twins", TwinLargos),
+ ("largos twins", TwinLargos),
("qadim", Qadim),
("Qadim", Qadim),
("adina", CardinalAdina),
@@ -445,7 +438,7 @@ mod tests {
("fraenir", FraenirOfJormag),
("Fraenir of Jormag", FraenirOfJormag),
("boneskinner", Boneskinner),
- ("kodans", VoiceOfTheFallen),
+ ("kodans", SuperKodanBrothers),
("whisper", WhisperOfJormag),
("Whisper of Jormag", WhisperOfJormag),
];
@@ -461,7 +454,7 @@ mod tests {
}
#[test]
- fn test_boss_parsing_err() {
+ fn test_encounter_parsing_err() {
let tests = &[
"",
"vga",
@@ -475,7 +468,7 @@ mod tests {
"cardinal",
];
for test in tests {
- assert!(test.parse::<Boss>().is_err());
+ assert!(test.parse::<Encounter>().is_err());
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 0c934ec..75bf313 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -104,7 +104,7 @@ mod processing;
pub use processing::{process, process_file, process_stream, Compression};
pub mod gamedata;
-pub use gamedata::{Boss, EliteSpec, Profession};
+pub use gamedata::{EliteSpec, Encounter, Profession};
pub mod analyzers;
pub use analyzers::{Analyzer, Outcome};
@@ -758,11 +758,11 @@ impl Log {
/// This correctly returns multiple agents on encounters where multiple
/// agents are needed.
pub fn boss_agents(&self) -> Vec<&Agent> {
- let boss_ids = if self.boss_id == Boss::Xera as u16 {
+ let boss_ids = if self.boss_id == Encounter::Xera as u16 {
vec![self.boss_id, gamedata::XERA_PHASE2_ID]
- } else if self.boss_id == Boss::LargosTwins as u16 {
+ } else if self.boss_id == Encounter::TwinLargos as u16 {
vec![gamedata::NIKARE_ID, gamedata::KENUT_ID]
- } else if self.encounter() == Some(Boss::VoiceOfTheFallen) {
+ } else if self.encounter() == Some(Encounter::SuperKodanBrothers) {
vec![
gamedata::VOICE_OF_THE_FALLEN_ID,
gamedata::CLAW_OF_THE_FALLEN_ID,
@@ -791,16 +791,16 @@ impl Log {
///
/// Some logs don't have an encounter set or have an ID that is unknown to us (for example, if
/// people set up arcdps with custom IDs). Therefore, this method can only return the encounter
- /// if we know about it in [`Boss`][Boss].
+ /// if we know about it in [`Encounter`].
#[inline]
- pub fn encounter(&self) -> Option<Boss> {
+ pub fn encounter(&self) -> Option<Encounter> {
// Sometimes, encounters of the strike mission "Voice of the Fallen and Claw of the Fallen"
// are saved with the ID of the Claw and sometimes with the Voice. Therefore, we need to
// unify those cases.
if self.boss_id == gamedata::CLAW_OF_THE_FALLEN_ID {
- return Some(Boss::VoiceOfTheFallen);
+ return Some(Encounter::SuperKodanBrothers);
}
- Boss::from_u16(self.boss_id)
+ Encounter::from_u16(self.boss_id)
}
/// Return an analyzer suitable to analyze the given log.