aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG.md13
-rw-r--r--src/analyzers/mod.rs56
-rw-r--r--src/analyzers/raids/mod.rs2
-rw-r--r--src/analyzers/raids/w6.rs16
-rw-r--r--src/gamedata.rs525
-rw-r--r--src/lib.rs33
-rw-r--r--tests/parsing.rs66
7 files changed, 576 insertions, 135 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 28666fd..c6820d9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,19 @@ All notable changes to this project will be documented in this file.
- `analyzers::fractal::Ai` with logic to determine CM and outcome of the
Sunqua Peak CM fight.
+### Changed
+- `gamedata::Boss` has been split in `gamedata::Boss` and `gamedata::Encounter`
+ - `Encounter::VoiceOfTheFallen` is now `Encounter::SuperKodanBrothers`
+ - `Encounter::LargosTwins` is now `Encounter::TwinLargos`
+ - `Boss::Xera2`, `Boss::Nikare`, `Boss::Kenut`, `Boss::ClawOfTheFallen` and
+ `Boss::VoiceOfTheFallen` have been introduced
+- `gamedata::Boss` is no longer re-exported as `evtclib::Boss`, instead
+ `evtclib::Encounter` is exported.
+
+### Removed
+- Various `*_ID` constants from `gamedata`: `XERA_PHASE2_ID`, `NIKARE_ID`,
+ `KENUT_ID`, `VOICE_OF_THE_FALLEN_ID` and `CLAW_OF_THE_FALLEN_ID`.
+
## 0.4.3 - 2020-09-21
### Added
- `gamedata::VOICE_OF_THE_FALLEN_ID` and `gamedata::CLAW_OF_THE_FALLEN_ID`.
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..7b636a7 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, Qadim, TwinLargos};
mod w7;
pub use w7::{CardinalAdina, CardinalSabir, QadimThePeerless};
diff --git a/src/analyzers/raids/w6.rs b/src/analyzers/raids/w6.rs
index 8701a63..97a2094 100644
--- a/src/analyzers/raids/w6.rs
+++ b/src/analyzers/raids/w6.rs
@@ -1,7 +1,7 @@
//! Boss fight analyzers for Wing 6 (Mythwright Gambit)
use crate::{
analyzers::{helpers, Analyzer, Outcome},
- gamedata::{KENUT_ID, NIKARE_ID},
+ gamedata::Boss,
EventKind, Log,
};
@@ -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
}
@@ -100,9 +100,9 @@ impl<'log> Analyzer for LargosTwins<'log> {
continue;
};
- if agent.id() == NIKARE_ID {
+ if agent.id() == Boss::Nikare as u16 {
nikare_dead = true;
- } else if agent.id() == KENUT_ID {
+ } else if agent.id() == Boss::Kenut as u16 {
kenut_dead = true;
}
}
diff --git a/src/gamedata.rs b/src/gamedata.rs
index 392bd01..8d0bb7f 100644
--- a/src/gamedata.rs
+++ b/src/gamedata.rs
@@ -6,79 +6,407 @@ 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 for which a log can exist. An encounter consists 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, currently not implemented.).
+///
+/// This enum is non-exhaustive to ensure that future encounters can be added without
+/// inducing a breaking change.
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
+#[non_exhaustive]
+#[repr(u16)]
+pub enum Encounter {
+ // Wing 1
+ ValeGuardian = Boss::ValeGuardian as u16,
+ Gorseval = Boss::Gorseval as u16,
+ Sabetha = Boss::Sabetha as u16,
+
+ // Wing 2
+ Slothasor = Boss::Slothasor as u16,
+ Matthias = Boss::Matthias as u16,
+
+ // Wing 3
+ KeepConstruct = Boss::KeepConstruct as u16,
+ Xera = Boss::Xera as u16,
+
+ // Wing 4
+ Cairn = Boss::Cairn as u16,
+ MursaatOverseer = Boss::MursaatOverseer as u16,
+ Samarog = Boss::Samarog as u16,
+ Deimos = Boss::Deimos as u16,
+
+ // Wing 5
+ SoullessHorror = Boss::SoullessHorror as u16,
+ VoiceInTheVoid = Boss::Dhuum as u16,
+
+ // Wing 6
+ ConjuredAmalgamate = Boss::ConjuredAmalgamate as u16,
+ TwinLargos = Boss::Nikare as u16,
+ Qadim = Boss::Qadim as u16,
+
+ // Wing 7
+ CardinalAdina = Boss::CardinalAdina as u16,
+ CardinalSabir = Boss::CardinalSabir as u16,
+ QadimThePeerless = Boss::QadimThePeerless as u16,
+
+ // 100 CM (Sunqua Peak)
+ Ai = Boss::Ai as u16,
+
+ // 99 CM (Shattered Observatory)
+ Skorvald = Boss::Skorvald as u16,
+ Artsariiv = Boss::Artsariiv as u16,
+ Arkk = Boss::Arkk as u16,
+
+ // 98 CM (Nightmare)
+ MAMA = Boss::MAMA as u16,
+ Siax = Boss::Siax as u16,
+ Ensolyss = Boss::Ensolyss as u16,
+
+ // Strike missions
+ IcebroodConstruct = Boss::IcebroodConstruct as u16,
+ /// Internal name for the "Voice of the Fallen and Claw of the Fallen" strike mission.
+ SuperKodanBrothers = Boss::VoiceOfTheFallen as u16,
+ FraenirOfJormag = Boss::FraenirOfJormag as u16,
+ Boneskinner = Boss::Boneskinner as u16,
+ WhisperOfJormag = Boss::WhisperOfJormag as u16,
+}
+
+impl Encounter {
+ /// Return all possible bosses that can appear in this encounter.
+ ///
+ /// This returns the possible boss IDs, not actual agents. For a similar function check
+ /// [`Log::boss_agents`][crate::Log::boss_agents].
+ ///
+ /// Note that not all of them have to be present in a log, for example if the encounter stopped
+ /// before all of them spawned.
+ pub fn bosses(self) -> &'static [Boss] {
+ match self {
+ Encounter::ValeGuardian => &[Boss::ValeGuardian],
+ Encounter::Gorseval => &[Boss::Gorseval],
+ Encounter::Sabetha => &[Boss::Sabetha],
+ Encounter::Slothasor => &[Boss::Slothasor],
+ Encounter::Matthias => &[Boss::Matthias],
+ Encounter::KeepConstruct => &[Boss::KeepConstruct],
+ Encounter::Xera => &[Boss::Xera, Boss::Xera2],
+ Encounter::Cairn => &[Boss::Cairn],
+ Encounter::MursaatOverseer => &[Boss::MursaatOverseer],
+ Encounter::Samarog => &[Boss::Samarog],
+ Encounter::Deimos => &[Boss::Deimos],
+ Encounter::SoullessHorror => &[Boss::SoullessHorror],
+ Encounter::VoiceInTheVoid => &[Boss::Dhuum],
+ Encounter::ConjuredAmalgamate => &[Boss::ConjuredAmalgamate],
+ Encounter::TwinLargos => &[Boss::Nikare, Boss::Kenut],
+ Encounter::Qadim => &[Boss::Qadim],
+ Encounter::CardinalAdina => &[Boss::CardinalAdina],
+ Encounter::CardinalSabir => &[Boss::CardinalSabir],
+ Encounter::QadimThePeerless => &[Boss::QadimThePeerless],
+ Encounter::Ai => &[Boss::Ai],
+ Encounter::Skorvald => &[Boss::Skorvald],
+ Encounter::Artsariiv => &[Boss::Artsariiv],
+ Encounter::Arkk => &[Boss::Arkk],
+ Encounter::MAMA => &[Boss::MAMA],
+ Encounter::Siax => &[Boss::Siax],
+ Encounter::Ensolyss => &[Boss::Ensolyss],
+ Encounter::IcebroodConstruct => &[Boss::IcebroodConstruct],
+ Encounter::SuperKodanBrothers => &[Boss::VoiceOfTheFallen, Boss::ClawOfTheFallen],
+ Encounter::FraenirOfJormag => &[Boss::FraenirOfJormag],
+ Encounter::Boneskinner => &[Boss::Boneskinner],
+ Encounter::WhisperOfJormag => &[Boss::WhisperOfJormag],
+ }
+ }
+}
+
+/// Error for when converting a string to an encounter fails.
+#[derive(Debug, Clone, Hash, PartialEq, Eq, Error)]
+#[error("Invalid encounter identifier: {0}")]
+pub struct ParseEncounterError(String);
+
+impl FromStr for Encounter {
+ type Err = ParseEncounterError;
+
+ fn from_str(s: &str) -> Result<Self, Self::Err> {
+ // Parsing an encounter is in most cases the same as parsing a boss, as the encounters map
+ // 1:1 to a boss. For the special cases where the encounter as such has a specific name
+ // (such as Twin Largos), this parses strictly more bosses (so "Kenut" would be parsed as
+ // Encounter::TwinLargos, which is fine). The special cases are then added later (so that
+ // "Twin Largos" also is parsed as Encounter::TwinLargos).
+ if let Ok(boss) = Boss::from_str(s) {
+ return Ok(boss.encounter());
+ }
+ let lower = s.to_lowercase();
+ match &lower as &str {
+ "largos" | "twins" | "largos twins" | "twin largos" => Ok(Encounter::TwinLargos),
+ "kodans" | "super kodan brothers" => Ok(Encounter::SuperKodanBrothers),
+
+ _ => Err(ParseEncounterError(s.to_owned())),
+ }
+ }
+}
+
+impl Display for Encounter {
+ fn fmt(&self, f: &mut Formatter) -> fmt::Result {
+ let name = match *self {
+ 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)
+ }
+}
+
+/// Enum containing all boss IDs.
+///
+/// For a high-level event categorization, take a look at the [`Encounter`] enum. The IDs listed
+/// here are for a more fine-grained control, e.g. if you specifically need to differentiate
+/// between Nikare and Kenut in the Twin Largos encounter.
+///
+/// This enum is non-exhaustive to ensure that future bosses can be added without
+/// inducing a breaking change.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, FromPrimitive)]
+#[non_exhaustive]
+#[repr(u16)]
pub enum Boss {
// Wing 1
+ /// Vale Guardian, first boss of Spirit Vale.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Vale_Guardian)
ValeGuardian = 0x3C4E,
+ /// Gorseval, second boss of Spirit Vale.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Gorseval_the_Multifarious)
Gorseval = 0x3C45,
+ /// Sabetha, third boss of Spirit Vale.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Sabetha_the_Saboteur)
Sabetha = 0x3C0F,
// Wing 2
+ /// Slothasor, first boss of Salvation Pass.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Slothasor)
Slothasor = 0x3EFB,
+ /// Matthias, third boss of Salvation Pass.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Matthias_Gabrel)
Matthias = 0x3EF3,
// Wing 3
+ /// Keep Construct, second boss of the Stronghold of the Faithful.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Keep_Construct)
KeepConstruct = 0x3F6B,
- /// Xera ID for phase 1.
+ /// Xera, third boss of the Stronghold of the Faithful.
///
- /// 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).
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Xera)
Xera = 0x3F76,
+ /// ID for Xera in the second phase.
+ ///
+ /// The original Xera will despawn, and after the tower phase, a separate spawn will take over.
+ /// This new Xera will have [`Boss::Xera2`] as ID. Care needs to be taken when calculating boss
+ /// damage on this encounter, as both Xeras have to be taken into account.
+ Xera2 = 0x3F9E,
// Wing 4
+ /// Cairn, first boss of the Bastion of the Penitent.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Cairn_the_Indomitable)
Cairn = 0x432A,
+ /// Mursaat Overseer, second boss of the Bastion of the Penitent.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Mursaat_Overseer)
MursaatOverseer = 0x4314,
+ /// Samarog, third boss of the Bastion of the Penitent.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Samarog)
Samarog = 0x4324,
+ /// Deimos, fourth boss of the Bastion of the Penitent.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Deimos)
Deimos = 0x4302,
// Wing 5
+ /// Soulless Horror, first boss of the Hall of Chains.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Soulless_Horror)
SoullessHorror = 0x4D37,
+ /// Dhuum, second boss of the Hall of Chains.
+ ///
+ /// The encounter to this boss is called [Voice in the Void][Encounter::VoiceInTheVoid].
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Dhuum)
Dhuum = 0x4BFA,
// Wing 6
+ /// Conjured Amalgamate, first boss of Mythwright Gambit.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Conjured_Amalgamate)
ConjuredAmalgamate = 0xABC6,
- /// This is the ID of Nikare, as that is what the Twin Largos logs are identified by.
+ /// Nikare, part of the [Twin Largos][Encounter::TwinLargos] encounter in Mythwright Gamit.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Nikare)
+ Nikare = 0x5271,
+ /// Kenut, part of the [Twin Largos][Encounter::TwinLargos] encounter in Mythwright Gamit.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Nikare)
+ Kenut = 0x5261,
+ /// Qadim, third boss in Mythwright Gambit.
///
- /// 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,
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Qadim)
Qadim = 0x51C6,
// Wing 7
+ /// Cardinal Adina, one of the first two bosses in the Key of Ahdashim.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Cardinal_Adina)
CardinalAdina = 0x55F6,
+ /// Cardinal Sabir, one of the first two bosses in the Key of Ahdashim.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Cardinal_Sabir)
CardinalSabir = 0x55CC,
+ /// Qadim the Peerless, third boss in the Key of Ahdashim.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Qadim_the_Peerless)
QadimThePeerless = 0x55F0,
// 100 CM (Sunqua Peak)
+ /// Ai, Keeper of the Peak, boss of the Sunqua Peak CM fractal.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Ai,_Keeper_of_the_Peak)
Ai = 0x5AD6,
// 99 CM (Shattered Observatory)
+ /// Skorvald the Shattered, first boss in the Shattered Observatory.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Skorvald_the_Shattered)
Skorvald = 0x44E0,
+ /// Artsariiv, second boss in the Shattered Observatory CM.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Artsariiv)
Artsariiv = 0x461D,
+ /// Arkk, third boss in the Shattered Observatory.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Arkk)
Arkk = 0x455F,
// 98 CM (Nightmare)
+ /// MAMA, first boss in the Nightmare CM fractal.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/MAMA)
MAMA = 0x427D,
+ /// Siax the Corrupted, second boss in the Nightmare CM fractal.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Siax_the_Corrupted)
Siax = 0x4284,
+ /// Ensolyss of the Endless Torment, third boss in the Nightmare CM fractal.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Ensolyss_of_the_Endless_Torment)
Ensolyss = 0x4234,
// Strike missions
+ /// Legendary Icebrood Construct, boss of the Shiverpeaks Pass strike mission.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Legendary_Icebrood_Construct)
IcebroodConstruct = 0x568A,
- /// This is the ID of the Voice of the Fallen.
+ /// The Voice of the Fallen, part of the Voice of the Fallen and Claw of the Fallen strike
+ /// mission.
///
- /// 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.
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Voice_of_the_Fallen)
VoiceOfTheFallen = 0x5747,
+ /// The Claw of the Fallen, part of the Voice of the Fallen and Claw of the Fallen strike
+ /// mission.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Claw_of_the_Fallen)
+ ClawOfTheFallen = 0x57D1,
+ /// The Fraenir of Jormag, boss of the Fraenir of Jormag strike mission.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Fraenir_of_Jormag)
FraenirOfJormag = 0x57DC,
+ /// The Boneskinner, boss of the Boneskinner strike mission.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Boneskinner)
Boneskinner = 0x57F9,
+ /// The Whisper of Jormag, boss of the Whisper of Jormag strike mission.
+ ///
+ /// [Guild Wars 2 Wiki](https://wiki.guildwars2.com/wiki/Whisper_of_Jormag)
WhisperOfJormag = 0x58B7,
}
-/// Error for when converting a string to the boss fails.
+impl Boss {
+ /// Get the encounter ID in which this boss can appear.
+ ///
+ /// This is the counterpart to [`Encounter::bosses`].
+ pub fn encounter(self) -> Encounter {
+ match self {
+ Boss::ValeGuardian => Encounter::ValeGuardian,
+ Boss::Gorseval => Encounter::Gorseval,
+ Boss::Sabetha => Encounter::Sabetha,
+ Boss::Slothasor => Encounter::Slothasor,
+ Boss::Matthias => Encounter::Matthias,
+ Boss::KeepConstruct => Encounter::KeepConstruct,
+ Boss::Xera => Encounter::Xera,
+ Boss::Xera2 => Encounter::Xera,
+ Boss::Cairn => Encounter::Cairn,
+ Boss::MursaatOverseer => Encounter::MursaatOverseer,
+ Boss::Samarog => Encounter::Samarog,
+ Boss::Deimos => Encounter::Deimos,
+ Boss::SoullessHorror => Encounter::SoullessHorror,
+ Boss::Dhuum => Encounter::VoiceInTheVoid,
+ Boss::ConjuredAmalgamate => Encounter::ConjuredAmalgamate,
+ Boss::Nikare => Encounter::TwinLargos,
+ Boss::Kenut => Encounter::TwinLargos,
+ Boss::Qadim => Encounter::Qadim,
+ Boss::CardinalAdina => Encounter::CardinalAdina,
+ Boss::CardinalSabir => Encounter::CardinalSabir,
+ Boss::QadimThePeerless => Encounter::QadimThePeerless,
+ Boss::Ai => Encounter::Ai,
+ Boss::Skorvald => Encounter::Skorvald,
+ Boss::Artsariiv => Encounter::Artsariiv,
+ Boss::Arkk => Encounter::Arkk,
+ Boss::MAMA => Encounter::MAMA,
+ Boss::Siax => Encounter::Siax,
+ Boss::Ensolyss => Encounter::Ensolyss,
+ Boss::IcebroodConstruct => Encounter::IcebroodConstruct,
+ Boss::VoiceOfTheFallen => Encounter::SuperKodanBrothers,
+ Boss::ClawOfTheFallen => Encounter::SuperKodanBrothers,
+ Boss::FraenirOfJormag => Encounter::FraenirOfJormag,
+ Boss::Boneskinner => Encounter::Boneskinner,
+ Boss::WhisperOfJormag => Encounter::WhisperOfJormag,
+ }
+ }
+}
+
+/// 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);
@@ -105,10 +433,11 @@ impl FromStr for Boss {
"deimos" => Ok(Boss::Deimos),
"desmina" | "sh" | "soulless horror" => Ok(Boss::SoullessHorror),
- "dhuum" => Ok(Boss::Dhuum),
+ "dhuum" | "voice in the void" => Ok(Boss::Dhuum),
"ca" | "conjured amalgamate" => Ok(Boss::ConjuredAmalgamate),
- "largos" | "twins" | "largos twins" => Ok(Boss::LargosTwins),
+ "nikare" => Ok(Boss::Nikare),
+ "kenut" => Ok(Boss::Kenut),
"qadim" => Ok(Boss::Qadim),
"adina" | "cardinal adina" => Ok(Boss::CardinalAdina),
@@ -126,7 +455,8 @@ impl FromStr for Boss {
"ensolyss" | "ensolyss of the endless torment" => Ok(Boss::Ensolyss),
"icebrood" | "icebrood construct" => Ok(Boss::IcebroodConstruct),
- "kodans" | "super kodan brothers" => Ok(Boss::VoiceOfTheFallen),
+ "voice" | "voice of the fallen" => Ok(Boss::VoiceOfTheFallen),
+ "claw" | "claw of the fallen" => Ok(Boss::ClawOfTheFallen),
"fraenir" | "fraenir of jormag" => Ok(Boss::FraenirOfJormag),
"boneskinner" => Ok(Boss::Boneskinner),
"whisper" | "whisper of jormag" => Ok(Boss::WhisperOfJormag),
@@ -146,6 +476,7 @@ impl Display for Boss {
Boss::Matthias => "Matthias Gabrel",
Boss::KeepConstruct => "Keep Construct",
Boss::Xera => "Xera",
+ Boss::Xera2 => "Xera",
Boss::Cairn => "Cairn the Indomitable",
Boss::MursaatOverseer => "Mursaat Overseer",
Boss::Samarog => "Samarog",
@@ -153,7 +484,8 @@ impl Display for Boss {
Boss::SoullessHorror => "Soulless Horror",
Boss::Dhuum => "Dhuum",
Boss::ConjuredAmalgamate => "Conjured Amalgamate",
- Boss::LargosTwins => "Twin Largos",
+ Boss::Nikare => "Nikare",
+ Boss::Kenut => "Kenut",
Boss::Qadim => "Qadim",
Boss::CardinalAdina => "Cardinal Adina",
Boss::CardinalSabir => "Cardinal Sabir",
@@ -166,7 +498,8 @@ impl Display for Boss {
Boss::Siax => "Siax the Corrupted",
Boss::Ensolyss => "Ensolyss of the Endless Torment",
Boss::IcebroodConstruct => "Icebrood Construct",
- Boss::VoiceOfTheFallen => "Super Kodan Brothers",
+ Boss::VoiceOfTheFallen => "Voice of the Fallen",
+ Boss::ClawOfTheFallen => "Claw of the Fallen",
Boss::FraenirOfJormag => "Fraenir of Jormag",
Boss::Boneskinner => "Boneskinner",
Boss::WhisperOfJormag => "Whisper of Jormag",
@@ -174,25 +507,6 @@ impl Display for Boss {
write!(f, "{}", name)
}
}
-
-/// ID for Xera in the second phase.
-///
-/// The original Xera will despawn, and after the tower phase, a separate spawn
-/// will take over. This new Xera will have this ID. Care needs to be taken when
-/// calculating boss damage on this encounter, as both Xeras have to be taken
-/// into account.
-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;
-/// 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;
-/// The ID of the Claw of the Fallen.
-pub const CLAW_OF_THE_FALLEN_ID: u16 = 22481;
-
/// Error for when converting a string to a profession fails.
#[derive(Debug, Clone, PartialEq, Eq, Hash, Error)]
#[error("Invalid profession identifier: {0}")]
@@ -369,6 +683,119 @@ mod tests {
use super::*;
#[test]
+ fn test_encounter_parsing_ok() {
+ use Encounter::*;
+ let tests: &[(&'static str, Encounter)] = &[
+ ("vg", ValeGuardian),
+ ("VG", ValeGuardian),
+ ("vale guardian", ValeGuardian),
+ ("Vale Guardian", ValeGuardian),
+ ("gorse", Gorseval),
+ ("Gorse", Gorseval),
+ ("gorseval", Gorseval),
+ ("Gorseval", Gorseval),
+ ("sab", Sabetha),
+ ("sabetha", Sabetha),
+ ("Sabetha", Sabetha),
+ ("sloth", Slothasor),
+ ("slothasor", Slothasor),
+ ("Slothasor", Slothasor),
+ ("matthias", Matthias),
+ ("Matthias", Matthias),
+ ("kc", KeepConstruct),
+ ("KC", KeepConstruct),
+ ("keep construct", KeepConstruct),
+ ("Keep Construct", KeepConstruct),
+ ("xera", Xera),
+ ("Xera", Xera),
+ ("cairn", Cairn),
+ ("Cairn", Cairn),
+ ("mo", MursaatOverseer),
+ ("MO", MursaatOverseer),
+ ("mursaat overseer", MursaatOverseer),
+ ("Mursaat Overseer", MursaatOverseer),
+ ("samarog", Samarog),
+ ("Samarog", Samarog),
+ ("deimos", Deimos),
+ ("Deimos", Deimos),
+ ("sh", SoullessHorror),
+ ("soulless horror", SoullessHorror),
+ ("desmina", SoullessHorror),
+ ("Desmina", SoullessHorror),
+ ("dhuum", VoiceInTheVoid),
+ ("Dhuum", VoiceInTheVoid),
+ ("ca", ConjuredAmalgamate),
+ ("conjured amalgamate", ConjuredAmalgamate),
+ ("Conjured Amalgamate", ConjuredAmalgamate),
+ ("largos", TwinLargos),
+ ("twins", TwinLargos),
+ ("largos twins", TwinLargos),
+ ("qadim", Qadim),
+ ("Qadim", Qadim),
+ ("adina", CardinalAdina),
+ ("cardinal adina", CardinalAdina),
+ ("Cardinal Adina", CardinalAdina),
+ ("sabir", CardinalSabir),
+ ("cardinal sabir", CardinalSabir),
+ ("Cardinal Sabir", CardinalSabir),
+ ("qadimp", QadimThePeerless),
+ ("qadim the peerless", QadimThePeerless),
+ ("Qadim The Peerless", QadimThePeerless),
+ ("Ai", Ai),
+ ("ai", Ai),
+ ("skorvald", Skorvald),
+ ("Skorvald", Skorvald),
+ ("artsariiv", Artsariiv),
+ ("Artsariiv", Artsariiv),
+ ("arkk", Arkk),
+ ("Arkk", Arkk),
+ ("mama", MAMA),
+ ("MAMA", MAMA),
+ ("siax", Siax),
+ ("SIAX", Siax),
+ ("ensolyss", Ensolyss),
+ ("Ensolyss", Ensolyss),
+ ("Ensolyss of the Endless Torment", Ensolyss),
+ ("icebrood", IcebroodConstruct),
+ ("Icebrood Construct", IcebroodConstruct),
+ ("fraenir", FraenirOfJormag),
+ ("Fraenir of Jormag", FraenirOfJormag),
+ ("boneskinner", Boneskinner),
+ ("kodans", SuperKodanBrothers),
+ ("whisper", WhisperOfJormag),
+ ("Whisper of Jormag", WhisperOfJormag),
+ ];
+
+ for (input, expected) in tests {
+ assert_eq!(
+ input.parse(),
+ Ok(*expected),
+ "parsing input {:?} failed",
+ input
+ );
+ }
+ }
+
+ #[test]
+ fn test_encounter_parsing_err() {
+ let tests = &[
+ "",
+ "vga",
+ "VGA",
+ "foovg",
+ "valeguardian",
+ "ValeGuardian",
+ "slotha",
+ "slot",
+ "slothasora",
+ "cardinal",
+ ];
+ for test in tests {
+ assert!(test.parse::<Encounter>().is_err());
+ }
+ }
+
+ #[test]
fn test_boss_parsing_ok() {
use Boss::*;
let tests: &[(&'static str, Boss)] = &[
@@ -413,9 +840,10 @@ mod tests {
("ca", ConjuredAmalgamate),
("conjured amalgamate", ConjuredAmalgamate),
("Conjured Amalgamate", ConjuredAmalgamate),
- ("largos", LargosTwins),
- ("twins", LargosTwins),
- ("largos twins", LargosTwins),
+ ("kenut", Kenut),
+ ("Kenut", Kenut),
+ ("nikare", Nikare),
+ ("Nikare", Nikare),
("qadim", Qadim),
("Qadim", Qadim),
("adina", CardinalAdina),
@@ -427,6 +855,8 @@ mod tests {
("qadimp", QadimThePeerless),
("qadim the peerless", QadimThePeerless),
("Qadim The Peerless", QadimThePeerless),
+ ("Ai", Ai),
+ ("ai", Ai),
("skorvald", Skorvald),
("Skorvald", Skorvald),
("artsariiv", Artsariiv),
@@ -445,7 +875,12 @@ mod tests {
("fraenir", FraenirOfJormag),
("Fraenir of Jormag", FraenirOfJormag),
("boneskinner", Boneskinner),
- ("kodans", VoiceOfTheFallen),
+ ("claw", ClawOfTheFallen),
+ ("Claw", ClawOfTheFallen),
+ ("Claw of the Fallen", ClawOfTheFallen),
+ ("voice", VoiceOfTheFallen),
+ ("Voice", VoiceOfTheFallen),
+ ("Voice of the Fallen", VoiceOfTheFallen),
("whisper", WhisperOfJormag),
("Whisper of Jormag", WhisperOfJormag),
];
@@ -473,6 +908,10 @@ mod tests {
"slot",
"slothasora",
"cardinal",
+ // The following are encounters, make sure we don't parse them as bosses.
+ "twins",
+ "kodans",
+ "twin largos",
];
for test in tests {
assert!(test.parse::<Boss>().is_err());
diff --git a/src/lib.rs b/src/lib.rs
index 0c934ec..ecdc876 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -104,7 +104,8 @@ mod processing;
pub use processing::{process, process_file, process_stream, Compression};
pub mod gamedata;
-pub use gamedata::{Boss, EliteSpec, Profession};
+use gamedata::Boss;
+pub use gamedata::{EliteSpec, Encounter, Profession};
pub mod analyzers;
pub use analyzers::{Analyzer, Outcome};
@@ -758,20 +759,12 @@ 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 {
- vec![self.boss_id, gamedata::XERA_PHASE2_ID]
- } else if self.boss_id == Boss::LargosTwins as u16 {
- vec![gamedata::NIKARE_ID, gamedata::KENUT_ID]
- } else if self.encounter() == Some(Boss::VoiceOfTheFallen) {
- vec![
- gamedata::VOICE_OF_THE_FALLEN_ID,
- gamedata::CLAW_OF_THE_FALLEN_ID,
- ]
- } else {
- vec![self.boss_id]
- };
+ let bosses = self
+ .encounter()
+ .map(Encounter::bosses)
+ .unwrap_or(&[] as &[_]);
self.npcs()
- .filter(|c| boss_ids.contains(&c.character().id))
+ .filter(|c| bosses.iter().any(|boss| *boss as u16 == c.character().id))
.map(Agent::erase)
.collect()
}
@@ -791,16 +784,10 @@ 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> {
- // 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);
- }
- Boss::from_u16(self.boss_id)
+ pub fn encounter(&self) -> Option<Encounter> {
+ Boss::from_u16(self.boss_id).map(Boss::encounter)
}
/// Return an analyzer suitable to analyze the given log.
diff --git a/tests/parsing.rs b/tests/parsing.rs
index 5da7a1a..08922c9 100644
--- a/tests/parsing.rs
+++ b/tests/parsing.rs
@@ -3,7 +3,7 @@
use std::fs::File;
use std::io::BufReader;
-use evtclib::{Boss, EliteSpec::*, Profession::*};
+use evtclib::{EliteSpec::*, Encounter, Profession::*};
macro_rules! test {
(name: $name:ident, log: $log:literal, boss: $boss:expr, players: $players:expr,) => {
@@ -42,7 +42,7 @@ macro_rules! test {
test! {
name: parse_vale_guardian,
log: "logs/vg-20200421.zevtc",
- boss: Boss::ValeGuardian,
+ boss: Encounter::ValeGuardian,
players: &[
(4, ":AliceWindwalker.6238", "Fafnarin Sunseeker", Warrior, Some(Berserker)),
(4, ":Gellalli.6580", "Germi N", Revenant, Some(Renegade)),
@@ -60,7 +60,7 @@ test! {
test! {
name: parse_gorseval,
log: "logs/gorseval-20200421.zevtc",
- boss: Boss::Gorseval,
+ boss: Encounter::Gorseval,
players: &[
(4, ":AliceWindwalker.6238", "Fafnarin Sunseeker", Warrior, Some(Berserker)),
(4, ":Gellalli.6580", "Germi N", Revenant, Some(Renegade)),
@@ -78,7 +78,7 @@ test! {
test! {
name: parse_sabetha,
log: "logs/sabetha-20200421.zevtc",
- boss: Boss::Sabetha,
+ boss: Encounter::Sabetha,
players: &[
(4, ":AliceWindwalker.6238", "Fafnarin Sunseeker", Warrior, Some(Berserker)),
(4, ":Gellalli.6580", "Germi N", Revenant, Some(Renegade)),
@@ -98,7 +98,7 @@ test! {
test! {
name: parse_slothasor,
log: "logs/slothasor-20200420.zevtc",
- boss: Boss::Slothasor,
+ boss: Encounter::Slothasor,
players: &[
(2, ":Basafrass.4138", "Miss Mary J", Guardian, Some(Dragonhunter)),
(2, ":Gellalli.6580", "Gellalli V", Guardian, Some(Dragonhunter)),
@@ -116,7 +116,7 @@ test! {
test! {
name: parse_matthias,
log: "logs/matthias-20200421.zevtc",
- boss: Boss::Matthias,
+ boss: Encounter::Matthias,
players: &[
(2, ":Basafrass.4138", "Miss Mary J", Guardian, Some(Dragonhunter)),
(2, ":Gellalli.6580", "Germi N", Revenant, Some(Renegade)),
@@ -136,7 +136,7 @@ test! {
test! {
name: parse_keep_construct,
log: "logs/kc-20200426.zevtc",
- boss: Boss::KeepConstruct,
+ boss: Encounter::KeepConstruct,
players: &[
(3, ":Bomaga.2106", "Krupniczek", Guardian, Some(Dragonhunter)),
(3, ":Buddy Christ.1758", "Block Buddy", Guardian, Some(Dragonhunter)),
@@ -154,7 +154,7 @@ test! {
test! {
name: parse_xera,
log: "logs/xera-20200415.zevtc",
- boss: Boss::Xera,
+ boss: Encounter::Xera,
players: &[
(2, ":Marcoliveira.7526", "Flamed Horns", Guardian, Some(Dragonhunter)),
(2, ":Marvin.4612", "Necro Rp", Necromancer, Some(Reaper)),
@@ -174,7 +174,7 @@ test! {
test! {
name: parse_cairn,
log: "logs/cairn-20200426.zevtc",
- boss: Boss::Cairn,
+ boss: Encounter::Cairn,
players: &[
(3, ":Bomaga.2106", "Krupniczek", Guardian, Some(Dragonhunter)),
(3, ":Buddy Christ.1758", "Block Buddy", Guardian, Some(Firebrand)),
@@ -192,7 +192,7 @@ test! {
test! {
name: parse_mursaat_overseer,
log: "logs/mo-20200426.zevtc",
- boss: Boss::MursaatOverseer,
+ boss: Encounter::MursaatOverseer,
players: &[
(3, ":Bomaga.2106", "Krupniczek", Guardian, Some(Dragonhunter)),
(3, ":Buddy Christ.1758", "Block Buddy", Guardian, Some(Dragonhunter)),
@@ -210,7 +210,7 @@ test! {
test! {
name: parse_samarog,
log: "logs/samarog-20200426.zevtc",
- boss: Boss::Samarog,
+ boss: Encounter::Samarog,
players: &[
(3, ":Bomaga.2106", "Krupniczek", Guardian, Some(Dragonhunter)),
(3, ":Buddy Christ.1758", "Block Buddy", Guardian, Some(Dragonhunter)),
@@ -228,7 +228,7 @@ test! {
test! {
name: parse_deimos,
log: "logs/deimos-20200428.zevtc",
- boss: Boss::Deimos,
+ boss: Encounter::Deimos,
players: &[
(2, ":CrusaderCody.6935", "Cody Quickfire", Guardian, Some(Firebrand)),
(2, ":Mrperfect.5213", "Hanna Kowalski", Revenant, Some(Renegade)),
@@ -248,7 +248,7 @@ test! {
test! {
name: parse_desmina,
log: "logs/desmina-20200425.zevtc",
- boss: Boss::SoullessHorror,
+ boss: Encounter::SoullessHorror,
players: &[
(3, ":AliceWindwalker.6238", "Fafnarin Sunseeker", Warrior, Some(Berserker)),
(3, ":Dunje.4863", "Godric Gobbledygook", Mesmer, Some(Chronomancer)),
@@ -266,7 +266,7 @@ test! {
test! {
name: parse_dhuum,
log: "logs/dhuum-20200428.zevtc",
- boss: Boss::Dhuum,
+ boss: Encounter::VoiceInTheVoid,
players: &[
(1, ":DaZzius.4753", "Amestye Aëther", Mesmer, Some(Chronomancer)),
(1, ":Dunje.4863", "Maho Shiina", Revenant, Some(Renegade)),
@@ -286,7 +286,7 @@ test! {
test! {
name: parse_conjured_amalgamate,
log: "logs/ca-20200426.zevtc",
- boss: Boss::ConjuredAmalgamate,
+ boss: Encounter::ConjuredAmalgamate,
players: &[
(3, ":Admiral Aka Inu.4962", "Großadmiral Aka Inu", Warrior, Some(Berserker)),
(3, ":Dunje.4863", "Irodo", Elementalist, Some(Weaver)),
@@ -304,7 +304,7 @@ test! {
test! {
name: parse_largos_twins,
log: "logs/largos-20200426.zevtc",
- boss: Boss::LargosTwins,
+ boss: Encounter::TwinLargos,
players: &[
(3, ":Cyen Lazarus.4170", "Cyen Blackarrow", Ranger, Some(Druid)),
(3, ":Dunje.4863", "Godric Gobbledygook", Mesmer, Some(Mirage)),
@@ -322,7 +322,7 @@ test! {
test! {
name: parse_qadim,
log: "logs/qadim-20200427.zevtc",
- boss: Boss::Qadim,
+ boss: Encounter::Qadim,
players: &[
(3, ":Cyen Lazarus.4170", "Cyen Blackarrow", Ranger, Some(Druid)),
(3, ":Lopoeo.1594", "Glücklich Und Satt", Mesmer, Some(Chronomancer)),
@@ -342,7 +342,7 @@ test! {
test! {
name: parse_adina,
log: "logs/adina-20200427.zevtc",
- boss: Boss::CardinalAdina,
+ boss: Encounter::CardinalAdina,
players: &[
(3, ":Arkady.3768", "Just Pakly", Engineer, Some(Holosmith)),
(3, ":Dunje.4863", "Peter Party", Ranger, Some(Soulbeast)),
@@ -360,7 +360,7 @@ test! {
test! {
name: parse_sabir,
log: "logs/sabir-20200427.zevtc",
- boss: Boss::CardinalSabir,
+ boss: Encounter::CardinalSabir,
players: &[
(3, ":Arkady.3768", "Just Pakly", Engineer, Some(Holosmith)),
(3, ":Dunje.4863", "Emma Hydes", Elementalist, Some(Weaver)),
@@ -378,7 +378,7 @@ test! {
test! {
name: parse_qadim_the_peerless,
log: "logs/qadimp-20200427.zevtc",
- boss: Boss::QadimThePeerless,
+ boss: Encounter::QadimThePeerless,
players: &[
(3, ":AliceWindwalker.6238", "Fafnarin Sunseeker", Warrior, Some(Berserker)),
(3, ":Arkady.3768", "Just Pakly", Engineer, Some(Holosmith)),
@@ -398,7 +398,7 @@ test! {
test! {
name: parse_ai,
log: "logs/ai-20200922.zevtc",
- boss: Boss::Ai,
+ boss: Encounter::Ai,
players: &[
(0, ":Dunje.4863", "Padme Amidada", Guardian, Some(Firebrand)),
(0, ":Speeaaakmaan.8974", "Damage Modifiers", Guardian, Some(Firebrand)),
@@ -413,7 +413,7 @@ test! {
test! {
name: parse_skorvald,
log: "logs/skorvald-20200427.zevtc",
- boss: Boss::Skorvald,
+ boss: Encounter::Skorvald,
players: &[
(0, ":Dunje.4863", "Jane Whiskerlisp", Revenant, Some(Renegade)),
(0, ":Gellalli.6580", "Germi X", Ranger, Some(Soulbeast)),
@@ -426,7 +426,7 @@ test! {
test! {
name: parse_artsariiv,
log: "logs/artsariiv-20200427.zevtc",
- boss: Boss::Artsariiv,
+ boss: Encounter::Artsariiv,
players: &[
(0, ":Dunje.4863", "Jane Whiskerlisp", Revenant, Some(Renegade)),
(0, ":Gellalli.6580", "Germi X", Ranger, Some(Soulbeast)),
@@ -439,7 +439,7 @@ test! {
test! {
name: parse_arkk,
log: "logs/arkk-20200427.zevtc",
- boss: Boss::Arkk,
+ boss: Encounter::Arkk,
players: &[
(0, ":Dunje.4863", "Jane Whiskerlisp", Revenant, Some(Renegade)),
(0, ":Gellalli.6580", "Germi X", Ranger, Some(Soulbeast)),
@@ -454,7 +454,7 @@ test! {
test! {
name: parse_mama,
log: "logs/mama-20200427.zevtc",
- boss: Boss::MAMA,
+ boss: Encounter::MAMA,
players: &[
(0, ":Dunje.4863", "Jane Whiskerlisp", Revenant, Some(Renegade)),
(0, ":Gellalli.6580", "Germi X", Ranger, Some(Soulbeast)),
@@ -467,7 +467,7 @@ test! {
test! {
name: parse_siax,
log: "logs/siax-20200427.zevtc",
- boss: Boss::Siax,
+ boss: Encounter::Siax,
players: &[
(0, ":Dunje.4863", "Jane Whiskerlisp", Revenant, Some(Renegade)),
(0, ":Gellalli.6580", "Germi X", Ranger, Some(Soulbeast)),
@@ -480,7 +480,7 @@ test! {
test! {
name: parse_ensolyss,
log: "logs/ensolyss-20200427.zevtc",
- boss: Boss::Ensolyss,
+ boss: Encounter::Ensolyss,
players: &[
(0, ":Dunje.4863", "Jane Whiskerlisp", Revenant, Some(Renegade)),
(0, ":Gellalli.6580", "Germi X", Ranger, Some(Soulbeast)),
@@ -495,7 +495,7 @@ test! {
test! {
name: parse_icebrood,
log: "logs/icebrood-20200424.zevtc",
- boss: Boss::IcebroodConstruct,
+ boss: Encounter::IcebroodConstruct,
players: &[
(3, ":Dunje.4863", "Thank You Exorcist", Necromancer, Some(Reaper)),
(3, ":Speeaaakmaan.8974", "Damage Modifiers", Guardian, Some(Firebrand)),
@@ -513,7 +513,7 @@ test! {
test! {
name: parse_kodan_brothers,
log: "logs/kodans-20200424.zevtc",
- boss: Boss::VoiceOfTheFallen,
+ boss: Encounter::SuperKodanBrothers,
players: &[
(3, ":Gellalli.6580", "Germi J", Necromancer, Some(Scourge)),
(3, ":Speeaaakmaan.8974", "Damage Modifiers", Guardian, Some(Firebrand)),
@@ -531,7 +531,7 @@ test! {
test! {
name: parse_fraenir_of_jormag,
log: "logs/fraenir-20200424.zevtc",
- boss: Boss::FraenirOfJormag,
+ boss: Encounter::FraenirOfJormag,
players: &[
(3, ":Dunje.4863", "Thank You Exorcist", Necromancer, Some(Reaper)),
(3, ":Speeaaakmaan.8974", "Damage Modifiers", Guardian, Some(Firebrand)),
@@ -549,7 +549,7 @@ test! {
test! {
name: parse_boneskinner,
log: "logs/boneskinner-20200424.zevtc",
- boss: Boss::Boneskinner,
+ boss: Encounter::Boneskinner,
players: &[
(3, ":Gellalli.6580", "Germi J", Necromancer, Some(Scourge)),
(3, ":Speeaaakmaan.8974", "Damage Modifiers", Guardian, Some(Firebrand)),
@@ -567,7 +567,7 @@ test! {
test! {
name: parse_whisper_of_jormag,
log: "logs/whisper-20200424.zevtc",
- boss: Boss::WhisperOfJormag,
+ boss: Encounter::WhisperOfJormag,
players: &[
(3, ":Gellalli.6580", "Germi J", Necromancer, Some(Scourge)),
(3, ":Speeaaakmaan.8974", "Damage Modifiers", Guardian, Some(Firebrand)),
@@ -587,7 +587,7 @@ test! {
test! {
name: parse_old_cairn_log,
log: "logs/old-cairn-20180321.evtc.zip",
- boss: Boss::Cairn,
+ boss: Encounter::Cairn,
players: &[
(1, ":Medejz.1679", "Nuerha", Guardian, Some(Firebrand)),
(1, ":ONEVA.5860", "Berserkoala", Revenant, Some(Renegade)),