diff --git a/src/entity/item/esweapon.rs b/src/entity/item/esweapon.rs new file mode 100644 index 0000000..be38a8a --- /dev/null +++ b/src/entity/item/esweapon.rs @@ -0,0 +1,221 @@ +// TODO: actually use this +pub enum SrankError { + InvalidSrankType, + InvalidSrankSpecial, + InvalidSrankName, +} + +pub enum SrankType { + Saber = 0, + Sword, + Blade, + Partisan, + Slicer, + Gun, + Rifle, + Mechgun, + Shot, + Can, + Rod, + Wand, + Twin, + Claw, + Bazooka, + Needle, + Scythe, + Hammer, + Moon, + Psychogun, + Punch, + Windmill, + Harisen, + Katana, + JCutter, + Swords, + Launcher, + Cards, + Knuckle, + Axe, +} + +impl SrankType { + pub fn to_value(&self) -> u8 { + *self as u8 + } + + pub fn from_value(value: u8) -> Result { + match value { + 0 => Ok(SrankType::Saber), + 1 => Ok(SrankType::Sword), + 2 => Ok(SrankType::Blade), + 3 => Ok(SrankType::Partisan), + 4 => Ok(SrankType::Slicer), + 5 => Ok(SrankType::Gun), + 6 => Ok(SrankType::Rifle), + 7 => Ok(SrankType::Mechgun), + 8 => Ok(SrankType::Shot), + 9 => Ok(SrankType::Can), + 10 => Ok(SrankType::Rod), + 11 => Ok(SrankType::Wand), + 12 => Ok(SrankType::Twin), + 13 => Ok(SrankType::Claw), + 14 => Ok(SrankType::Bazooka), + 15 => Ok(SrankType::Needle), + 16 => Ok(SrankType::Scythe), + 17 => Ok(SrankType::Hammer), + 18 => Ok(SrankType::Moon), + 19 => Ok(SrankType::Psychogun), + 20 => Ok(SrankType::Punch), + 21 => Ok(SrankType::Windmill), + 22 => Ok(SrankType::Harisen), + 23 => Ok(SrankType::Katana), + 24 => Ok(SrankType::JCutter), + 25 => Ok(SrankType::Swords), + 26 => Ok(SrankType::Launcher), + 27 => Ok(SrankType::Cards), + 28 => Ok(SrankType::Knuckle), + 29 => Ok(SrankType::Axe), + _ => Err(SrankError::InvalidSrankype), + } + } +} + +pub enum SrankSpecial { + Jellen = 0, + Zalure, + HPRegen, + TPRegen, + Burning, + Tempest, + Blizzard, + Arrest, + Chaos, + Hell, + Spirit, + Berserk, + Demons, + Gush, + Geist, + Kings, +} + +impl SrankSpecial { + pub fn to_value(&self) -> u8 { + *self as u8 + } + + pub fn from_value(value: u8) -> Result { + match value{ + 0 => Ok(SrankSpecial::Jellen), + 1 => Ok(SrankSpecial::Zalure), + 2 => Ok(SrankSpecial::HPRegen), + 3 => Ok(SrankSpecial::TPRegen), + 4 => Ok(SrankSpecial::Burning), + 5 => Ok(SrankSpecial::Tempest), + 6 => Ok(SrankSpecial::Blizzard), + 7 => Ok(SrankSpecial::Arrest), + 8 => Ok(SrankSpecial::Chaos), + 9 => Ok(SrankSpecial::Hell), + 10 => Ok(SrankSpecial::Spirit), + 11 => Ok(SrankSpecial::Berserk), + 12 => Ok(SrankSpecial::Demons), + 13 => Ok(SrankSpecial::Gush), + 14 => Ok(SrankSpecial::Geist), + 15 => Ok(SrankSpecial::Kings), + _ => Err(SrankError::InvalidSrankSpecial), + } + } +} + +pub struct SRankWeapon { + pub type: SrankType, + pub special: Option, + pub name: String, + pub grind: u8, +} + +impl SRankWeapon { + pub fn new(t: SrankType) -> SRankWeapon { + SRankWeapon { + type: t, + special: None, + name: "".to_owned(), + grind: 0, + } + } + + pub fn bytes_from_name(&self) -> [u8; 6] { + let mut result = [0u16; 3]; + let mut letters = [0u8; 8]; + letters[0..self.name.len()].clone_from_slice(&self.name.to_uppercase().clone().into_bytes()); + + for letter in letters.iter_mut() { + *letter = *letter & 0x3F; + } + + result[0] = 0x8000 + (0x20 * letters[0] as u16) + (letters[1] as u16); + result[1] = 0x8000 + (0x400 * letters[2] as u16) + (0x20 * letters[3] as u16) + (letters[4] as u16); + result[2] = 0x8000 + (0x400 * letters[5] as u16) + (0x20 * letters[6] as u16) + (letters[7] as u16); + + [result[0].to_be_bytes()[0], result[0].to_be_bytes()[1], + result[1].to_be_bytes()[0], result[1].to_be_bytes()[1], + result[2].to_be_bytes()[0], result[2].to_be_bytes()[1]] + } + + // TODO: error handling, ensure name is never more than 8 + pub fn name_from_bytes(namebytes: &[u8]) -> String { + let mut name: Vec = Vec::with_capacity(8); + name.extend_from_slice(namebytes); + + for _ in name.len()..name.capacity() { + name.push(0); + } + + let buf: [u16; 3] = [ + u16::from_be_bytes([namebytes[0], namebytes[1]]), + u16::from_be_bytes([namebytes[2], namebytes[3]]), + u16::from_be_bytes([namebytes[4], namebytes[5]]), + ]; + + name[0] = ((buf[0] - 0x8000) / 0x20 + 0x40) as u8; + name[1] = ((buf[0] - 0x8000) % 0x20 + 0x40) as u8; + + name[2] = ((buf[1] - 0x8000) / 0x400 + 0x40) as u8; + name[3] = (((buf[1] - 0x8000) % 0x400) / 0x20 + 0x40) as u8; + name[4] = (((buf[1] - 0x8000) % 0x400) % 0x20 + 0x40) as u8; + + name[5] = ((buf[2] - 0x8000) / 0x400 + 0x40) as u8; + name[6] = (((buf[2] - 0x8000) % 0x400) / 0x20 + 0x40) as u8; + name[7] = (((buf[2] - 0x8000) % 0x400) % 0x20 + 0x40) as u8; + + name.retain(|&x| x > 0x40 && x < 0x5B); + + String::from_utf8(name).unwrap() + } + + pub fn as_bytes(&self) -> [u8; 16] { + let mut result = [0u8; 16]; + result[1] = 0x70 + self.type.to_value(); + result[2] = self.special.to_value(); + result[3] = self.grind; + //result[4] = tekked/untekked flag + result[6..12].clone_from_slice(self.name.bytes_from_name()); + result + } + + // TODO: return Result + pub fn from_bytes(bytes: [u8; 16]) -> SRankWeapon { + let type = bytes[1]; + let special = bytes[2]; + let grind = bytes[3]; + let name = SRankWeapon::name_from_bytes(bytes[6..12]); + + SRankWeapon { + type: type, + special: special, + grind: grind, + name: name, + } + } +} +