From c09d449902f529db6fe390b22307a237124410de Mon Sep 17 00:00:00 2001 From: Daniel Schadt Date: Sat, 7 Dec 2019 03:16:43 +0100 Subject: add chatlink + revenant legends support --- src/bt.rs | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) (limited to 'src/bt.rs') diff --git a/src/bt.rs b/src/bt.rs index 3485448..8bfd70a 100644 --- a/src/bt.rs +++ b/src/bt.rs @@ -68,6 +68,60 @@ impl FromStr for TraitChoice { } } +/// Represents a revenenant legend. +#[repr(u8)] +#[derive(Debug, PartialEq, Eq, Hash, Copy, Clone)] +pub enum Legend { + None = 0, + Dragon = 13, + Assassin = 14, + Dwarf = 15, + Demon = 16, + Renegade = 17, + Centaur = 18, +} + +impl Legend { + pub fn get_api_id(self) -> Option { + Some( + match self { + Legend::None => return None, + Legend::Dragon => "Legend1", + Legend::Assassin => "Legend2", + Legend::Dwarf => "Legend3", + Legend::Demon => "Legend4", + Legend::Renegade => "Legend5", + Legend::Centaur => "Legend6", + } + .to_owned(), + ) + } +} + +impl FromStr for Legend { + type Err = (); + + fn from_str(s: &str) -> Result { + let lower = s.to_lowercase(); + match &lower as &str { + "" | "none" => Ok(Legend::None), + "dragon" | "glint" => Ok(Legend::Dragon), + "assassin" | "shiro" => Ok(Legend::Assassin), + "dwarf" | "jalis" => Ok(Legend::Dwarf), + "demon" | "mallyx" => Ok(Legend::Demon), + "renegade" | "kalla" => Ok(Legend::Renegade), + "centaur" | "ventari" => Ok(Legend::Centaur), + _ => Err(()), + } + } +} + +#[derive(Debug, Clone)] +pub enum ExtraData { + None, + Legends([Legend; 4]), +} + /// Represents a traitline. /// /// A traitline consists of the chosen specialization including 3 possible trait choices. @@ -75,6 +129,7 @@ pub type Traitline = (Specialization, [TraitChoice; 3]); pub const SKILL_COUNT: usize = 5; pub const TRAITLINE_COUNT: usize = 3; +pub const LEGEND_COUNT: usize = 4; /// Represents a build template. /// @@ -92,6 +147,8 @@ pub struct BuildTemplate { skills: [Option; SKILL_COUNT], /// The traitlines of the build. traitlines: [Option; TRAITLINE_COUNT], + /// Extra data, such as revenant legends or ranger pets. + extra_data: ExtraData, } impl BuildTemplate { @@ -101,6 +158,7 @@ impl BuildTemplate { profession, skills: [None, None, None, None, None], traitlines: [None, None, None], + extra_data: ExtraData::None, } } @@ -111,6 +169,7 @@ impl BuildTemplate { profession: Profession, skills: &[Skill], traitlines: &[Traitline], + extra_data: ExtraData, ) -> Option { if skills.len() > SKILL_COUNT { return None; @@ -130,6 +189,7 @@ impl BuildTemplate { profession, skills: skill_array, traitlines: trait_array, + extra_data, }) } @@ -157,4 +217,73 @@ impl BuildTemplate { pub fn traitline_count(&self) -> u32 { self.traitlines.iter().filter(|x| x.is_some()).count() as u32 } + + pub fn extra_data(&self) -> &ExtraData { + &self.extra_data + } + + pub fn chatlink(&self) -> String { + let mut bytes = vec![0x0Du8]; + let prof_byte = self.profession() as u8; + bytes.push(prof_byte); + + for traitline in self.traitlines().iter() { + if let Some((spec, choices)) = traitline { + bytes.push(spec.id as u8); + let selected = choices[0] as u8 | (choices[1] as u8) << 2 | (choices[2] as u8) << 4; + bytes.push(selected); + } else { + bytes.push(0); + bytes.push(0); + } + } + + for skill in self.skills() { + // Terrestric + match skill { + None => { + bytes.push(0); + bytes.push(0); + } + Some(s) => { + let palette_id = skill_id_to_palette_id(s.id); + bytes.push((palette_id & 0xFF) as u8); + bytes.push(((palette_id >> 8) & 0xFF) as u8); + } + } + // Aquatic + bytes.push(0); + bytes.push(0); + } + + match *self.extra_data() { + ExtraData::None => { + bytes.extend_from_slice(&[0, 0, 0, 0]); + } + ExtraData::Legends(ref legends) => { + bytes.extend(legends.iter().map(|l| *l as u8)); + } + } + + // Weird padding, achieved by looking at other chat links. + for _ in 0..12 { + bytes.push(0); + } + + println!("Length: {}", bytes.len()); + println!("{:?}", bytes); + format!("[&{}]", base64::encode(&bytes)) + } +} + +static JSON_PALETTE: &'static str = include_str!("skill_palette.json"); + +fn skill_id_to_palette_id(input: u32) -> u32 { + let lookup_table: Vec<(u32, u32)> = serde_json::from_str(JSON_PALETTE).unwrap(); + for (skill, palette) in &lookup_table { + if *skill == input { + return *palette; + } + } + 0 } -- cgit v1.2.3