aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2020-04-28 12:11:29 +0200
committerDaniel Schadt <kingdread@gmx.de>2020-04-28 12:12:56 +0200
commit134c9eb670095210672ec125c2df755fe7ec341e (patch)
tree4eae10de1d67446fdd3e0b07288c9f7487df531a
parent4193165476a05fb4b07849c5371af3c8b328d6cb (diff)
downloadevtclib-134c9eb670095210672ec125c2df755fe7ec341e.tar.gz
evtclib-134c9eb670095210672ec125c2df755fe7ec341e.tar.bz2
evtclib-134c9eb670095210672ec125c2df755fe7ec341e.zip
add Profession and EliteSpec enum
In the high-level "Player" struct, dealing with the low-level numbers seems a bit off, especially because it means that applications have to keep a table of id-to-profession mappings anyway. We're already including a Boss enum for the same reasons, so we might as well include Profession and EliteSpec data - which is also not changing as frequently as Boss.
-rw-r--r--src/gamedata.rs68
-rw-r--r--src/lib.rs26
2 files changed, 88 insertions, 6 deletions
diff --git a/src/gamedata.rs b/src/gamedata.rs
index b7ffc11..b32b385 100644
--- a/src/gamedata.rs
+++ b/src/gamedata.rs
@@ -126,6 +126,74 @@ impl FromStr for Boss {
/// into account.
pub const XERA_PHASE2_ID: u16 = 0x3F9E;
+/// An in-game profession.
+///
+/// This only contains the 9 base professions. For elite specializations, see
+/// [`EliteSpec`][EliteSpec].
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, FromPrimitive)]
+pub enum Profession {
+ Guardian = 1,
+ Warrior = 2,
+ Engineer = 3,
+ Ranger = 4,
+ Thief = 5,
+ Elementalist = 6,
+ Mesmer = 7,
+ Necromancer = 8,
+ Revenant = 9,
+}
+
+/// All possible elite specializations.
+///
+/// Note that the numeric value of the enum variants correspond to the specialization ID in the API
+/// as well. See [the official wiki](https://wiki.guildwars2.com/wiki/API:2/specializations) for
+/// more information regarding the API usage.
+#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, FromPrimitive)]
+pub enum EliteSpec {
+ // Heart of Thorns elites:
+ Dragonhunter = 27,
+ Berserker = 18,
+ Scrapper = 43,
+ Druid = 5,
+ Daredevil = 7,
+ Tempest = 48,
+ Chronomancer = 40,
+ Reaper = 34,
+ Herald = 52,
+
+ // Path of Fire elites:
+ Firebrand = 62,
+ Spellbreaker = 61,
+ Holosmith = 57,
+ Soulbeast = 55,
+ Deadeye = 58,
+ Weaver = 56,
+ Mirage = 59,
+ Scourge = 60,
+ Renegade = 63,
+}
+
+impl EliteSpec {
+ /// Return the profession that this elite specialization belongs to.
+ ///
+ /// This value is hardcoded (and not expected to change), and does not require a network
+ /// connection or API access.
+ pub fn profession(self) -> Profession {
+ use EliteSpec::*;
+ match self {
+ Dragonhunter | Firebrand => Profession::Guardian,
+ Berserker | Spellbreaker => Profession::Warrior,
+ Scrapper | Holosmith => Profession::Engineer,
+ Druid | Soulbeast => Profession::Ranger,
+ Daredevil | Deadeye => Profession::Thief,
+ Tempest | Weaver => Profession::Elementalist,
+ Chronomancer | Mirage => Profession::Mesmer,
+ Reaper | Scourge => Profession::Necromancer,
+ Herald | Renegade => Profession::Revenant,
+ }
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/lib.rs b/src/lib.rs
index ee9146a..b884b05 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -20,6 +20,7 @@
use std::marker::PhantomData;
use getset::{CopyGetters, Getters};
+use num_traits::FromPrimitive;
use thiserror::Error;
pub mod raw;
@@ -28,12 +29,16 @@ mod event;
pub use event::{Event, EventKind};
pub mod gamedata;
-pub use gamedata::Boss;
+pub use gamedata::{Boss, EliteSpec, Profession};
#[derive(Error, Debug)]
pub enum EvtcError {
#[error("invalid data has been provided")]
InvalidData,
+ #[error("invalid profession id: {0}")]
+ InvalidProfession(u32),
+ #[error("invalid elite specialization id: {0}")]
+ InvalidEliteSpec(u32),
#[error("utf8 decoding error: {0}")]
Utf8Error(#[from] std::string::FromUtf8Error),
}
@@ -43,11 +48,11 @@ pub enum EvtcError {
pub struct Player {
/// The player's profession.
#[get_copy = "pub"]
- profession: u32,
+ profession: Profession,
- /// The player's elite specialization.
+ /// The player's elite specialization, if any is equipped.
#[get_copy = "pub"]
- elite: u32,
+ elite: Option<EliteSpec>,
character_name: String,
@@ -298,9 +303,18 @@ impl Agent {
.take_while(|c| *c != 0)
.collect::<Vec<_>>();
let third = raw_agent.name[first.len() + second.len() + 2] - b'0';
+ let elite = if raw_agent.is_elite == 0 {
+ None
+ } else {
+ Some(
+ EliteSpec::from_u32(raw_agent.is_elite)
+ .ok_or(EvtcError::InvalidEliteSpec(raw_agent.is_elite))?,
+ )
+ };
AgentKind::Player(Player {
- profession: raw_agent.prof,
- elite: raw_agent.is_elite,
+ profession: Profession::from_u32(raw_agent.prof)
+ .ok_or(EvtcError::InvalidProfession(raw_agent.prof))?,
+ elite,
character_name: String::from_utf8(first)?,
account_name: String::from_utf8(second)?,
subgroup: third,