aboutsummaryrefslogtreecommitdiff
path: root/src/bt.rs
diff options
context:
space:
mode:
authorDaniel Schadt <kingdread@gmx.de>2019-12-07 03:16:43 +0100
committerDaniel Schadt <kingdread@gmx.de>2019-12-07 03:16:43 +0100
commitc09d449902f529db6fe390b22307a237124410de (patch)
tree64c04077d2795ae4f288f4fed05e1996238d122c /src/bt.rs
parentd35534c0795caeda46e57fc515b74eba701110a2 (diff)
downloadkondou-c09d449902f529db6fe390b22307a237124410de.tar.gz
kondou-c09d449902f529db6fe390b22307a237124410de.tar.bz2
kondou-c09d449902f529db6fe390b22307a237124410de.zip
add chatlink + revenant legends support
Diffstat (limited to 'src/bt.rs')
-rw-r--r--src/bt.rs129
1 files changed, 129 insertions, 0 deletions
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<String> {
+ 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<Self, Self::Err> {
+ 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>; SKILL_COUNT],
/// The traitlines of the build.
traitlines: [Option<Traitline>; 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<BuildTemplate> {
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
}