diff --git a/src/entity/item/armor.rs b/src/entity/item/armor.rs index 62ae2df..a97a508 100644 --- a/src/entity/item/armor.rs +++ b/src/entity/item/armor.rs @@ -1,5 +1,11 @@ use serde::{Serialize, Deserialize}; +#[derive(Debug, Copy, Clone)] +pub enum ItemParseError { + InvalidArmorBytes, + InvalidArmorType, +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] pub enum ArmorType { Frame, @@ -185,6 +191,100 @@ impl ArmorType { ArmorType::StealthSuit => [0x01, 0x01, 0x57], } } + + pub fn parse_type(data: [u8; 3]) -> Result { + match data { + [0x01, 0x01, 0x00] => Ok(ArmorType::Frame), + [0x01, 0x01, 0x01] => Ok(ArmorType::Armor), + [0x01, 0x01, 0x02] => Ok(ArmorType::PsyArmor), + [0x01, 0x01, 0x03] => Ok(ArmorType::GigaFrame), + [0x01, 0x01, 0x04] => Ok(ArmorType::SoulFrame), + [0x01, 0x01, 0x05] => Ok(ArmorType::CrossArmor), + [0x01, 0x01, 0x06] => Ok(ArmorType::SolidFrame), + [0x01, 0x01, 0x07] => Ok(ArmorType::BraveArmor), + [0x01, 0x01, 0x08] => Ok(ArmorType::HyperFrame), + [0x01, 0x01, 0x09] => Ok(ArmorType::GrandArmor), + [0x01, 0x01, 0x0A] => Ok(ArmorType::ShockFrame), + [0x01, 0x01, 0x0B] => Ok(ArmorType::KingsFrame), + [0x01, 0x01, 0x0C] => Ok(ArmorType::DragonFrame), + [0x01, 0x01, 0x0D] => Ok(ArmorType::AbsorbArmor), + [0x01, 0x01, 0x0E] => Ok(ArmorType::ProtectFrame), + [0x01, 0x01, 0x0F] => Ok(ArmorType::GeneralArmor), + [0x01, 0x01, 0x10] => Ok(ArmorType::PerfectFrame), + [0x01, 0x01, 0x11] => Ok(ArmorType::ValiantFrame), + [0x01, 0x01, 0x12] => Ok(ArmorType::ImperialArmor), + [0x01, 0x01, 0x13] => Ok(ArmorType::HolinessArmor), + [0x01, 0x01, 0x14] => Ok(ArmorType::GuardianArmor), + [0x01, 0x01, 0x15] => Ok(ArmorType::DivinityArmor), + [0x01, 0x01, 0x16] => Ok(ArmorType::UltimateFrame), + [0x01, 0x01, 0x17] => Ok(ArmorType::CelestialArmor), + [0x01, 0x01, 0x18] => Ok(ArmorType::HunterField), + [0x01, 0x01, 0x19] => Ok(ArmorType::RangerField), + [0x01, 0x01, 0x1A] => Ok(ArmorType::ForceField), + [0x01, 0x01, 0x1B] => Ok(ArmorType::RevivalGarment), + [0x01, 0x01, 0x1C] => Ok(ArmorType::SpiritGarment), + [0x01, 0x01, 0x1D] => Ok(ArmorType::StinkFrame), + [0x01, 0x01, 0x1E] => Ok(ArmorType::DPartsVer101), + [0x01, 0x01, 0x1F] => Ok(ArmorType::DPartsVer210), + [0x01, 0x01, 0x20] => Ok(ArmorType::ParasiteWearDeRol), + [0x01, 0x01, 0x21] => Ok(ArmorType::ParasiteWearNelgal), + [0x01, 0x01, 0x22] => Ok(ArmorType::ParasiteWearVajulla), + [0x01, 0x01, 0x23] => Ok(ArmorType::SensePlate), + [0x01, 0x01, 0x24] => Ok(ArmorType::GravitonPlate), + [0x01, 0x01, 0x25] => Ok(ArmorType::AttributePlate), + [0x01, 0x01, 0x26] => Ok(ArmorType::FlowensFrame), + [0x01, 0x01, 0x27] => Ok(ArmorType::CustomFrameVerOo), + [0x01, 0x01, 0x28] => Ok(ArmorType::DbsArmor), + [0x01, 0x01, 0x29] => Ok(ArmorType::GuardWave), + [0x01, 0x01, 0x2A] => Ok(ArmorType::DfField), + [0x01, 0x01, 0x2B] => Ok(ArmorType::LuminousField), + [0x01, 0x01, 0x2C] => Ok(ArmorType::ChuChuFever), + [0x01, 0x01, 0x2D] => Ok(ArmorType::LoveHeart), + [0x01, 0x01, 0x2E] => Ok(ArmorType::FlameGarment), + [0x01, 0x01, 0x2F] => Ok(ArmorType::VirusArmorLafuteria), + [0x01, 0x01, 0x30] => Ok(ArmorType::BrightnessCircle), + [0x01, 0x01, 0x31] => Ok(ArmorType::AuraField), + [0x01, 0x01, 0x32] => Ok(ArmorType::ElectroFrame), + [0x01, 0x01, 0x33] => Ok(ArmorType::SacredCloth), + [0x01, 0x01, 0x34] => Ok(ArmorType::SmokingPlate), + [0x01, 0x01, 0x35] => Ok(ArmorType::StarCuirass), + [0x01, 0x01, 0x36] => Ok(ArmorType::BlackHoundCuirass), + [0x01, 0x01, 0x37] => Ok(ArmorType::MorningPrayer), + [0x01, 0x01, 0x38] => Ok(ArmorType::BlackOdoshiDomaru), + [0x01, 0x01, 0x39] => Ok(ArmorType::RedOdoshiDomaru), + [0x01, 0x01, 0x3A] => Ok(ArmorType::BlackOdoshiRedNimaidou), + [0x01, 0x01, 0x3B] => Ok(ArmorType::BlueOdoshiVioletNimaidou), + [0x01, 0x01, 0x3C] => Ok(ArmorType::DirtyLifejacket), + [0x01, 0x01, 0x3D] => Ok(ArmorType::KroesSweater), + [0x01, 0x01, 0x3E] => Ok(ArmorType::WeddingDress), + [0x01, 0x01, 0x3F] => Ok(ArmorType::SonicteamArmor), + [0x01, 0x01, 0x40] => Ok(ArmorType::RedCoat), + [0x01, 0x01, 0x41] => Ok(ArmorType::Thirteen), + [0x01, 0x01, 0x42] => Ok(ArmorType::MotherGarb), + [0x01, 0x01, 0x43] => Ok(ArmorType::MotherGarbPlus), + [0x01, 0x01, 0x44] => Ok(ArmorType::DressPlate), + [0x01, 0x01, 0x45] => Ok(ArmorType::Sweetheart), + [0x01, 0x01, 0x46] => Ok(ArmorType::IgnitionCloak), + [0x01, 0x01, 0x47] => Ok(ArmorType::CongealCloak), + [0x01, 0x01, 0x48] => Ok(ArmorType::TempestCloak), + [0x01, 0x01, 0x49] => Ok(ArmorType::CursedCloak), + [0x01, 0x01, 0x4A] => Ok(ArmorType::SelectCloak), + [0x01, 0x01, 0x4B] => Ok(ArmorType::SpiritCuirass), + [0x01, 0x01, 0x4C] => Ok(ArmorType::RevivalCuriass), + [0x01, 0x01, 0x4D] => Ok(ArmorType::AllianceUniform), + [0x01, 0x01, 0x4E] => Ok(ArmorType::OfficerUniform), + [0x01, 0x01, 0x4F] => Ok(ArmorType::CommanderUniform), + [0x01, 0x01, 0x50] => Ok(ArmorType::CrimsonCoat), + [0x01, 0x01, 0x51] => Ok(ArmorType::InfantryGear), + [0x01, 0x01, 0x52] => Ok(ArmorType::LieutenantGear), + [0x01, 0x01, 0x53] => Ok(ArmorType::InfantryMantle), + [0x01, 0x01, 0x54] => Ok(ArmorType::LieutenantMantle), + [0x01, 0x01, 0x55] => Ok(ArmorType::UnionField), + [0x01, 0x01, 0x56] => Ok(ArmorType::SamuraiArmor), + [0x01, 0x01, 0x57] => Ok(ArmorType::StealthSuit), + _ => Err(ItemParseError::InvalidArmorType), + } + } } @@ -205,4 +305,19 @@ impl Armor { result[8] = self.evp; result } + + pub fn from_bytes(data: [u8; 16]) -> Result { + let a = ArmorType::parse_type([data[0], data[1], data[2]]); + if a.is_ok() { + Ok(Armor { + armor: a.unwrap(), + dfp: data[6], + evp: data[8], + slots: data[5], + }) + } + else { + Err(ItemParseError::InvalidArmorBytes) // TODO: error handling if wrong bytes are given + } + } } diff --git a/src/entity/item/mag.rs b/src/entity/item/mag.rs index 1c01392..ac34e62 100644 --- a/src/entity/item/mag.rs +++ b/src/entity/item/mag.rs @@ -1,5 +1,10 @@ use serde::{Serialize, Deserialize}; +#[derive(Debug, Copy, Clone)] +pub enum ItemParseError { + InvalidMagType, + InvalidMagBytes, +} #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] pub enum MagType { @@ -162,6 +167,88 @@ impl MagType { MagType::Agastya => [0x02, 0x4C, 0x00], } } + + pub fn parse_type(data: [u8; 3]) -> Result { + match data { + [0x02, 0x00, 0x00] => Ok(MagType::Mag), + [0x02, 0x01, 0x00] => Ok(MagType::Varuna), + [0x02, 0x02, 0x00] => Ok(MagType::Mitra), + [0x02, 0x03, 0x00] => Ok(MagType::Surya), + [0x02, 0x04, 0x00] => Ok(MagType::Vayu), + [0x02, 0x05, 0x00] => Ok(MagType::Varaha), + [0x02, 0x06, 0x00] => Ok(MagType::Kama), + [0x02, 0x07, 0x00] => Ok(MagType::Ushasu), + [0x02, 0x08, 0x00] => Ok(MagType::Apsaras), + [0x02, 0x09, 0x00] => Ok(MagType::Kumara), + [0x02, 0x0A, 0x00] => Ok(MagType::Kaitabha), + [0x02, 0x0B, 0x00] => Ok(MagType::Tapas), + [0x02, 0x0C, 0x00] => Ok(MagType::Bhirava), + [0x02, 0x0D, 0x00] => Ok(MagType::Kalki), + [0x02, 0x0E, 0x00] => Ok(MagType::Rudra), + [0x02, 0x0F, 0x00] => Ok(MagType::Marutah), + [0x02, 0x10, 0x00] => Ok(MagType::Yaksa), + [0x02, 0x11, 0x00] => Ok(MagType::Sita), + [0x02, 0x12, 0x00] => Ok(MagType::Garuda), + [0x02, 0x13, 0x00] => Ok(MagType::Nandin), + [0x02, 0x14, 0x00] => Ok(MagType::Ashvinau), + [0x02, 0x15, 0x00] => Ok(MagType::Ribhava), + [0x02, 0x16, 0x00] => Ok(MagType::Soma), + [0x02, 0x17, 0x00] => Ok(MagType::Ila), + [0x02, 0x18, 0x00] => Ok(MagType::Durga), + [0x02, 0x19, 0x00] => Ok(MagType::Vritra), + [0x02, 0x1A, 0x00] => Ok(MagType::Namuci), + [0x02, 0x1B, 0x00] => Ok(MagType::Sumba), + [0x02, 0x1C, 0x00] => Ok(MagType::Naga), + [0x02, 0x1D, 0x00] => Ok(MagType::Pitri), + [0x02, 0x1E, 0x00] => Ok(MagType::Kabanda), + [0x02, 0x1F, 0x00] => Ok(MagType::Ravana), + [0x02, 0x20, 0x00] => Ok(MagType::Marica), + [0x02, 0x21, 0x00] => Ok(MagType::Soniti), + [0x02, 0x22, 0x00] => Ok(MagType::Preta), + [0x02, 0x23, 0x00] => Ok(MagType::Andhaka), + [0x02, 0x24, 0x00] => Ok(MagType::Bana), + [0x02, 0x25, 0x00] => Ok(MagType::Naraka), + [0x02, 0x26, 0x00] => Ok(MagType::Madhu), + [0x02, 0x27, 0x00] => Ok(MagType::Churel), + [0x02, 0x28, 0x00] => Ok(MagType::Robochao), + [0x02, 0x29, 0x00] => Ok(MagType::OpaOpa), + [0x02, 0x2A, 0x00] => Ok(MagType::Pian), + [0x02, 0x2B, 0x00] => Ok(MagType::Chao), + [0x02, 0x2C, 0x00] => Ok(MagType::ChuChu), + [0x02, 0x2D, 0x00] => Ok(MagType::KapuKapu), + [0x02, 0x2E, 0x00] => Ok(MagType::AngelsWing), + [0x02, 0x2F, 0x00] => Ok(MagType::DevilsWing), + [0x02, 0x30, 0x00] => Ok(MagType::Elenor), + [0x02, 0x31, 0x00] => Ok(MagType::MarkIII), + [0x02, 0x32, 0x00] => Ok(MagType::MasterSystem), + [0x02, 0x33, 0x00] => Ok(MagType::Genesis), + [0x02, 0x34, 0x00] => Ok(MagType::SegaSaturn), + [0x02, 0x35, 0x00] => Ok(MagType::Dreamcast), + [0x02, 0x36, 0x00] => Ok(MagType::Hamburger), + [0x02, 0x37, 0x00] => Ok(MagType::PanzersTail), + [0x02, 0x38, 0x00] => Ok(MagType::DevilsTail), + [0x02, 0x39, 0x00] => Ok(MagType::Deva), + [0x02, 0x3A, 0x00] => Ok(MagType::Rati), + [0x02, 0x3B, 0x00] => Ok(MagType::Savitri), + [0x02, 0x3C, 0x00] => Ok(MagType::Rukmin), + [0x02, 0x3D, 0x00] => Ok(MagType::Pushan), + [0x02, 0x3E, 0x00] => Ok(MagType::Diwari), + [0x02, 0x3F, 0x00] => Ok(MagType::Sato), + [0x02, 0x40, 0x00] => Ok(MagType::Bhima), + [0x02, 0x41, 0x00] => Ok(MagType::Nidra), + [0x02, 0x42, 0x00] => Ok(MagType::GeungSi), + [0x02, 0x44, 0x00] => Ok(MagType::Tellusis), + [0x02, 0x45, 0x00] => Ok(MagType::StrikerUnit), + [0x02, 0x46, 0x00] => Ok(MagType::Pioneer), + [0x02, 0x47, 0x00] => Ok(MagType::Puyo), + [0x02, 0x48, 0x00] => Ok(MagType::Moro), + [0x02, 0x49, 0x00] => Ok(MagType::Rappy), + [0x02, 0x4A, 0x00] => Ok(MagType::Yahoo), + [0x02, 0x4B, 0x00] => Ok(MagType::GaelGiel), + [0x02, 0x4C, 0x00] => Ok(MagType::Agastya), + _ => Err(ItemParseError::InvalidMagType), + } + } } #[derive(Debug, Copy, Clone, PartialEq)] @@ -255,4 +342,39 @@ impl Mag { } count } + + pub fn from_bytes(data: [u8; 16]) -> Result { + let m = MagType::parse_type([data[0], data[1], data[2]]); + if m.is_ok() { + let mut def = u16::from_le_bytes([data[4], data[5]]); + let mut pow = u16::from_le_bytes([data[6], data[7]]); + let mut dex = u16::from_le_bytes([data[8], data[9]]); + let mut mind = u16::from_le_bytes([data[10], data[11]]); + + if (def/100 + dex/100 + pow/100 + mind/100) > 200 { + def = 0; + pow = 0; + dex = 0; + mind = 0; + } + + let sync = data[12] % 121; // TODO: handle invalid values. + let iq = data[13] % 201; // TODO: handle invalid values. + + Ok(Mag{ + mag: m.unwrap(), + def: def, + pow: pow, + dex: dex, + mnd: mind, + synchro: sync, + iq: iq, + photon_blast: [None, None, None], // TODO: actually get PBs from bytes + color: data[15] % 18, + }) + } + else { + Err(ItemParseError::InvalidMagBytes) // TODO: error handling if wrong bytes are given + } + } } diff --git a/src/entity/item/mod.rs b/src/entity/item/mod.rs index 04b64e0..be29d74 100644 --- a/src/entity/item/mod.rs +++ b/src/entity/item/mod.rs @@ -9,6 +9,7 @@ pub mod mag; use crate::entity::character::CharacterEntityId; use crate::ship::map::MapArea; +use crate::ship::drops::ItemDropType; #[derive(PartialEq, Copy, Clone, Debug, Hash, Eq)] pub struct ItemEntityId(pub u32); @@ -75,6 +76,10 @@ pub enum ItemType { Mag(mag::MagType), } +#[derive(Clone, Debug, PartialEq)] +pub enum ItemParseError { + InvalidBytes +} #[derive(Clone, Debug, PartialEq)] pub enum ItemDetail { @@ -106,6 +111,25 @@ impl ItemDetail { ItemDetail::Mag(m) => ItemType::Mag(m.mag), } } + + pub fn parse_item_from_bytes(data: [u8; 16]) -> Option { + let item_type = weapon::WeaponType::parse_type([data[0],data[1],data[2]]).map(|w| ItemType::Weapon(w)) + .or(armor::ArmorType::parse_type([data[0],data[1],data[2]]).map(|a| ItemType::Armor(a))) + .or(shield::ShieldType::parse_type([data[0],data[1],data[2]]).map(|s| ItemType::Shield(s))) + .or(unit::UnitType::parse_type([data[0],data[1],data[2]]).map(|u| ItemType::Unit(u))) + .or(mag::MagType::parse_type([data[0],data[1],data[2]]).map(|m| ItemType::Mag(m))) + .or(tool::ToolType::parse_type([data[0],data[1],data[2]]).map(|t| ItemType::Tool(t))).ok()?; + + match item_type { + ItemType::Weapon(_w) => Some(ItemDropType::Weapon(weapon::Weapon::from_bytes(data).ok()?)), + ItemType::Armor(_a) => Some(ItemDropType::Armor(armor::Armor::from_bytes(data).ok()?)), + ItemType::Shield(_s) => Some(ItemDropType::Shield(shield::Shield::from_bytes(data).ok()?)), + ItemType::Unit(_u) => Some(ItemDropType::Unit(unit::Unit::from_bytes(data).ok()?)), + ItemType::Mag(_m) => Some(ItemDropType::Mag(mag::Mag::from_bytes(data).ok()?)), + ItemType::Tool(_t) => Some(ItemDropType::Tool(tool::Tool::from_bytes(data).ok()?)), + _ => None, + } + } } #[derive(Clone, Debug)] diff --git a/src/entity/item/shield.rs b/src/entity/item/shield.rs index d2a34fb..29ce984 100644 --- a/src/entity/item/shield.rs +++ b/src/entity/item/shield.rs @@ -1,5 +1,11 @@ use serde::{Serialize, Deserialize}; +#[derive(Debug, Copy, Clone)] +pub enum ItemParseError { + InvalidShieldBytes, + InvalidShieldType, +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] pub enum ShieldType { Barrier, @@ -275,7 +281,7 @@ impl ShieldType { ShieldType::YellowRing2 => [0x01, 0x02, 0x64], ShieldType::YellowRing3 => [0x01, 0x02, 0x65], ShieldType::YellowRing4 => [0x01, 0x02, 0x66], - ShieldType::YellowRing5=> [0x01, 0x02, 0x67], + ShieldType::YellowRing5 => [0x01, 0x02, 0x67], ShieldType::YellowRing6 => [0x01, 0x02, 0x68], ShieldType::YellowRing7 => [0x01, 0x02, 0x69], ShieldType::YellowRing8 => [0x01, 0x02, 0x6A], @@ -283,7 +289,7 @@ impl ShieldType { ShieldType::PurpleRing2 => [0x01, 0x02, 0x6C], ShieldType::PurpleRing3 => [0x01, 0x02, 0x6D], ShieldType::PurpleRing4 => [0x01, 0x02, 0x6E], - ShieldType::PurpleRing5=> [0x01, 0x02, 0x6F], + ShieldType::PurpleRing5 => [0x01, 0x02, 0x6F], ShieldType::PurpleRing6 => [0x01, 0x02, 0x70], ShieldType::PurpleRing7 => [0x01, 0x02, 0x71], ShieldType::PurpleRing8 => [0x01, 0x02, 0x72], @@ -292,7 +298,7 @@ impl ShieldType { ShieldType::WhiteRing3 => [0x01, 0x02, 0x75], ShieldType::WhiteRing4 => [0x01, 0x02, 0x76], ShieldType::WhiteRing5 => [0x01, 0x02, 0x77], - ShieldType::WhiteRing6=> [0x01, 0x02, 0x78], + ShieldType::WhiteRing6 => [0x01, 0x02, 0x78], ShieldType::WhiteRing7 => [0x01, 0x02, 0x79], ShieldType::WhiteRing8 => [0x01, 0x02, 0x7A], ShieldType::BlackRing => [0x01, 0x02, 0x7B], @@ -339,6 +345,177 @@ impl ShieldType { ShieldType::Genpei10 => [0x01, 0x02, 0xA4], } } + + pub fn parse_type(data: [u8; 3]) -> Result { + match data { + [0x01, 0x02, 0x00] => Ok(ShieldType::Barrier), + [0x01, 0x02, 0x01] => Ok(ShieldType::Shield), + [0x01, 0x02, 0x02] => Ok(ShieldType::CoreShield), + [0x01, 0x02, 0x03] => Ok(ShieldType::GigaShield), + [0x01, 0x02, 0x04] => Ok(ShieldType::SoulBarrier), + [0x01, 0x02, 0x05] => Ok(ShieldType::HardShield), + [0x01, 0x02, 0x06] => Ok(ShieldType::BraveBarrier), + [0x01, 0x02, 0x07] => Ok(ShieldType::SolidShield), + [0x01, 0x02, 0x08] => Ok(ShieldType::FlameBarrier), + [0x01, 0x02, 0x09] => Ok(ShieldType::PlasmaBarrier), + [0x01, 0x02, 0x0A] => Ok(ShieldType::FreezeBarrier), + [0x01, 0x02, 0x0B] => Ok(ShieldType::PsychicBarrier), + [0x01, 0x02, 0x0C] => Ok(ShieldType::GeneralShield), + [0x01, 0x02, 0x0D] => Ok(ShieldType::ProtectBarrier), + [0x01, 0x02, 0x0E] => Ok(ShieldType::GloriousShield), + [0x01, 0x02, 0x0F] => Ok(ShieldType::ImperialBarrier), + [0x01, 0x02, 0x10] => Ok(ShieldType::GuardianShield), + [0x01, 0x02, 0x11] => Ok(ShieldType::DivinityBarrier), + [0x01, 0x02, 0x12] => Ok(ShieldType::UltimateShield), + [0x01, 0x02, 0x13] => Ok(ShieldType::SpiritualShield), + [0x01, 0x02, 0x14] => Ok(ShieldType::CelestialShield), + [0x01, 0x02, 0x15] => Ok(ShieldType::InvisibleGuard), + [0x01, 0x02, 0x16] => Ok(ShieldType::SacredGuard), + [0x01, 0x02, 0x17] => Ok(ShieldType::SPartsVer116), + [0x01, 0x02, 0x18] => Ok(ShieldType::SPartsVer201), + [0x01, 0x02, 0x19] => Ok(ShieldType::LightRelief), + [0x01, 0x02, 0x1A] => Ok(ShieldType::ShieldOfDelsaber), + [0x01, 0x02, 0x1B] => Ok(ShieldType::ForceWall), + [0x01, 0x02, 0x1C] => Ok(ShieldType::RangerWall), + [0x01, 0x02, 0x1D] => Ok(ShieldType::HunterWall), + [0x01, 0x02, 0x1E] => Ok(ShieldType::AttributeWall), + [0x01, 0x02, 0x1F] => Ok(ShieldType::SecretGear), + [0x01, 0x02, 0x20] => Ok(ShieldType::CombatGear), + [0x01, 0x02, 0x21] => Ok(ShieldType::ProtoRegeneGear), + [0x01, 0x02, 0x22] => Ok(ShieldType::RegenerateGear), + [0x01, 0x02, 0x23] => Ok(ShieldType::RegeneGearAdv), + [0x01, 0x02, 0x24] => Ok(ShieldType::FlowensShield), + [0x01, 0x02, 0x25] => Ok(ShieldType::CustomBarrierVerOo), + [0x01, 0x02, 0x26] => Ok(ShieldType::DbsShield), + [0x01, 0x02, 0x27] => Ok(ShieldType::RedRing), + [0x01, 0x02, 0x28] => Ok(ShieldType::TripolicShield), + [0x01, 0x02, 0x29] => Ok(ShieldType::StandstillShield), + [0x01, 0x02, 0x2A] => Ok(ShieldType::SafetyHeart), + [0x01, 0x02, 0x2B] => Ok(ShieldType::KasamiBracer), + [0x01, 0x02, 0x2C] => Ok(ShieldType::GodsShieldSuzaku), + [0x01, 0x02, 0x2D] => Ok(ShieldType::GodsShieldGenbu), + [0x01, 0x02, 0x2E] => Ok(ShieldType::GodsShieldByakko), + [0x01, 0x02, 0x2F] => Ok(ShieldType::GodsShieldSeiryu), + [0x01, 0x02, 0x30] => Ok(ShieldType::HuntersShell), + [0x01, 0x02, 0x31] => Ok(ShieldType::RicosGlasses), + [0x01, 0x02, 0x32] => Ok(ShieldType::RicosEarring), + [0x01, 0x02, 0x33] => Ok(ShieldType::BlueRing), + [0x01, 0x02, 0x34] => Ok(ShieldType::Barrier2), + [0x01, 0x02, 0x35] => Ok(ShieldType::SecureFeet), + [0x01, 0x02, 0x36] => Ok(ShieldType::Barrier3), + [0x01, 0x02, 0x37] => Ok(ShieldType::Barrier4), + [0x01, 0x02, 0x38] => Ok(ShieldType::Barrier5), + [0x01, 0x02, 0x39] => Ok(ShieldType::Barrier6), + [0x01, 0x02, 0x3A] => Ok(ShieldType::RestaMerge), + [0x01, 0x02, 0x3B] => Ok(ShieldType::AntiMerge), + [0x01, 0x02, 0x3C] => Ok(ShieldType::ShiftaMerge), + [0x01, 0x02, 0x3D] => Ok(ShieldType::DebandMerge), + [0x01, 0x02, 0x3E] => Ok(ShieldType::FoieMerge), + [0x01, 0x02, 0x3F] => Ok(ShieldType::GifoieMerge), + [0x01, 0x02, 0x40] => Ok(ShieldType::RafoieMerge), + [0x01, 0x02, 0x41] => Ok(ShieldType::RedMerge), + [0x01, 0x02, 0x42] => Ok(ShieldType::BartaMerge), + [0x01, 0x02, 0x43] => Ok(ShieldType::GibartaMerge), + [0x01, 0x02, 0x44] => Ok(ShieldType::RabartaMerge), + [0x01, 0x02, 0x45] => Ok(ShieldType::BlueMerge), + [0x01, 0x02, 0x46] => Ok(ShieldType::ZondeMerge), + [0x01, 0x02, 0x47] => Ok(ShieldType::GizondeMerge), + [0x01, 0x02, 0x48] => Ok(ShieldType::RazondeMerge), + [0x01, 0x02, 0x49] => Ok(ShieldType::YellowMerge), + [0x01, 0x02, 0x4A] => Ok(ShieldType::RecoveryBarrier), + [0x01, 0x02, 0x4B] => Ok(ShieldType::AssistBarrier), + [0x01, 0x02, 0x4C] => Ok(ShieldType::RedBarrier), + [0x01, 0x02, 0x4D] => Ok(ShieldType::BlueBarrier), + [0x01, 0x02, 0x4E] => Ok(ShieldType::YellowBarrier), + [0x01, 0x02, 0x4F] => Ok(ShieldType::WeaponsGoldShield), + [0x01, 0x02, 0x50] => Ok(ShieldType::BlackGear), + [0x01, 0x02, 0x51] => Ok(ShieldType::WorksGuard), + [0x01, 0x02, 0x52] => Ok(ShieldType::RagolRing), + [0x01, 0x02, 0x53] => Ok(ShieldType::BlueRing2), + [0x01, 0x02, 0x54] => Ok(ShieldType::BlueRing3), + [0x01, 0x02, 0x55] => Ok(ShieldType::BlueRing4), + [0x01, 0x02, 0x56] => Ok(ShieldType::BlueRing5), + [0x01, 0x02, 0x57] => Ok(ShieldType::BlueRing6), + [0x01, 0x02, 0x58] => Ok(ShieldType::BlueRing7), + [0x01, 0x02, 0x59] => Ok(ShieldType::BlueRing8), + [0x01, 0x02, 0x5A] => Ok(ShieldType::BlueRing9), + [0x01, 0x02, 0x5B] => Ok(ShieldType::GreenRing), + [0x01, 0x02, 0x5C] => Ok(ShieldType::GreenRing2), + [0x01, 0x02, 0x5D] => Ok(ShieldType::GreenRing3), + [0x01, 0x02, 0x5E] => Ok(ShieldType::GreenRing4), + [0x01, 0x02, 0x5F] => Ok(ShieldType::GreenRing5), + [0x01, 0x02, 0x60] => Ok(ShieldType::GreenRing6), + [0x01, 0x02, 0x61] => Ok(ShieldType::GreenRing7), + [0x01, 0x02, 0x62] => Ok(ShieldType::GreenRing8), + [0x01, 0x02, 0x63] => Ok(ShieldType::YellowRing), + [0x01, 0x02, 0x64] => Ok(ShieldType::YellowRing2), + [0x01, 0x02, 0x65] => Ok(ShieldType::YellowRing3), + [0x01, 0x02, 0x66] => Ok(ShieldType::YellowRing4), + [0x01, 0x02, 0x67] => Ok(ShieldType::YellowRing5), + [0x01, 0x02, 0x68] => Ok(ShieldType::YellowRing6), + [0x01, 0x02, 0x69] => Ok(ShieldType::YellowRing7), + [0x01, 0x02, 0x6A] => Ok(ShieldType::YellowRing8), + [0x01, 0x02, 0x6B] => Ok(ShieldType::PurpleRing), + [0x01, 0x02, 0x6C] => Ok(ShieldType::PurpleRing2), + [0x01, 0x02, 0x6D] => Ok(ShieldType::PurpleRing3), + [0x01, 0x02, 0x6E] => Ok(ShieldType::PurpleRing4), + [0x01, 0x02, 0x6F] => Ok(ShieldType::PurpleRing5), + [0x01, 0x02, 0x70] => Ok(ShieldType::PurpleRing6), + [0x01, 0x02, 0x71] => Ok(ShieldType::PurpleRing7), + [0x01, 0x02, 0x72] => Ok(ShieldType::PurpleRing8), + [0x01, 0x02, 0x73] => Ok(ShieldType::WhiteRing), + [0x01, 0x02, 0x74] => Ok(ShieldType::WhiteRing2), + [0x01, 0x02, 0x75] => Ok(ShieldType::WhiteRing3), + [0x01, 0x02, 0x76] => Ok(ShieldType::WhiteRing4), + [0x01, 0x02, 0x77] => Ok(ShieldType::WhiteRing5), + [0x01, 0x02, 0x78] => Ok(ShieldType::WhiteRing6), + [0x01, 0x02, 0x79] => Ok(ShieldType::WhiteRing7), + [0x01, 0x02, 0x7A] => Ok(ShieldType::WhiteRing8), + [0x01, 0x02, 0x7B] => Ok(ShieldType::BlackRing), + [0x01, 0x02, 0x7C] => Ok(ShieldType::BlackRing2), + [0x01, 0x02, 0x7D] => Ok(ShieldType::BlackRing3), + [0x01, 0x02, 0x7E] => Ok(ShieldType::BlackRing4), + [0x01, 0x02, 0x7F] => Ok(ShieldType::BlackRing5), + [0x01, 0x02, 0x80] => Ok(ShieldType::BlackRing6), + [0x01, 0x02, 0x81] => Ok(ShieldType::BlackRing7), + [0x01, 0x02, 0x82] => Ok(ShieldType::BlackRing8), + [0x01, 0x02, 0x83] => Ok(ShieldType::WeaponsSilverShield), + [0x01, 0x02, 0x84] => Ok(ShieldType::WeaponsCopperShield), + [0x01, 0x02, 0x85] => Ok(ShieldType::Gratia), + [0x01, 0x02, 0x86] => Ok(ShieldType::TripolicReflector), + [0x01, 0x02, 0x87] => Ok(ShieldType::StrikerPlus), + [0x01, 0x02, 0x88] => Ok(ShieldType::RegenerateGearBP), + [0x01, 0x02, 0x89] => Ok(ShieldType::Rupika), + [0x01, 0x02, 0x8A] => Ok(ShieldType::YataMirror), + [0x01, 0x02, 0x8B] => Ok(ShieldType::BunnyEars), + [0x01, 0x02, 0x8C] => Ok(ShieldType::CatEars), + [0x01, 0x02, 0x8D] => Ok(ShieldType::ThreeSeals), + [0x01, 0x02, 0x8E] => Ok(ShieldType::GodsShieldKouryu), + [0x01, 0x02, 0x8F] => Ok(ShieldType::DfShield), + [0x01, 0x02, 0x90] => Ok(ShieldType::FromTheDepths), + [0x01, 0x02, 0x91] => Ok(ShieldType::DeRolLeShield), + [0x01, 0x02, 0x92] => Ok(ShieldType::HoneycombReflector), + [0x01, 0x02, 0x93] => Ok(ShieldType::Epsiguard), + [0x01, 0x02, 0x94] => Ok(ShieldType::AngelRing), + [0x01, 0x02, 0x95] => Ok(ShieldType::UnionGuard), + [0x01, 0x02, 0x96] => Ok(ShieldType::UnionGuard2), + [0x01, 0x02, 0x97] => Ok(ShieldType::UnionGuard3), + [0x01, 0x02, 0x98] => Ok(ShieldType::UnionGuard4), + [0x01, 0x02, 0x99] => Ok(ShieldType::StinkShield), + [0x01, 0x02, 0x9A] => Ok(ShieldType::Unknownb), + [0x01, 0x02, 0x9B] => Ok(ShieldType::Genpei), + [0x01, 0x02, 0x9C] => Ok(ShieldType::Genpei2), + [0x01, 0x02, 0x9D] => Ok(ShieldType::Genpei3), + [0x01, 0x02, 0x9E] => Ok(ShieldType::Genpei4), + [0x01, 0x02, 0x9F] => Ok(ShieldType::Genpei5), + [0x01, 0x02, 0xA0] => Ok(ShieldType::Genpei6), + [0x01, 0x02, 0xA1] => Ok(ShieldType::Genpei7), + [0x01, 0x02, 0xA2] => Ok(ShieldType::Genpei8), + [0x01, 0x02, 0xA3] => Ok(ShieldType::Genpei9), + [0x01, 0x02, 0xA4] => Ok(ShieldType::Genpei10), + _ => Err(ItemParseError::InvalidShieldType), + } + } } @@ -357,4 +534,18 @@ impl Shield { result[8] = self.evp; result } + + pub fn from_bytes(data: [u8; 16]) -> Result { + let s = ShieldType::parse_type([data[0], data[1], data[2]]); + if s.is_ok() { + Ok(Shield{ + shield: s.unwrap(), + dfp: data[6], + evp: data[8], + }) + } + else { + Err(ItemParseError::InvalidShieldBytes) // TODO: error handling if wrong bytes are given + } + } } diff --git a/src/entity/item/tool.rs b/src/entity/item/tool.rs index 7894530..4d5dc59 100644 --- a/src/entity/item/tool.rs +++ b/src/entity/item/tool.rs @@ -1,5 +1,11 @@ use serde::{Serialize, Deserialize}; +#[derive(Debug, Copy, Clone)] +pub enum ItemParseError { + InvalidToolBytes, + InvalidToolType, +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] pub enum ToolType { Monomate, @@ -390,6 +396,186 @@ impl ToolType { ToolType::TeamPoints10000 => [0x03, 0x19, 0x03], } } + + pub fn parse_type(data: [u8; 3]) -> Result { + match data { + [0x03, 0x00, 0x00] => Ok(ToolType::Monomate), + [0x03, 0x00, 0x01] => Ok(ToolType::Dimate), + [0x03, 0x00, 0x02] => Ok(ToolType::Trimate), + [0x03, 0x01, 0x00] => Ok(ToolType::Monofluid), + [0x03, 0x01, 0x01] => Ok(ToolType::Difluid), + [0x03, 0x01, 0x02] => Ok(ToolType::Trifluid), + [0x03, 0x03, 0x00] => Ok(ToolType::SolAtomizer), + [0x03, 0x04, 0x00] => Ok(ToolType::MoonAtomizer), + [0x03, 0x05, 0x00] => Ok(ToolType::StarAtomizer), + [0x03, 0x06, 0x00] => Ok(ToolType::Antidote), + [0x03, 0x06, 0x01] => Ok(ToolType::Antiparalysis), + [0x03, 0x07, 0x00] => Ok(ToolType::Telepipe), + [0x03, 0x08, 0x00] => Ok(ToolType::TrapVision), + [0x03, 0x09, 0x00] => Ok(ToolType::ScapeDoll), + [0x03, 0x0A, 0x00] => Ok(ToolType::Monogrinder), + [0x03, 0x0A, 0x01] => Ok(ToolType::Digrinder), + [0x03, 0x0A, 0x02] => Ok(ToolType::Trigrinder), + [0x03, 0x0B, 0x00] => Ok(ToolType::PowerMaterial), + [0x03, 0x0B, 0x01] => Ok(ToolType::MindMaterial), + [0x03, 0x0B, 0x02] => Ok(ToolType::EvadeMaterial), + [0x03, 0x0B, 0x03] => Ok(ToolType::HpMaterial), + [0x03, 0x0B, 0x04] => Ok(ToolType::TpMaterial), + [0x03, 0x0B, 0x05] => Ok(ToolType::DefMaterial), + [0x03, 0x0B, 0x06] => Ok(ToolType::LuckMaterial), + [0x03, 0x0C, 0x00] => Ok(ToolType::CellOfMag502), + [0x03, 0x0C, 0x01] => Ok(ToolType::CellOfMag213), + [0x03, 0x0C, 0x02] => Ok(ToolType::PartsOfRobochao), + [0x03, 0x0C, 0x03] => Ok(ToolType::HeartOfOpaOpa), + [0x03, 0x0C, 0x04] => Ok(ToolType::HeartOfPian), + [0x03, 0x0C, 0x05] => Ok(ToolType::HeartOfChao), + [0x03, 0x0D, 0x00] => Ok(ToolType::SorcerersRightArm), + [0x03, 0x0D, 0x01] => Ok(ToolType::SBeatsArms), + [0x03, 0x0D, 0x02] => Ok(ToolType::PArmsArms), + [0x03, 0x0D, 0x03] => Ok(ToolType::DelsabersRightArm), + [0x03, 0x0D, 0x04] => Ok(ToolType::BringersRightArm), + [0x03, 0x0D, 0x05] => Ok(ToolType::DelsabersLeftArm), + [0x03, 0x0D, 0x06] => Ok(ToolType::SRedsArms), + [0x03, 0x0D, 0x07] => Ok(ToolType::DragonsClaw), + [0x03, 0x0D, 0x08] => Ok(ToolType::HildebearsHead), + [0x03, 0x0D, 0x09] => Ok(ToolType::HildebluesHead), + [0x03, 0x0D, 0x0A] => Ok(ToolType::PartsOfBaranz), + [0x03, 0x0D, 0x0B] => Ok(ToolType::BelrasRightArm), + [0x03, 0x0D, 0x0C] => Ok(ToolType::GiGuesBody), + [0x03, 0x0D, 0x0D] => Ok(ToolType::SinowBerillsArms), + [0x03, 0x0D, 0x0E] => Ok(ToolType::GrassAssassinsArms), + [0x03, 0x0D, 0x0F] => Ok(ToolType::BoomasRightArm), + [0x03, 0x0D, 0x10] => Ok(ToolType::GoboomasRightArm), + [0x03, 0x0D, 0x11] => Ok(ToolType::GigoboomasRightArm), + [0x03, 0x0D, 0x12] => Ok(ToolType::GalGryphonsWing), + [0x03, 0x0D, 0x13] => Ok(ToolType::RappysWing), + [0x03, 0x0D, 0x14] => Ok(ToolType::CladdingOfEpsilon), + [0x03, 0x0D, 0x15] => Ok(ToolType::DeRolLeShell), + [0x03, 0x0E, 0x00] => Ok(ToolType::BerillPhoton), + [0x03, 0x0E, 0x01] => Ok(ToolType::ParasiticGeneFlow), + [0x03, 0x0E, 0x02] => Ok(ToolType::MagicStoneIritista), + [0x03, 0x0E, 0x03] => Ok(ToolType::BlueBlackStone), + [0x03, 0x0E, 0x04] => Ok(ToolType::Syncesta), + [0x03, 0x0E, 0x05] => Ok(ToolType::MagicWater), + [0x03, 0x0E, 0x06] => Ok(ToolType::ParasiticCellTypeD), + [0x03, 0x0E, 0x07] => Ok(ToolType::MagicRockHeartKey), + [0x03, 0x0E, 0x08] => Ok(ToolType::MagicRockMoola), + [0x03, 0x0E, 0x09] => Ok(ToolType::StarAmplifier), + [0x03, 0x0E, 0x0A] => Ok(ToolType::BookOfHitogata), + [0x03, 0x0E, 0x0B] => Ok(ToolType::HeartOfChuChu), + [0x03, 0x0E, 0x0C] => Ok(ToolType::PartsOfEggBlaster), + [0x03, 0x0E, 0x0D] => Ok(ToolType::HeartOfAngel), + [0x03, 0x0E, 0x0E] => Ok(ToolType::HeartOfDevil), + [0x03, 0x0E, 0x0F] => Ok(ToolType::KitOfHamburger), + [0x03, 0x0E, 0x10] => Ok(ToolType::PanthersSpirit), + [0x03, 0x0E, 0x11] => Ok(ToolType::KitOfMark3), + [0x03, 0x0E, 0x12] => Ok(ToolType::KitOfMasterSystem), + [0x03, 0x0E, 0x13] => Ok(ToolType::KitOfGenesis), + [0x03, 0x0E, 0x14] => Ok(ToolType::KitOfSegaSaturn), + [0x03, 0x0E, 0x15] => Ok(ToolType::KitOfDreamcast), + [0x03, 0x0E, 0x16] => Ok(ToolType::AmplifierOfResta), + [0x03, 0x0E, 0x17] => Ok(ToolType::AmplifierOfAnti), + [0x03, 0x0E, 0x18] => Ok(ToolType::AmplifierOfShifta), + [0x03, 0x0E, 0x19] => Ok(ToolType::AmplifierOfDeband), + [0x03, 0x0E, 0x1A] => Ok(ToolType::AmplifierOfFoie), + [0x03, 0x0E, 0x1B] => Ok(ToolType::AmplifierOfGifoie), + [0x03, 0x0E, 0x1C] => Ok(ToolType::AmplifierOfRafoie), + [0x03, 0x0E, 0x1D] => Ok(ToolType::AmplifierOfBarta), + [0x03, 0x0E, 0x1E] => Ok(ToolType::AmplifierOfGibarta), + [0x03, 0x0E, 0x1F] => Ok(ToolType::AmplifierOfRabarta), + [0x03, 0x0E, 0x20] => Ok(ToolType::AmplifierOfZonde), + [0x03, 0x0E, 0x21] => Ok(ToolType::AmplifierOfGizonde), + [0x03, 0x0E, 0x22] => Ok(ToolType::AmplifierOfRazonde), + [0x03, 0x0E, 0x23] => Ok(ToolType::AmplifierOfRed), + [0x03, 0x0E, 0x24] => Ok(ToolType::AmplifierOfBlue), + [0x03, 0x0E, 0x25] => Ok(ToolType::AmplifierOfYellow), + [0x03, 0x0E, 0x26] => Ok(ToolType::HeartOfKapuKapu), + [0x03, 0x0E, 0x27] => Ok(ToolType::PhotonBooster), + [0x03, 0x0F, 0x00] => Ok(ToolType::Addslot), + [0x03, 0x10, 0x00] => Ok(ToolType::PhotonDrop), + [0x03, 0x10, 0x01] => Ok(ToolType::PhotonSphere), + [0x03, 0x10, 0x02] => Ok(ToolType::PhotonCrystal), + [0x03, 0x10, 0x03] => Ok(ToolType::SecretTicket), + [0x03, 0x10, 0x04] => Ok(ToolType::PhotonTicket), + [0x03, 0x11, 0x00] => Ok(ToolType::BookOfKatana1), + [0x03, 0x11, 0x01] => Ok(ToolType::BookOfKatana2), + [0x03, 0x11, 0x02] => Ok(ToolType::BookOfKatana3), + [0x03, 0x12, 0x00] => Ok(ToolType::WeaponsBronzeBadge), + [0x03, 0x12, 0x01] => Ok(ToolType::WeaponsSilverBadge), + [0x03, 0x12, 0x02] => Ok(ToolType::WeaponsGoldBadge), + [0x03, 0x12, 0x03] => Ok(ToolType::WeaponsCrystalBadge), + [0x03, 0x12, 0x04] => Ok(ToolType::WeaponsSteelBadge), + [0x03, 0x12, 0x05] => Ok(ToolType::WeaponsAluminumBadge), + [0x03, 0x12, 0x06] => Ok(ToolType::WeaponsLeatherBadge), + [0x03, 0x12, 0x07] => Ok(ToolType::WeaponsBoneBadge), + [0x03, 0x12, 0x08] => Ok(ToolType::LetterOfAppreciation), + [0x03, 0x12, 0x09] => Ok(ToolType::ItemTicket), + [0x03, 0x12, 0x0A] => Ok(ToolType::ValentinesChocolate), + [0x03, 0x12, 0x0B] => Ok(ToolType::NewYearsCard), + [0x03, 0x12, 0x0C] => Ok(ToolType::ChristmasCard), + [0x03, 0x12, 0x0D] => Ok(ToolType::BirthdayCard), + [0x03, 0x12, 0x0E] => Ok(ToolType::ProofOfSonicTeam), + [0x03, 0x12, 0x0F] => Ok(ToolType::SpecialEventTicket), + [0x03, 0x12, 0x10] => Ok(ToolType::FlowerBouquet), + [0x03, 0x12, 0x11] => Ok(ToolType::Cake), + [0x03, 0x12, 0x12] => Ok(ToolType::Accessories), + [0x03, 0x12, 0x13] => Ok(ToolType::MrNakasBusinessCard), + [0x03, 0x13, 0x00] => Ok(ToolType::Present), + [0x03, 0x14, 0x00] => Ok(ToolType::Chocolate), + [0x03, 0x14, 0x01] => Ok(ToolType::Candy), + [0x03, 0x14, 0x02] => Ok(ToolType::Cake2), + [0x03, 0x14, 0x03] => Ok(ToolType::WeaponsSilverBadge2), + [0x03, 0x14, 0x04] => Ok(ToolType::WeaponsGoldBadge2), + [0x03, 0x14, 0x05] => Ok(ToolType::WeaponsCrystalBadge2), + [0x03, 0x14, 0x06] => Ok(ToolType::WeaponsSteelBadge2), + [0x03, 0x14, 0x07] => Ok(ToolType::WeaponsAluminumBadge2), + [0x03, 0x14, 0x08] => Ok(ToolType::WeaponsLeatherBadge2), + [0x03, 0x14, 0x09] => Ok(ToolType::WeaponsBoneBadge2), + [0x03, 0x14, 0x0A] => Ok(ToolType::Bouquet), + [0x03, 0x14, 0x0B] => Ok(ToolType::Decoction), + [0x03, 0x15, 0x00] => Ok(ToolType::ChristmasPresent), + [0x03, 0x15, 0x01] => Ok(ToolType::EasterEgg), + [0x03, 0x15, 0x02] => Ok(ToolType::JackOLantern), + [0x03, 0x16, 0x00] => Ok(ToolType::DiskVol1WeddingMarch), + [0x03, 0x16, 0x01] => Ok(ToolType::DiskVol2DayLight), + [0x03, 0x16, 0x02] => Ok(ToolType::DiskVol3BurningRangers), + [0x03, 0x16, 0x03] => Ok(ToolType::DiskVol4OpenYourHeart), + [0x03, 0x16, 0x04] => Ok(ToolType::DiskVol5LiveLearn), + [0x03, 0x16, 0x05] => Ok(ToolType::DiskVol6Nights), + [0x03, 0x16, 0x06] => Ok(ToolType::DiskVol7EndingThemePianoVer), + [0x03, 0x16, 0x07] => Ok(ToolType::DiskVol8HeartToHeart), + [0x03, 0x16, 0x08] => Ok(ToolType::DiskVol9StrangeBlue), + [0x03, 0x16, 0x09] => Ok(ToolType::DiskVol10ReunionSystem), + [0x03, 0x16, 0x0A] => Ok(ToolType::DiskVol11Pinnacles), + [0x03, 0x16, 0x0B] => Ok(ToolType::DiskVol12FightInsideTheSpaceship), + [0x03, 0x17, 0x00] => Ok(ToolType::HuntersReport), + [0x03, 0x17, 0x01] => Ok(ToolType::HuntersReport2), + [0x03, 0x17, 0x02] => Ok(ToolType::HuntersReport3), + [0x03, 0x17, 0x03] => Ok(ToolType::HuntersReport4), + [0x03, 0x17, 0x04] => Ok(ToolType::HuntersReport5), + [0x03, 0x18, 0x00] => Ok(ToolType::Tablet), + [0x03, 0x18, 0x01] => Ok(ToolType::Unknown2), + [0x03, 0x18, 0x02] => Ok(ToolType::DragonScale), + [0x03, 0x18, 0x03] => Ok(ToolType::HeavenStrikerCoat), + [0x03, 0x18, 0x04] => Ok(ToolType::PioneerParts), + [0x03, 0x18, 0x05] => Ok(ToolType::AmitiesMemo), + [0x03, 0x18, 0x06] => Ok(ToolType::HeartOfMorolian), + [0x03, 0x18, 0x07] => Ok(ToolType::RappysBeak), + [0x03, 0x18, 0x08] => Ok(ToolType::YahoosEngine), + [0x03, 0x18, 0x09] => Ok(ToolType::DPhotonCore), + [0x03, 0x18, 0x0A] => Ok(ToolType::LibertaKit), + [0x03, 0x18, 0x0B] => Ok(ToolType::CellOfMag0503), + [0x03, 0x18, 0x0C] => Ok(ToolType::CellOfMag0504), + [0x03, 0x18, 0x0D] => Ok(ToolType::CellOfMag0505), + [0x03, 0x18, 0x0E] => Ok(ToolType::CellOfMag0506), + [0x03, 0x18, 0x0F] => Ok(ToolType::CellOfMag0507), + [0x03, 0x19, 0x00] => Ok(ToolType::TeamPoints500), + [0x03, 0x19, 0x01] => Ok(ToolType::TeamPoints1000), + [0x03, 0x19, 0x02] => Ok(ToolType::TeamPoints5000), + [0x03, 0x19, 0x03] => Ok(ToolType::TeamPoints10000), + _ => Err(ItemParseError::InvalidToolType), + } + } } @@ -411,4 +597,16 @@ impl Tool { result[5] = len as u8; result } + + pub fn from_bytes(data: [u8; 16]) -> Result { + let t = ToolType::parse_type([data[0], data[1], data[2]]); + if t.is_ok() { + Ok(Tool { + tool: t.unwrap(), + }) + } + else { + Err(ItemParseError::InvalidToolBytes) // TODO: error handling if wrong bytes are given + } + } } diff --git a/src/entity/item/unit.rs b/src/entity/item/unit.rs index 617e79d..061551a 100644 --- a/src/entity/item/unit.rs +++ b/src/entity/item/unit.rs @@ -1,5 +1,10 @@ use serde::{Serialize, Deserialize}; +#[derive(Debug, Copy, Clone)] +pub enum ItemParseError { + InvalidUnitBytes, + InvalidUnitType, +} #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] pub enum UnitType { @@ -210,6 +215,112 @@ impl UnitType { UnitType::PbIncrease => [0x01, 0x03, 0x63], } } + + pub fn parse_type(data: [u8; 3]) -> Result { + match data { + [0x01, 0x03, 0x00] => Ok(UnitType::KnightPower), + [0x01, 0x03, 0x01] => Ok(UnitType::GeneralPower), + [0x01, 0x03, 0x02] => Ok(UnitType::OgrePower), + [0x01, 0x03, 0x03] => Ok(UnitType::GodPower), + [0x01, 0x03, 0x04] => Ok(UnitType::PriestMind), + [0x01, 0x03, 0x05] => Ok(UnitType::GeneralMind), + [0x01, 0x03, 0x06] => Ok(UnitType::AngelMind), + [0x01, 0x03, 0x07] => Ok(UnitType::GodMind), + [0x01, 0x03, 0x08] => Ok(UnitType::MarksmanArm), + [0x01, 0x03, 0x09] => Ok(UnitType::GeneralArm), + [0x01, 0x03, 0x0A] => Ok(UnitType::ElfArm), + [0x01, 0x03, 0x0B] => Ok(UnitType::GodArm), + [0x01, 0x03, 0x0C] => Ok(UnitType::ThiefLegs), + [0x01, 0x03, 0x0D] => Ok(UnitType::GeneralLegs), + [0x01, 0x03, 0x0E] => Ok(UnitType::ElfLegs), + [0x01, 0x03, 0x0F] => Ok(UnitType::GodLegs), + [0x01, 0x03, 0x10] => Ok(UnitType::DiggerHp), + [0x01, 0x03, 0x11] => Ok(UnitType::GeneralHp), + [0x01, 0x03, 0x12] => Ok(UnitType::DragonHp), + [0x01, 0x03, 0x13] => Ok(UnitType::GodHp), + [0x01, 0x03, 0x14] => Ok(UnitType::MagicianTp), + [0x01, 0x03, 0x15] => Ok(UnitType::GeneralTp), + [0x01, 0x03, 0x16] => Ok(UnitType::AngelTp), + [0x01, 0x03, 0x17] => Ok(UnitType::GodTp), + [0x01, 0x03, 0x18] => Ok(UnitType::WarriorBody), + [0x01, 0x03, 0x19] => Ok(UnitType::GeneralBody), + [0x01, 0x03, 0x1A] => Ok(UnitType::MetalBody), + [0x01, 0x03, 0x1B] => Ok(UnitType::GodBody), + [0x01, 0x03, 0x1C] => Ok(UnitType::AngelLuck), + [0x01, 0x03, 0x1D] => Ok(UnitType::GodLuck), + [0x01, 0x03, 0x1E] => Ok(UnitType::MasterAbility), + [0x01, 0x03, 0x1F] => Ok(UnitType::HeroAbility), + [0x01, 0x03, 0x20] => Ok(UnitType::GodAbility), + [0x01, 0x03, 0x21] => Ok(UnitType::ResistFire), + [0x01, 0x03, 0x22] => Ok(UnitType::ResistFlame), + [0x01, 0x03, 0x23] => Ok(UnitType::ResistBurning), + [0x01, 0x03, 0x24] => Ok(UnitType::ResistCold), + [0x01, 0x03, 0x25] => Ok(UnitType::ResistFreeze), + [0x01, 0x03, 0x26] => Ok(UnitType::ResistBlizzard), + [0x01, 0x03, 0x27] => Ok(UnitType::ResistShock), + [0x01, 0x03, 0x28] => Ok(UnitType::ResistThunder), + [0x01, 0x03, 0x29] => Ok(UnitType::ResistStorm), + [0x01, 0x03, 0x2A] => Ok(UnitType::ResistLight), + [0x01, 0x03, 0x2B] => Ok(UnitType::ResistSaint), + [0x01, 0x03, 0x2C] => Ok(UnitType::ResistHoly), + [0x01, 0x03, 0x2D] => Ok(UnitType::ResistDark), + [0x01, 0x03, 0x2E] => Ok(UnitType::ResistEvil), + [0x01, 0x03, 0x2F] => Ok(UnitType::ResistDevil), + [0x01, 0x03, 0x30] => Ok(UnitType::AllResist), + [0x01, 0x03, 0x31] => Ok(UnitType::SuperResist), + [0x01, 0x03, 0x32] => Ok(UnitType::PerfectResist), + [0x01, 0x03, 0x33] => Ok(UnitType::HpRestorate), + [0x01, 0x03, 0x34] => Ok(UnitType::HpGenerate), + [0x01, 0x03, 0x35] => Ok(UnitType::HpRevival), + [0x01, 0x03, 0x36] => Ok(UnitType::TpRestorate), + [0x01, 0x03, 0x37] => Ok(UnitType::TpGenerate), + [0x01, 0x03, 0x38] => Ok(UnitType::TpRevival), + [0x01, 0x03, 0x39] => Ok(UnitType::PbAmplifier), + [0x01, 0x03, 0x3A] => Ok(UnitType::PbGenerate), + [0x01, 0x03, 0x3B] => Ok(UnitType::PbCreate), + [0x01, 0x03, 0x3C] => Ok(UnitType::WizardTechnique), + [0x01, 0x03, 0x3D] => Ok(UnitType::DevilTechnique), + [0x01, 0x03, 0x3E] => Ok(UnitType::GodTechnique), + [0x01, 0x03, 0x3F] => Ok(UnitType::GeneralBattle), + [0x01, 0x03, 0x40] => Ok(UnitType::DevilBattle), + [0x01, 0x03, 0x41] => Ok(UnitType::GodBattle), + [0x01, 0x03, 0x42] => Ok(UnitType::CurePoison), + [0x01, 0x03, 0x43] => Ok(UnitType::CureParalysis), + [0x01, 0x03, 0x44] => Ok(UnitType::CureSlow), + [0x01, 0x03, 0x45] => Ok(UnitType::CureConfuse), + [0x01, 0x03, 0x46] => Ok(UnitType::CureFreeze), + [0x01, 0x03, 0x47] => Ok(UnitType::CureShock), + [0x01, 0x03, 0x48] => Ok(UnitType::YasakaniMagatama), + [0x01, 0x03, 0x49] => Ok(UnitType::V101), + [0x01, 0x03, 0x4A] => Ok(UnitType::V501), + [0x01, 0x03, 0x4B] => Ok(UnitType::V502), + [0x01, 0x03, 0x4C] => Ok(UnitType::V801), + [0x01, 0x03, 0x4D] => Ok(UnitType::Limiter), + [0x01, 0x03, 0x4E] => Ok(UnitType::Adept), + [0x01, 0x03, 0x4F] => Ok(UnitType::SwordsmanLore), + [0x01, 0x03, 0x50] => Ok(UnitType::ProofOfSwordSaint), + [0x01, 0x03, 0x51] => Ok(UnitType::Smartlink), + [0x01, 0x03, 0x52] => Ok(UnitType::DivineProtection), + [0x01, 0x03, 0x53] => Ok(UnitType::HeavenlyBattle), + [0x01, 0x03, 0x54] => Ok(UnitType::HeavenlyPower), + [0x01, 0x03, 0x55] => Ok(UnitType::HeavenlyMind), + [0x01, 0x03, 0x56] => Ok(UnitType::HeavenlyArms), + [0x01, 0x03, 0x57] => Ok(UnitType::HeavenlyLegs), + [0x01, 0x03, 0x58] => Ok(UnitType::HeavenlyBody), + [0x01, 0x03, 0x59] => Ok(UnitType::HeavenlyLuck), + [0x01, 0x03, 0x5A] => Ok(UnitType::HeavenlyAbility), + [0x01, 0x03, 0x5B] => Ok(UnitType::CenturionAbility), + [0x01, 0x03, 0x5C] => Ok(UnitType::FriendRing), + [0x01, 0x03, 0x5D] => Ok(UnitType::HeavenlyHp), + [0x01, 0x03, 0x5E] => Ok(UnitType::HeavenlyTp), + [0x01, 0x03, 0x5F] => Ok(UnitType::HeavenlyResist), + [0x01, 0x03, 0x60] => Ok(UnitType::HeavenlyTechnique), + [0x01, 0x03, 0x61] => Ok(UnitType::HpRessurection), + [0x01, 0x03, 0x62] => Ok(UnitType::TpRessurection), + [0x01, 0x03, 0x63] => Ok(UnitType::PbIncrease), + _ => Err(ItemParseError::InvalidUnitType), + } + } } #[derive(Debug, Copy, Clone, PartialEq)] @@ -253,4 +364,26 @@ impl Unit { result } + + pub fn from_bytes(data: [u8; 16]) -> Result { + let u = UnitType::parse_type([data[0], data[1], data[2]]); + if u.is_ok() { + let mut m = None; + match u16::from_le_bytes([data[7], data[8]]) { + 0x03 => m = Some(UnitModifier::PlusPlus), + 0x01 => m = Some(UnitModifier::Plus), + 0xFEFF => m = Some(UnitModifier::Minus), + 0xFFFF => m = Some(UnitModifier::MinusMinus), + _ => m = None, + } + + Ok(Unit{ + unit: u.unwrap(), + modifier: m, + }) + } + else { + Err(ItemParseError::InvalidUnitBytes) // TODO: error handling if wrong bytes are given + } + } } diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index 286342a..4421d53 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -1,5 +1,13 @@ use serde::{Serialize, Deserialize}; +#[derive(Debug, Copy, Clone)] +pub enum ItemParseError { + InvalidWeaponBytes, + InvalidWeaponType, + InvalidWeaponGrind, + InvalidWeaponSpecial, + InvalidWeaponAttribute, +} #[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] pub enum Attribute { @@ -10,6 +18,19 @@ pub enum Attribute { Hit } +impl Attribute { + pub fn from(data: u8) -> Option { + match data { + 1 => Some(Attribute::Native), + 2 => Some(Attribute::ABeast), + 3 => Some(Attribute::Machine), + 4 => Some(Attribute::Dark), + 5 => Some(Attribute::Hit), + _ => None, + } + } +} + #[derive(Debug, Copy, Clone, PartialEq)] pub struct WeaponAttribute { pub attr: Attribute, @@ -71,6 +92,52 @@ impl WeaponSpecial { pub fn value(&self) -> u8 { *self as u8 } + + pub fn from(data: u8) -> Option { + match data { + 1 => Some(WeaponSpecial::Draw), + 2 => Some(WeaponSpecial::Drain), + 3 => Some(WeaponSpecial::Fill), + 4 => Some(WeaponSpecial::Gush), + 5 => Some(WeaponSpecial::Heart), + 6 => Some(WeaponSpecial::Mind), + 7 => Some(WeaponSpecial::Soul), + 8 => Some(WeaponSpecial::Geist), + 9 => Some(WeaponSpecial::Masters), + 10 => Some(WeaponSpecial::Lords), + 11 => Some(WeaponSpecial::Kings), + 12 => Some(WeaponSpecial::Charge), + 13 => Some(WeaponSpecial::Spirit), + 14 => Some(WeaponSpecial::Berserk), + 15 => Some(WeaponSpecial::Ice), + 16 => Some(WeaponSpecial::Frost), + 17 => Some(WeaponSpecial::Freeze), + 18 => Some(WeaponSpecial::Blizzard), + 19 => Some(WeaponSpecial::Bind), + 20 => Some(WeaponSpecial::Hold), + 21 => Some(WeaponSpecial::Seize), + 22 => Some(WeaponSpecial::Arrest), + 23 => Some(WeaponSpecial::Heat), + 24 => Some(WeaponSpecial::Fire), + 25 => Some(WeaponSpecial::Flame), + 26 => Some(WeaponSpecial::Burning), + 27 => Some(WeaponSpecial::Shock), + 28 => Some(WeaponSpecial::Thunder), + 29 => Some(WeaponSpecial::Storm), + 30 => Some(WeaponSpecial::Tempest), + 31 => Some(WeaponSpecial::Dim), + 32 => Some(WeaponSpecial::Shadow), + 33 => Some(WeaponSpecial::Dark), + 34 => Some(WeaponSpecial::Hell), + 35 => Some(WeaponSpecial::Panic), + 36 => Some(WeaponSpecial::Riot), + 37 => Some(WeaponSpecial::Havoc), + 38 => Some(WeaponSpecial::Chaos), + 39 => Some(WeaponSpecial::Devils), + 40 => Some(WeaponSpecial::Demons), + _ => None, + } + } } #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)] @@ -864,6 +931,403 @@ impl WeaponType { WeaponType::TypewaWand => [0x00, 0xEC, 0x00], } } + + pub fn parse_type(data: [u8; 3]) -> Result { + match data { + [0x00, 0x01, 0x00] => Ok(WeaponType::Saber), + [0x00, 0x01, 0x01] => Ok(WeaponType::Brand), + [0x00, 0x01, 0x02] => Ok(WeaponType::Buster), + [0x00, 0x01, 0x03] => Ok(WeaponType::Pallasch), + [0x00, 0x01, 0x04] => Ok(WeaponType::Gladius), + [0x00, 0x01, 0x05] => Ok(WeaponType::DbsSaber), + [0x00, 0x01, 0x06] => Ok(WeaponType::Kaladbolg), + [0x00, 0x01, 0x07] => Ok(WeaponType::Durandal), + [0x00, 0x01, 0x08] => Ok(WeaponType::Galatine), + [0x00, 0x02, 0x00] => Ok(WeaponType::Sword), + [0x00, 0x02, 0x01] => Ok(WeaponType::Gigush), + [0x00, 0x02, 0x02] => Ok(WeaponType::Breaker), + [0x00, 0x02, 0x03] => Ok(WeaponType::Claymore), + [0x00, 0x02, 0x04] => Ok(WeaponType::Calibur), + [0x00, 0x02, 0x05] => Ok(WeaponType::FlowensSword), + [0x00, 0x02, 0x06] => Ok(WeaponType::LastSurvivor), + [0x00, 0x02, 0x07] => Ok(WeaponType::DragonSlayer), + [0x00, 0x03, 0x00] => Ok(WeaponType::Dagger), + [0x00, 0x03, 0x01] => Ok(WeaponType::Knife), + [0x00, 0x03, 0x02] => Ok(WeaponType::Blade), + [0x00, 0x03, 0x03] => Ok(WeaponType::Edge), + [0x00, 0x03, 0x04] => Ok(WeaponType::Ripper), + [0x00, 0x03, 0x05] => Ok(WeaponType::BladeDance), + [0x00, 0x03, 0x06] => Ok(WeaponType::BloodyArt), + [0x00, 0x03, 0x07] => Ok(WeaponType::CrossScar), + [0x00, 0x03, 0x08] => Ok(WeaponType::ZeroDivide), + [0x00, 0x03, 0x09] => Ok(WeaponType::TwoKamui), + [0x00, 0x04, 0x00] => Ok(WeaponType::Partisan), + [0x00, 0x04, 0x01] => Ok(WeaponType::Halbert), + [0x00, 0x04, 0x02] => Ok(WeaponType::Glaive), + [0x00, 0x04, 0x03] => Ok(WeaponType::Berdys), + [0x00, 0x04, 0x04] => Ok(WeaponType::Gungnir), + [0x00, 0x04, 0x05] => Ok(WeaponType::Brionac), + [0x00, 0x04, 0x06] => Ok(WeaponType::Vjaya), + [0x00, 0x04, 0x07] => Ok(WeaponType::GaeBolg), + [0x00, 0x04, 0x08] => Ok(WeaponType::AsteronBelt), + [0x00, 0x05, 0x00] => Ok(WeaponType::Slicer), + [0x00, 0x05, 0x01] => Ok(WeaponType::Spinner), + [0x00, 0x05, 0x02] => Ok(WeaponType::Cutter), + [0x00, 0x05, 0x03] => Ok(WeaponType::Sawcer), + [0x00, 0x05, 0x04] => Ok(WeaponType::Diska), + [0x00, 0x05, 0x05] => Ok(WeaponType::SlicerOfAssassin), + [0x00, 0x05, 0x06] => Ok(WeaponType::DiskaOfLiberator), + [0x00, 0x05, 0x07] => Ok(WeaponType::DiskaOfBraveman), + [0x00, 0x05, 0x08] => Ok(WeaponType::Izmaela), + [0x00, 0x06, 0x00] => Ok(WeaponType::Handgun), + [0x00, 0x06, 0x01] => Ok(WeaponType::Autogun), + [0x00, 0x06, 0x02] => Ok(WeaponType::Lockgun), + [0x00, 0x06, 0x03] => Ok(WeaponType::Railgun), + [0x00, 0x06, 0x04] => Ok(WeaponType::Raygun), + [0x00, 0x06, 0x05] => Ok(WeaponType::Varista), + [0x00, 0x06, 0x06] => Ok(WeaponType::CustomRayVerOo), + [0x00, 0x06, 0x07] => Ok(WeaponType::Bravace), + [0x00, 0x06, 0x08] => Ok(WeaponType::TensionBlaster), + [0x00, 0x07, 0x00] => Ok(WeaponType::Rifle), + [0x00, 0x07, 0x01] => Ok(WeaponType::Sniper), + [0x00, 0x07, 0x02] => Ok(WeaponType::Blaster), + [0x00, 0x07, 0x03] => Ok(WeaponType::Beam), + [0x00, 0x07, 0x04] => Ok(WeaponType::Laser), + [0x00, 0x07, 0x05] => Ok(WeaponType::Visk235W), + [0x00, 0x07, 0x06] => Ok(WeaponType::WalsMk2), + [0x00, 0x07, 0x07] => Ok(WeaponType::Justy23St), + [0x00, 0x07, 0x08] => Ok(WeaponType::Rianov303snr), + [0x00, 0x07, 0x09] => Ok(WeaponType::Rianov303snr1), + [0x00, 0x07, 0x0A] => Ok(WeaponType::Rianov303snr2), + [0x00, 0x07, 0x0B] => Ok(WeaponType::Rianov303snr3), + [0x00, 0x07, 0x0C] => Ok(WeaponType::Rianov303snr4), + [0x00, 0x07, 0x0D] => Ok(WeaponType::Rianov303snr5), + [0x00, 0x08, 0x00] => Ok(WeaponType::Mechgun), + [0x00, 0x08, 0x01] => Ok(WeaponType::Assault), + [0x00, 0x08, 0x02] => Ok(WeaponType::Repeater), + [0x00, 0x08, 0x03] => Ok(WeaponType::Gatling), + [0x00, 0x08, 0x04] => Ok(WeaponType::Vulcan), + [0x00, 0x08, 0x05] => Ok(WeaponType::MA60Vise), + [0x00, 0x08, 0x06] => Ok(WeaponType::HS25Justice), + [0x00, 0x08, 0x07] => Ok(WeaponType::LK14Combat), + [0x00, 0x09, 0x00] => Ok(WeaponType::Shot), + [0x00, 0x09, 0x01] => Ok(WeaponType::Spread), + [0x00, 0x09, 0x02] => Ok(WeaponType::Cannon), + [0x00, 0x09, 0x03] => Ok(WeaponType::Launcher), + [0x00, 0x09, 0x04] => Ok(WeaponType::Arms), + [0x00, 0x09, 0x05] => Ok(WeaponType::CrushBullet), + [0x00, 0x09, 0x06] => Ok(WeaponType::MeteorSmash), + [0x00, 0x09, 0x07] => Ok(WeaponType::FinalImpact), + [0x00, 0x0A, 0x00] => Ok(WeaponType::Cane), + [0x00, 0x0A, 0x01] => Ok(WeaponType::Stick), + [0x00, 0x0A, 0x02] => Ok(WeaponType::Mace), + [0x00, 0x0A, 0x03] => Ok(WeaponType::Club), + [0x00, 0x0A, 0x04] => Ok(WeaponType::ClubOfLaconium), + [0x00, 0x0A, 0x05] => Ok(WeaponType::MaceOfAdaman), + [0x00, 0x0A, 0x06] => Ok(WeaponType::ClubOfZumiuran), + [0x00, 0x0A, 0x07] => Ok(WeaponType::Lollipop), + [0x00, 0x0B, 0x00] => Ok(WeaponType::Rod), + [0x00, 0x0B, 0x01] => Ok(WeaponType::Pole), + [0x00, 0x0B, 0x02] => Ok(WeaponType::Pillar), + [0x00, 0x0B, 0x03] => Ok(WeaponType::Striker), + [0x00, 0x0B, 0x04] => Ok(WeaponType::BattleVerge), + [0x00, 0x0B, 0x05] => Ok(WeaponType::BraveHammer), + [0x00, 0x0B, 0x06] => Ok(WeaponType::AliveAqhu), + [0x00, 0x0B, 0x07] => Ok(WeaponType::Valkyrie), + [0x00, 0x0C, 0x00] => Ok(WeaponType::Wand), + [0x00, 0x0C, 0x01] => Ok(WeaponType::Staff), + [0x00, 0x0C, 0x02] => Ok(WeaponType::Baton), + [0x00, 0x0C, 0x03] => Ok(WeaponType::Scepter), + [0x00, 0x0C, 0x04] => Ok(WeaponType::FireScepterAgni), + [0x00, 0x0C, 0x05] => Ok(WeaponType::IceStaffDagon), + [0x00, 0x0C, 0x06] => Ok(WeaponType::StormWandIndra), + [0x00, 0x0C, 0x07] => Ok(WeaponType::EarthWandBrownie), + [0x00, 0x0D, 0x00] => Ok(WeaponType::PhotonClaw), + [0x00, 0x0D, 0x01] => Ok(WeaponType::SilenceClaw), + [0x00, 0x0D, 0x02] => Ok(WeaponType::NeisClaw), + [0x00, 0x0D, 0x03] => Ok(WeaponType::PhoenixClaw), + [0x00, 0x0E, 0x00] => Ok(WeaponType::DoubleSaber), + [0x00, 0x0E, 0x01] => Ok(WeaponType::StagCutlery), + [0x00, 0x0E, 0x02] => Ok(WeaponType::TwinBrand), + [0x00, 0x0F, 0x00] => Ok(WeaponType::BraveKnuckle), + [0x00, 0x0F, 0x01] => Ok(WeaponType::AngryFist), + [0x00, 0x0F, 0x02] => Ok(WeaponType::GodHand), + [0x00, 0x0F, 0x03] => Ok(WeaponType::SonicKnuckle), + [0x00, 0x0F, 0x04] => Ok(WeaponType::Login), + [0x00, 0x10, 0x00] => Ok(WeaponType::Orotiagito), + [0x00, 0x10, 0x01] => Ok(WeaponType::Agito1975), + [0x00, 0x10, 0x02] => Ok(WeaponType::Agito1983), + [0x00, 0x10, 0x03] => Ok(WeaponType::Agito2001), + [0x00, 0x10, 0x04] => Ok(WeaponType::Agito1991), + [0x00, 0x10, 0x05] => Ok(WeaponType::Agito1977), + [0x00, 0x10, 0x06] => Ok(WeaponType::Agito1980), + [0x00, 0x10, 0x07] => Ok(WeaponType::Raikiri), + [0x00, 0x11, 0x00] => Ok(WeaponType::SoulEater), + [0x00, 0x11, 0x01] => Ok(WeaponType::SoulBanish), + [0x00, 0x12, 0x00] => Ok(WeaponType::SpreadNeedle), + [0x00, 0x13, 0x00] => Ok(WeaponType::HolyRay), + [0x00, 0x14, 0x00] => Ok(WeaponType::InfernoBazooka), + [0x00, 0x14, 0x01] => Ok(WeaponType::RamblingMay), + [0x00, 0x14, 0x02] => Ok(WeaponType::LK38Combat), + [0x00, 0x15, 0x00] => Ok(WeaponType::FlameVisit), + [0x00, 0x15, 0x01] => Ok(WeaponType::BurningVisit), + [0x00, 0x16, 0x00] => Ok(WeaponType::AkikosFryingPan), + [0x00, 0x17, 0x00] => Ok(WeaponType::SorcerersCane), + [0x00, 0x18, 0x00] => Ok(WeaponType::SBeatsBlade), + [0x00, 0x19, 0x00] => Ok(WeaponType::PArmssBlade), + [0x00, 0x1A, 0x00] => Ok(WeaponType::DelsabersBuster), + [0x00, 0x1B, 0x00] => Ok(WeaponType::BringersRifle), + [0x00, 0x1C, 0x00] => Ok(WeaponType::EggBlaster), + [0x00, 0x1D, 0x00] => Ok(WeaponType::PsychoWand), + [0x00, 0x1E, 0x00] => Ok(WeaponType::HeavenPunisher), + [0x00, 0x1F, 0x00] => Ok(WeaponType::LavisCannon), + [0x00, 0x20, 0x00] => Ok(WeaponType::VictorAxe), + [0x00, 0x20, 0x01] => Ok(WeaponType::LaconiumAxe), + [0x00, 0x21, 0x00] => Ok(WeaponType::ChainSawd), + [0x00, 0x22, 0x00] => Ok(WeaponType::Caduceus), + [0x00, 0x22, 0x01] => Ok(WeaponType::MercuriusRod), + [0x00, 0x23, 0x00] => Ok(WeaponType::StingTip), + [0x00, 0x24, 0x00] => Ok(WeaponType::MagicalPiece), + [0x00, 0x25, 0x00] => Ok(WeaponType::TechnicalCrozier), + [0x00, 0x26, 0x00] => Ok(WeaponType::SuppressedGun), + [0x00, 0x27, 0x00] => Ok(WeaponType::AncientSaber), + [0x00, 0x28, 0x00] => Ok(WeaponType::HarisenBattleFan), + [0x00, 0x29, 0x00] => Ok(WeaponType::Yamigarasu), + [0x00, 0x2A, 0x00] => Ok(WeaponType::AkikosWok), + [0x00, 0x2B, 0x00] => Ok(WeaponType::ToyHammer), + [0x00, 0x2C, 0x00] => Ok(WeaponType::Elysion), + [0x00, 0x2D, 0x00] => Ok(WeaponType::RedSaber), + [0x00, 0x2E, 0x00] => Ok(WeaponType::MeteorCudgel), + [0x00, 0x2F, 0x00] => Ok(WeaponType::MonkeyKingBar), + [0x00, 0x2F, 0x01] => Ok(WeaponType::BlackKingBar), + [0x00, 0x30, 0x00] => Ok(WeaponType::DoubleCannon), + [0x00, 0x30, 0x01] => Ok(WeaponType::Girasole), + [0x00, 0x31, 0x00] => Ok(WeaponType::HugeBattleFan), + [0x00, 0x32, 0x00] => Ok(WeaponType::TsumikiriJSword), + [0x00, 0x33, 0x00] => Ok(WeaponType::SealedJSword), + [0x00, 0x34, 0x00] => Ok(WeaponType::RedSword), + [0x00, 0x35, 0x00] => Ok(WeaponType::CrazyTune), + [0x00, 0x36, 0x00] => Ok(WeaponType::TwinChakram), + [0x00, 0x37, 0x00] => Ok(WeaponType::WokOfAkikosShop), + [0x00, 0x38, 0x00] => Ok(WeaponType::LavisBlade), + [0x00, 0x39, 0x00] => Ok(WeaponType::RedDagger), + [0x00, 0x3A, 0x00] => Ok(WeaponType::MadamsParasol), + [0x00, 0x3B, 0x00] => Ok(WeaponType::MadamsUmbrella), + [0x00, 0x3C, 0x00] => Ok(WeaponType::ImperialPick), + [0x00, 0x3D, 0x00] => Ok(WeaponType::Berdysh), + [0x00, 0x3E, 0x00] => Ok(WeaponType::RedPartisan), + [0x00, 0x3F, 0x00] => Ok(WeaponType::FlightCutter), + [0x00, 0x40, 0x00] => Ok(WeaponType::FlightFan), + [0x00, 0x41, 0x00] => Ok(WeaponType::RedSlicer), + [0x00, 0x42, 0x00] => Ok(WeaponType::HandgunGuld), + [0x00, 0x42, 0x01] => Ok(WeaponType::MasterRaven), + [0x00, 0x43, 0x00] => Ok(WeaponType::HandgunMilla), + [0x00, 0x43, 0x01] => Ok(WeaponType::LastSwan), + [0x00, 0x44, 0x00] => Ok(WeaponType::RedHandgun), + [0x00, 0x45, 0x00] => Ok(WeaponType::FrozenShooter), + [0x00, 0x45, 0x01] => Ok(WeaponType::SnowQueen), + [0x00, 0x46, 0x00] => Ok(WeaponType::AntiAndroidRifle), + [0x00, 0x47, 0x00] => Ok(WeaponType::RocketPunch), + [0x00, 0x48, 0x00] => Ok(WeaponType::SambaMaracas), + [0x00, 0x49, 0x00] => Ok(WeaponType::TwinPsychogun), + [0x00, 0x4A, 0x00] => Ok(WeaponType::DrillLauncher), + [0x00, 0x4B, 0x00] => Ok(WeaponType::GuldMilla), + [0x00, 0x4B, 0x01] => Ok(WeaponType::DualBird), + [0x00, 0x4C, 0x00] => Ok(WeaponType::RedMechgun), + [0x00, 0x4D, 0x00] => Ok(WeaponType::BelraCannon), + [0x00, 0x4E, 0x00] => Ok(WeaponType::PanzerFaust), + [0x00, 0x4E, 0x01] => Ok(WeaponType::IronFaust), + [0x00, 0x4F, 0x00] => Ok(WeaponType::SummitMoon), + [0x00, 0x50, 0x00] => Ok(WeaponType::Windmill), + [0x00, 0x51, 0x00] => Ok(WeaponType::EvilCurst), + [0x00, 0x52, 0x00] => Ok(WeaponType::FlowerCane), + [0x00, 0x53, 0x00] => Ok(WeaponType::HildebearsCane), + [0x00, 0x54, 0x00] => Ok(WeaponType::HildebluesCane), + [0x00, 0x55, 0x00] => Ok(WeaponType::RabbitWand), + [0x00, 0x56, 0x00] => Ok(WeaponType::PlantainLeaf), + [0x00, 0x56, 0x01] => Ok(WeaponType::Fatsia), + [0x00, 0x57, 0x00] => Ok(WeaponType::DemonicFork), + [0x00, 0x58, 0x00] => Ok(WeaponType::StrikerOfChao), + [0x00, 0x59, 0x00] => Ok(WeaponType::Broom), + [0x00, 0x5A, 0x00] => Ok(WeaponType::ProphetsOfMotav), + [0x00, 0x5B, 0x00] => Ok(WeaponType::TheSighOfAGod), + [0x00, 0x5C, 0x00] => Ok(WeaponType::TwinkleStar), + [0x00, 0x5D, 0x00] => Ok(WeaponType::PlantainFan), + [0x00, 0x5E, 0x00] => Ok(WeaponType::TwinBlaze), + [0x00, 0x5F, 0x00] => Ok(WeaponType::MarinasBag), + [0x00, 0x60, 0x00] => Ok(WeaponType::DragonsClaw), + [0x00, 0x61, 0x00] => Ok(WeaponType::PanthersClaw), + [0x00, 0x62, 0x00] => Ok(WeaponType::SRedsBlade), + [0x00, 0x63, 0x00] => Ok(WeaponType::PlantainHugeFan), + [0x00, 0x64, 0x00] => Ok(WeaponType::ChameleonScythe), + [0x00, 0x65, 0x00] => Ok(WeaponType::Yasminkov3000R), + [0x00, 0x66, 0x00] => Ok(WeaponType::AnoRifle), + [0x00, 0x67, 0x00] => Ok(WeaponType::BaranzLauncher), + [0x00, 0x68, 0x00] => Ok(WeaponType::BranchOfPakupaku), + [0x00, 0x69, 0x00] => Ok(WeaponType::HeartOfPoumn), + [0x00, 0x6A, 0x00] => Ok(WeaponType::Yasminkov2000H), + [0x00, 0x6B, 0x00] => Ok(WeaponType::Yasminkov7000V), + [0x00, 0x6C, 0x00] => Ok(WeaponType::Yasminkov9000M), + [0x00, 0x6D, 0x00] => Ok(WeaponType::MaserBeam), + [0x00, 0x6D, 0x01] => Ok(WeaponType::PowerMaser), + [0x00, 0x6E, 0x00] => Ok(WeaponType::GameMagazne), + [0x00, 0x6E, 0x01] => Ok(WeaponType::Login2), + [0x00, 0x6F, 0x00] => Ok(WeaponType::FlowerBouquet), + [0x00, 0x89, 0x00] => Ok(WeaponType::Musashi), + [0x00, 0x89, 0x01] => Ok(WeaponType::Yamato), + [0x00, 0x89, 0x02] => Ok(WeaponType::Asuka), + [0x00, 0x89, 0x03] => Ok(WeaponType::SangeYasha), + [0x00, 0x8A, 0x00] => Ok(WeaponType::Sange), + [0x00, 0x8A, 0x01] => Ok(WeaponType::Yasha), + [0x00, 0x8A, 0x02] => Ok(WeaponType::Kamui), + [0x00, 0x8B, 0x00] => Ok(WeaponType::PhotonLauncher), + [0x00, 0x8B, 0x01] => Ok(WeaponType::GuiltyLight), + [0x00, 0x8B, 0x02] => Ok(WeaponType::RedScorpio), + [0x00, 0x8B, 0x03] => Ok(WeaponType::PhononMaser), + [0x00, 0x8C, 0x00] => Ok(WeaponType::Talis), + [0x00, 0x8C, 0x01] => Ok(WeaponType::Mahu), + [0x00, 0x8C, 0x02] => Ok(WeaponType::Hitogata), + [0x00, 0x8C, 0x03] => Ok(WeaponType::DancingHitogata), + [0x00, 0x8C, 0x04] => Ok(WeaponType::Kunai), + [0x00, 0x8D, 0x00] => Ok(WeaponType::Nug2000Bazooka), + [0x00, 0x8E, 0x00] => Ok(WeaponType::SBerillsHands0), + [0x00, 0x8E, 0x01] => Ok(WeaponType::SBerillsHands1), + [0x00, 0x8F, 0x00] => Ok(WeaponType::FlowensSword3060), + [0x00, 0x8F, 0x01] => Ok(WeaponType::FlowensSword3064), + [0x00, 0x8F, 0x02] => Ok(WeaponType::FlowensSword3067), + [0x00, 0x8F, 0x03] => Ok(WeaponType::FlowensSword3073), + [0x00, 0x8F, 0x04] => Ok(WeaponType::FlowensSword3077), + [0x00, 0x8F, 0x05] => Ok(WeaponType::FlowensSword3082), + [0x00, 0x8F, 0x06] => Ok(WeaponType::FlowensSword3083), + [0x00, 0x8F, 0x07] => Ok(WeaponType::FlowensSword3084), + [0x00, 0x8F, 0x08] => Ok(WeaponType::FlowensSword3079), + [0x00, 0x90, 0x00] => Ok(WeaponType::DbsSaber3062), + [0x00, 0x90, 0x01] => Ok(WeaponType::DbsSaber3067), + [0x00, 0x90, 0x02] => Ok(WeaponType::DbsSaber3069Chris), + [0x00, 0x90, 0x03] => Ok(WeaponType::DbsSaber3064), + [0x00, 0x90, 0x04] => Ok(WeaponType::DbsSaber3069Torato), + [0x00, 0x90, 0x05] => Ok(WeaponType::DbsSaber3073), + [0x00, 0x90, 0x06] => Ok(WeaponType::DbsSaber3070), + [0x00, 0x90, 0x07] => Ok(WeaponType::DbsSaber3075), + [0x00, 0x90, 0x08] => Ok(WeaponType::DbsSaber3077), + [0x00, 0x91, 0x00] => Ok(WeaponType::GiGueBazooka), + [0x00, 0x92, 0x00] => Ok(WeaponType::Guardianna), + [0x00, 0x93, 0x00] => Ok(WeaponType::ViridiaCard), + [0x00, 0x93, 0x01] => Ok(WeaponType::GreenillCard), + [0x00, 0x93, 0x02] => Ok(WeaponType::SkylyCard), + [0x00, 0x93, 0x03] => Ok(WeaponType::BluefullCard), + [0x00, 0x93, 0x04] => Ok(WeaponType::PurplenumCard), + [0x00, 0x93, 0x05] => Ok(WeaponType::PinkalCard), + [0x00, 0x93, 0x06] => Ok(WeaponType::RedriaCard), + [0x00, 0x93, 0x07] => Ok(WeaponType::OranCard), + [0x00, 0x93, 0x08] => Ok(WeaponType::YellowbozeCard), + [0x00, 0x93, 0x09] => Ok(WeaponType::WhitillCard), + [0x00, 0x94, 0x00] => Ok(WeaponType::MorningGlory), + [0x00, 0x95, 0x00] => Ok(WeaponType::PartisanOfLightning), + [0x00, 0x96, 0x00] => Ok(WeaponType::GalWind), + [0x00, 0x97, 0x00] => Ok(WeaponType::Zanba), + [0x00, 0x98, 0x00] => Ok(WeaponType::RikasClaw), + [0x00, 0x99, 0x00] => Ok(WeaponType::AngelHarp), + [0x00, 0x9A, 0x00] => Ok(WeaponType::DemolitionComet), + [0x00, 0x9B, 0x00] => Ok(WeaponType::NeisClaw2), + [0x00, 0x9C, 0x00] => Ok(WeaponType::RainbowBaton), + [0x00, 0x9D, 0x00] => Ok(WeaponType::DarkFlow), + [0x00, 0x9E, 0x00] => Ok(WeaponType::DarkMeteor), + [0x00, 0x9F, 0x00] => Ok(WeaponType::DarkBridge), + [0x00, 0xA0, 0x00] => Ok(WeaponType::GAssassinsSabers), + [0x00, 0xA1, 0x00] => Ok(WeaponType::RappysFan), + [0x00, 0xA2, 0x00] => Ok(WeaponType::BoomasClaw), + [0x00, 0xA2, 0x01] => Ok(WeaponType::GoboomasClaw), + [0x00, 0xA2, 0x02] => Ok(WeaponType::GigoboomasClaw), + [0x00, 0xA3, 0x00] => Ok(WeaponType::RubyBullet), + [0x00, 0xA4, 0x00] => Ok(WeaponType::AmoreRose), + [0x00, 0xAA, 0x00] => Ok(WeaponType::SlicerOfFanatic), + [0x00, 0xAB, 0x00] => Ok(WeaponType::LameDArgent), + [0x00, 0xAC, 0x00] => Ok(WeaponType::Excalibur), + [0x00, 0xAD, 0x00] => Ok(WeaponType::RageDeFeu), + [0x00, 0xAD, 0x01] => Ok(WeaponType::RageDeFeu2), + [0x00, 0xAD, 0x02] => Ok(WeaponType::RageDeFeu3), + [0x00, 0xAD, 0x03] => Ok(WeaponType::RageDeFeu4), + [0x00, 0xAE, 0x00] => Ok(WeaponType::DaisyChain), + [0x00, 0xAF, 0x00] => Ok(WeaponType::OphelieSeize), + [0x00, 0xB0, 0x00] => Ok(WeaponType::MilleMarteaux), + [0x00, 0xB1, 0x00] => Ok(WeaponType::LeCogneur), + [0x00, 0xB2, 0x00] => Ok(WeaponType::CommanderBlade), + [0x00, 0xB3, 0x00] => Ok(WeaponType::Vivienne), + [0x00, 0xB4, 0x00] => Ok(WeaponType::Kusanagi), + [0x00, 0xB5, 0x00] => Ok(WeaponType::SacredDuster), + [0x00, 0xB6, 0x00] => Ok(WeaponType::Guren), + [0x00, 0xB7, 0x00] => Ok(WeaponType::Shouren), + [0x00, 0xB8, 0x00] => Ok(WeaponType::Jizai), + [0x00, 0xB9, 0x00] => Ok(WeaponType::Flamberge), + [0x00, 0xBA, 0x00] => Ok(WeaponType::Yunchang), + [0x00, 0xBB, 0x00] => Ok(WeaponType::SnakeSpire), + [0x00, 0xBC, 0x00] => Ok(WeaponType::FlapjackFlapper), + [0x00, 0xBD, 0x00] => Ok(WeaponType::Getsugasan), + [0x00, 0xBE, 0x00] => Ok(WeaponType::Maguwa), + [0x00, 0xBF, 0x00] => Ok(WeaponType::HeavenStriker), + [0x00, 0xC0, 0x00] => Ok(WeaponType::CannonRouge), + [0x00, 0xC1, 0x00] => Ok(WeaponType::MeteorRouge), + [0x00, 0xC2, 0x00] => Ok(WeaponType::Solferino), + [0x00, 0xC3, 0x00] => Ok(WeaponType::Clio), + [0x00, 0xC4, 0x00] => Ok(WeaponType::SirenGlassHammer), + [0x00, 0xC5, 0x00] => Ok(WeaponType::GlideDivine), + [0x00, 0xC6, 0x00] => Ok(WeaponType::Shichishito), + [0x00, 0xC7, 0x00] => Ok(WeaponType::Murasame), + [0x00, 0xC8, 0x00] => Ok(WeaponType::DaylightScar), + [0x00, 0xC9, 0x00] => Ok(WeaponType::Decalog), + [0x00, 0xCA, 0x00] => Ok(WeaponType::FifthAnnivBlade), + [0x00, 0xCB, 0x00] => Ok(WeaponType::TyrellsParasol), + [0x00, 0xCC, 0x00] => Ok(WeaponType::AkikosCleaver), + [0x00, 0xCD, 0x00] => Ok(WeaponType::Tanegashima), + [0x00, 0xCE, 0x00] => Ok(WeaponType::TreeClippers), + [0x00, 0xCF, 0x00] => Ok(WeaponType::NiceShot), + [0x00, 0xD0, 0x00] => Ok(WeaponType::Unknown3), + [0x00, 0xD1, 0x00] => Ok(WeaponType::Unknown4), + [0x00, 0xD2, 0x00] => Ok(WeaponType::AnoBazooka), + [0x00, 0xD3, 0x00] => Ok(WeaponType::Synthesizer), + [0x00, 0xD4, 0x00] => Ok(WeaponType::BambooSpear), + [0x00, 0xD5, 0x00] => Ok(WeaponType::KaneiTsuho), + [0x00, 0xD6, 0x00] => Ok(WeaponType::Jitte), + [0x00, 0xD7, 0x00] => Ok(WeaponType::ButterflyNet), + [0x00, 0xD8, 0x00] => Ok(WeaponType::Syringe), + [0x00, 0xD9, 0x00] => Ok(WeaponType::Battledore), + [0x00, 0xDA, 0x00] => Ok(WeaponType::Racket), + [0x00, 0xDB, 0x00] => Ok(WeaponType::Hammer), + [0x00, 0xDC, 0x00] => Ok(WeaponType::GreatBouquet), + [0x00, 0xDD, 0x00] => Ok(WeaponType::TypesaSaber), + [0x00, 0xDE, 0x00] => Ok(WeaponType::TypeslSaber), + [0x00, 0xDE, 0x01] => Ok(WeaponType::TypeslSlicer), + [0x00, 0xDE, 0x02] => Ok(WeaponType::TypeslClaw), + [0x00, 0xDE, 0x03] => Ok(WeaponType::TypeslKatana), + [0x00, 0xDF, 0x00] => Ok(WeaponType::TypejsSaber), + [0x00, 0xDF, 0x01] => Ok(WeaponType::TypejsSlicer), + [0x00, 0xDF, 0x02] => Ok(WeaponType::TypejsJSword), + [0x00, 0xE0, 0x00] => Ok(WeaponType::TypeswSword), + [0x00, 0xE0, 0x01] => Ok(WeaponType::TypeswSlicer), + [0x00, 0xE0, 0x02] => Ok(WeaponType::TypeswJSword), + [0x00, 0xE1, 0x00] => Ok(WeaponType::TyperoSword), + [0x00, 0xE1, 0x01] => Ok(WeaponType::TyperoHalbert), + [0x00, 0xE1, 0x02] => Ok(WeaponType::TyperoRod), + [0x00, 0xE2, 0x00] => Ok(WeaponType::TypeblBlade), + [0x00, 0xE3, 0x00] => Ok(WeaponType::TypeknBlade), + [0x00, 0xE3, 0x01] => Ok(WeaponType::TypeknClaw), + [0x00, 0xE4, 0x00] => Ok(WeaponType::TypehaHalbert), + [0x00, 0xE4, 0x01] => Ok(WeaponType::TypehaRod), + [0x00, 0xE5, 0x00] => Ok(WeaponType::TypedsDSaber), + [0x00, 0xE5, 0x01] => Ok(WeaponType::TypedsRod), + [0x00, 0xE5, 0x02] => Ok(WeaponType::Typeds), + [0x00, 0xE6, 0x00] => Ok(WeaponType::TypeclClaw), + [0x00, 0xE7, 0x00] => Ok(WeaponType::TypessSw), + [0x00, 0xE8, 0x00] => Ok(WeaponType::TypeguHand), + [0x00, 0xE8, 0x01] => Ok(WeaponType::TypeguMechgun), + [0x00, 0xE9, 0x00] => Ok(WeaponType::TyperiRifle), + [0x00, 0xEA, 0x00] => Ok(WeaponType::TypemeMechgun), + [0x00, 0xEB, 0x00] => Ok(WeaponType::TypeshShot), + [0x00, 0xEC, 0x00] => Ok(WeaponType::TypewaWand), + _ => Err(ItemParseError::InvalidWeaponType), + } + } } #[derive(Debug, Copy, Clone, PartialEq)] @@ -903,6 +1367,61 @@ impl Weapon { result } + + // TODO: error handling + pub fn from_bytes(data: [u8; 16]) -> Result { + let w = WeaponType::parse_type([data[0], data[1], data[2]]); + if w.is_ok() { + let mut s = None; + let mut t = true; + let g = data[3]; + + if data[4] >= 0x81 && data[4] <= 0xA8 { + s = WeaponSpecial::from(data[4] - 0x80); + t = false; + } + else if data[4] >= 0x01 && data[4] <= 0x28 { + s = WeaponSpecial::from(data[4]); + t = true; + } + // else { + // return Err(ItemParseError::InvalidSpecial) + // } + + let mut a = [ + None, + None, + None + ]; + + for i in 0..3 { + if data[2 * (3 + i)] >= 1 && data[2 * (3 + i)] <= 5 { + a[i] = Some(WeaponAttribute{ + attr: Attribute::from(data[2 * (3 + i)]).unwrap(), + value: data[2 * (3 + i) + 1] as i8, + }); + } else { + a[i] = None; + // return Err(ItemParseError::InvalidAttribute) + } + } + + Ok(Weapon { + weapon: w.unwrap(), + special: s, + grind: g, + attrs:[ + a[0], + a[1], + a[2], + ], + tekked: t, + }) + } + else { + Err(ItemParseError::InvalidWeaponBytes) // TODO: error handling if wrong bytes are given + } + } } diff --git a/src/ship/drops/box_drop_table.rs b/src/ship/drops/box_drop_table.rs index 7346792..94abd84 100644 --- a/src/ship/drops/box_drop_table.rs +++ b/src/ship/drops/box_drop_table.rs @@ -13,7 +13,7 @@ use crate::ship::drops::generic_armor::GenericArmorTable; use crate::ship::drops::generic_shield::GenericShieldTable; use crate::ship::drops::generic_unit::GenericUnitTable; use crate::ship::drops::tool_table::ToolTable; - +use crate::entity::item::ItemDetail; #[derive(Debug, Serialize, Deserialize)] struct BoxDropRate { @@ -86,7 +86,6 @@ struct BoxRareRate { rate: f32, } - struct BoxRareRates { area1: Vec, area2: Vec, @@ -133,9 +132,6 @@ impl BoxRareRates { } } - - - pub struct BoxDropTable { box_rates: BoxDropRates, rare_rates: BoxRareRates, @@ -147,7 +143,6 @@ pub struct BoxDropTable { tool_table: ToolTable, } - impl BoxDropTable { pub fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> BoxDropTable { let rates = load_data_file(episode, difficulty, section_id, "box_rare_rate.toml"); @@ -206,7 +201,11 @@ impl BoxDropTable { Some(ItemDropType::Meseta(rng.gen_range(rate.min_meseta, rate.max_meseta))) }, FixedBoxDropType::Random => self.random_box_drop(map_area, rng), - FixedBoxDropType::Specific(value) => panic!(), + FixedBoxDropType::Specific(value) => { + let mut buf: [u8; 16] = [0; 16]; + buf[0..4].copy_from_slice(&u32::to_be_bytes(value)); + ItemDetail::parse_item_from_bytes(buf) + }, } } @@ -238,6 +237,6 @@ mod test { let bdt = BoxDropTable::new(Episode::One, Difficulty::Ultimate, SectionID::Skyly); - println!("{:?}", bdt.get_drop(&MapArea::Forest1, &MapObject {object: MapObjectType::Box}, &mut rng)); + println!("{:?}", bdt.get_drop(&MapArea::Forest1, &MapObject {object: MapObjectType::Box, map: MapArea::Forest1, dropped_item: false}, &mut rng)); } } diff --git a/src/ship/map.rs b/src/ship/map.rs index c4c8ac2..4953833 100644 --- a/src/ship/map.rs +++ b/src/ship/map.rs @@ -310,6 +310,8 @@ pub enum MapObjectType { #[derive(Debug, Copy, Clone)] pub struct MapObject { pub object: MapObjectType, + pub map: MapArea, + pub dropped_item: bool, //id: u32, } @@ -320,7 +322,7 @@ enum MapObjectError { impl MapObject { - fn from_raw(raw: RawMapObject, episode: Episode) -> Result { + fn from_raw(raw: RawMapObject, episode: Episode, map_area: &MapArea) -> Result { let object = match (raw, episode) { (RawMapObject {otype: 136, ..}, _) => MapObjectType::Box, (RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox, @@ -337,6 +339,8 @@ impl MapObject { Ok(MapObject { object: object, + map: map_area.clone(), + dropped_item: false, }) } } @@ -496,7 +500,7 @@ impl MapVariant { fn obj_file(&self) -> String { match self.map { - MapArea::Pioneer2Ep1 => "data/maps/map_city00_00e.dat".into(), + MapArea::Pioneer2Ep1 => "data/maps/map_city00_00o.dat".into(), MapArea::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor), MapArea::Forest2 => format!("data/maps/map_forest02_0{}o.dat", self.minor), MapArea::Caves1 => format!("data/maps/map_cave01_0{}_0{}o.dat", self.major, self.minor), @@ -520,12 +524,12 @@ impl MapVariant { } -fn objects_from_map_data(path: PathBuf, episode: &Episode) -> Vec> { +fn objects_from_map_data(path: PathBuf, episode: &Episode, map_variant: &MapVariant) -> Vec> { let mut cursor = File::open(path.clone()).unwrap(); let mut object_data = Vec::new(); while let Ok(raw_object) = RawMapObject::from_byte_stream(&mut cursor) { - let object = MapObject::from_raw(raw_object.clone(), *episode); + let object = MapObject::from_raw(raw_object.clone(), *episode, &map_variant.map); object_data.push(object.ok()); } @@ -631,6 +635,7 @@ fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode) -> Vec< #[error("")] pub enum MapsError { InvalidMonsterId(usize), + InvalidObjectId(usize), } #[derive(Debug)] @@ -670,7 +675,7 @@ impl Maps { enemy_data }), object_data: map_variants.iter().map(|map_variant| { - objects_from_map_data(map_variant.obj_file().into(), &episode) + objects_from_map_data(map_variant.obj_file().into(), &episode, &map_variant) }).flatten().collect(), map_variants: map_variants, }; @@ -682,6 +687,10 @@ impl Maps { self.enemy_data[id].ok_or(MapsError::InvalidMonsterId(id)) } + pub fn object_by_id(&self, id: usize) -> Result { + self.object_data[id].ok_or(MapsError::InvalidObjectId(id)) + } + pub fn map_headers(&self) -> [u32; 0x20] { self.map_variants.iter() .enumerate() diff --git a/src/ship/packet/handler/direct_message.rs b/src/ship/packet/handler/direct_message.rs index 8edb708..d1b2fa8 100644 --- a/src/ship/packet/handler/direct_message.rs +++ b/src/ship/packet/handler/direct_message.rs @@ -139,3 +139,55 @@ where } } +pub fn request_box_item(id: ClientId, + box_drop_request: &BoxDropRequest, + entity_gateway: &mut EG, + client_location: &ClientLocation, + clients: &mut Clients, + rooms: &mut Rooms, + item_manager: &mut ItemManager) + -> Result + Send>, ShipError> +where +EG: EntityGateway +{ + let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?; + let room = rooms.get_mut(room_id.0) + .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))? + .as_mut() + .ok_or_else(|| ShipError::InvalidRoom(room_id.0 as u32))?; + + let box_object = room.maps.object_by_id(box_drop_request.object_id as usize)?; + if box_object.dropped_item { + return Err(ShipError::BoxAlreadyDroppedItem(id, box_drop_request.object_id)) + } + + let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?; + + let item_drop_packets = clients_in_area.into_iter() + .filter_map(|area_client| { + room.drop_table.get_box_drop(&box_object.map, &box_object).map(|item_drop_type| { + warn!("drop is? {:?}", item_drop_type); + (area_client, item_drop_type) + }) + }) + .map(|(area_client, item_drop_type)| -> Result<_, ShipError> { + let item_drop = ItemDrop { + map_area: box_object.map, + x: box_drop_request.x, + y: 0.0, + z: box_drop_request.z, + item: item_drop_type, + }; + let client = clients.get_mut(&area_client.client).ok_or(ShipError::ClientNotFound(area_client.client))?; + let floor_item = item_manager.enemy_drop_item_on_local_floor(entity_gateway, &client.character, item_drop).unwrap(); // TODO: unwrap + let item_drop_msg = builder::message::item_drop(box_drop_request.client, box_drop_request.target, &floor_item)?; + Ok((area_client.client, SendShipPacket::Message(Message::new(GameMessage::ItemDrop(item_drop_msg))))) + }) + .filter_map(|item_drop_pkt| { + // TODO: log errors here + item_drop_pkt.ok() + }) + .collect::>(); // TODO: can EntityGateway be Sync? + + Ok(Box::new(item_drop_packets.into_iter())) +} \ No newline at end of file diff --git a/src/ship/ship.rs b/src/ship/ship.rs index 68f9da2..1257fde 100644 --- a/src/ship/ship.rs +++ b/src/ship/ship.rs @@ -50,6 +50,7 @@ pub enum ShipError { DropInvalidItemId(u32), ItemManagerError(#[from] items::ItemManagerError), ItemDropLocationNotSet, + BoxAlreadyDroppedItem(ClientId, u16), } #[derive(Debug)] @@ -247,6 +248,9 @@ impl ShipServerState { GameMessage::PickupItem(pickup_item) => { handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.item_manager).unwrap() }, + GameMessage::BoxDropRequest(box_drop_request) => { + handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut self.client_location, &mut self.clients, &mut self.rooms, &mut self.item_manager).unwrap() // TODO: unwrap + } _ => { let cmsg = msg.clone(); Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter()