Browse Source

Merge pull request 'box_drops' (#155) from box_drops into master

Reviewed-by: jake <jake@sharnoth.com>
pbs
jake 5 years ago
parent
commit
1bd10f4bb8
  1. 115
      src/entity/item/armor.rs
  2. 122
      src/entity/item/mag.rs
  3. 24
      src/entity/item/mod.rs
  4. 191
      src/entity/item/shield.rs
  5. 198
      src/entity/item/tool.rs
  6. 133
      src/entity/item/unit.rs
  7. 519
      src/entity/item/weapon.rs
  8. 15
      src/ship/drops/box_drop_table.rs
  9. 19
      src/ship/map.rs
  10. 52
      src/ship/packet/handler/direct_message.rs
  11. 4
      src/ship/ship.rs

115
src/entity/item/armor.rs

@ -1,5 +1,11 @@
use serde::{Serialize, Deserialize}; 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)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
pub enum ArmorType { pub enum ArmorType {
Frame, Frame,
@ -185,6 +191,100 @@ impl ArmorType {
ArmorType::StealthSuit => [0x01, 0x01, 0x57], ArmorType::StealthSuit => [0x01, 0x01, 0x57],
} }
} }
pub fn parse_type(data: [u8; 3]) -> Result<ArmorType, ItemParseError> {
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[8] = self.evp;
result result
} }
pub fn from_bytes(data: [u8; 16]) -> Result<Armor, ItemParseError> {
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
}
}
} }

122
src/entity/item/mag.rs

@ -1,5 +1,10 @@
use serde::{Serialize, Deserialize}; 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)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
pub enum MagType { pub enum MagType {
@ -162,6 +167,88 @@ impl MagType {
MagType::Agastya => [0x02, 0x4C, 0x00], MagType::Agastya => [0x02, 0x4C, 0x00],
} }
} }
pub fn parse_type(data: [u8; 3]) -> Result<MagType, ItemParseError> {
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)] #[derive(Debug, Copy, Clone, PartialEq)]
@ -255,4 +342,39 @@ impl Mag {
} }
count count
} }
pub fn from_bytes(data: [u8; 16]) -> Result<Mag, ItemParseError> {
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
}
}
} }

24
src/entity/item/mod.rs

@ -9,6 +9,7 @@ pub mod mag;
use crate::entity::character::CharacterEntityId; use crate::entity::character::CharacterEntityId;
use crate::ship::map::MapArea; use crate::ship::map::MapArea;
use crate::ship::drops::ItemDropType;
#[derive(PartialEq, Copy, Clone, Debug, Hash, Eq)] #[derive(PartialEq, Copy, Clone, Debug, Hash, Eq)]
pub struct ItemEntityId(pub u32); pub struct ItemEntityId(pub u32);
@ -75,6 +76,10 @@ pub enum ItemType {
Mag(mag::MagType), Mag(mag::MagType),
} }
#[derive(Clone, Debug, PartialEq)]
pub enum ItemParseError {
InvalidBytes
}
#[derive(Clone, Debug, PartialEq)] #[derive(Clone, Debug, PartialEq)]
pub enum ItemDetail { pub enum ItemDetail {
@ -106,6 +111,25 @@ impl ItemDetail {
ItemDetail::Mag(m) => ItemType::Mag(m.mag), ItemDetail::Mag(m) => ItemType::Mag(m.mag),
} }
} }
pub fn parse_item_from_bytes(data: [u8; 16]) -> Option<ItemDropType> {
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)] #[derive(Clone, Debug)]

191
src/entity/item/shield.rs

@ -1,5 +1,11 @@
use serde::{Serialize, Deserialize}; 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)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
pub enum ShieldType { pub enum ShieldType {
Barrier, Barrier,
@ -339,6 +345,177 @@ impl ShieldType {
ShieldType::Genpei10 => [0x01, 0x02, 0xA4], ShieldType::Genpei10 => [0x01, 0x02, 0xA4],
} }
} }
pub fn parse_type(data: [u8; 3]) -> Result<ShieldType, ItemParseError> {
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[8] = self.evp;
result result
} }
pub fn from_bytes(data: [u8; 16]) -> Result<Shield, ItemParseError> {
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
}
}
} }

198
src/entity/item/tool.rs

@ -1,5 +1,11 @@
use serde::{Serialize, Deserialize}; 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)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
pub enum ToolType { pub enum ToolType {
Monomate, Monomate,
@ -390,6 +396,186 @@ impl ToolType {
ToolType::TeamPoints10000 => [0x03, 0x19, 0x03], ToolType::TeamPoints10000 => [0x03, 0x19, 0x03],
} }
} }
pub fn parse_type(data: [u8; 3]) -> Result<ToolType, ItemParseError> {
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[5] = len as u8;
result result
} }
pub fn from_bytes(data: [u8; 16]) -> Result<Tool, ItemParseError> {
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
}
}
} }

133
src/entity/item/unit.rs

@ -1,5 +1,10 @@
use serde::{Serialize, Deserialize}; 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)] #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize, enum_utils::FromStr, derive_more::Display)]
pub enum UnitType { pub enum UnitType {
@ -210,6 +215,112 @@ impl UnitType {
UnitType::PbIncrease => [0x01, 0x03, 0x63], UnitType::PbIncrease => [0x01, 0x03, 0x63],
} }
} }
pub fn parse_type(data: [u8; 3]) -> Result<UnitType, ItemParseError> {
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)] #[derive(Debug, Copy, Clone, PartialEq)]
@ -253,4 +364,26 @@ impl Unit {
result result
} }
pub fn from_bytes(data: [u8; 16]) -> Result<Unit, ItemParseError> {
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
}
}
} }

519
src/entity/item/weapon.rs

@ -1,5 +1,13 @@
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
#[derive(Debug, Copy, Clone)]
pub enum ItemParseError {
InvalidWeaponBytes,
InvalidWeaponType,
InvalidWeaponGrind,
InvalidWeaponSpecial,
InvalidWeaponAttribute,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)]
pub enum Attribute { pub enum Attribute {
@ -10,6 +18,19 @@ pub enum Attribute {
Hit Hit
} }
impl Attribute {
pub fn from(data: u8) -> Option<Attribute> {
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)] #[derive(Debug, Copy, Clone, PartialEq)]
pub struct WeaponAttribute { pub struct WeaponAttribute {
pub attr: Attribute, pub attr: Attribute,
@ -71,6 +92,52 @@ impl WeaponSpecial {
pub fn value(&self) -> u8 { pub fn value(&self) -> u8 {
*self as u8 *self as u8
} }
pub fn from(data: u8) -> Option<WeaponSpecial> {
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)] #[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], WeaponType::TypewaWand => [0x00, 0xEC, 0x00],
} }
} }
pub fn parse_type(data: [u8; 3]) -> Result<WeaponType, ItemParseError> {
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)] #[derive(Debug, Copy, Clone, PartialEq)]
@ -903,6 +1367,61 @@ impl Weapon {
result result
} }
// TODO: error handling
pub fn from_bytes(data: [u8; 16]) -> Result<Weapon, ItemParseError> {
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
}
}
} }

15
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_shield::GenericShieldTable;
use crate::ship::drops::generic_unit::GenericUnitTable; use crate::ship::drops::generic_unit::GenericUnitTable;
use crate::ship::drops::tool_table::ToolTable; use crate::ship::drops::tool_table::ToolTable;
use crate::entity::item::ItemDetail;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
struct BoxDropRate { struct BoxDropRate {
@ -86,7 +86,6 @@ struct BoxRareRate {
rate: f32, rate: f32,
} }
struct BoxRareRates { struct BoxRareRates {
area1: Vec<BoxRareRate>, area1: Vec<BoxRareRate>,
area2: Vec<BoxRareRate>, area2: Vec<BoxRareRate>,
@ -133,9 +132,6 @@ impl BoxRareRates {
} }
} }
pub struct BoxDropTable { pub struct BoxDropTable {
box_rates: BoxDropRates, box_rates: BoxDropRates,
rare_rates: BoxRareRates, rare_rates: BoxRareRates,
@ -147,7 +143,6 @@ pub struct BoxDropTable {
tool_table: ToolTable, tool_table: ToolTable,
} }
impl BoxDropTable { impl BoxDropTable {
pub fn new(episode: Episode, difficulty: Difficulty, section_id: SectionID) -> 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"); 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))) Some(ItemDropType::Meseta(rng.gen_range(rate.min_meseta, rate.max_meseta)))
}, },
FixedBoxDropType::Random => self.random_box_drop(map_area, rng), 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); 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));
} }
} }

19
src/ship/map.rs

@ -310,6 +310,8 @@ pub enum MapObjectType {
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct MapObject { pub struct MapObject {
pub object: MapObjectType, pub object: MapObjectType,
pub map: MapArea,
pub dropped_item: bool,
//id: u32, //id: u32,
} }
@ -320,7 +322,7 @@ enum MapObjectError {
impl MapObject { impl MapObject {
fn from_raw(raw: RawMapObject, episode: Episode) -> Result<MapObject, MapObjectError> {
fn from_raw(raw: RawMapObject, episode: Episode, map_area: &MapArea) -> Result<MapObject, MapObjectError> {
let object = match (raw, episode) { let object = match (raw, episode) {
(RawMapObject {otype: 136, ..}, _) => MapObjectType::Box, (RawMapObject {otype: 136, ..}, _) => MapObjectType::Box,
(RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox, (RawMapObject {otype: 145, ..}, _) => MapObjectType::EnemyBox,
@ -337,6 +339,8 @@ impl MapObject {
Ok(MapObject { Ok(MapObject {
object: object, object: object,
map: map_area.clone(),
dropped_item: false,
}) })
} }
} }
@ -496,7 +500,7 @@ impl MapVariant {
fn obj_file(&self) -> String { fn obj_file(&self) -> String {
match self.map { 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::Forest1 => format!("data/maps/map_forest01_0{}o.dat", self.minor),
MapArea::Forest2 => format!("data/maps/map_forest02_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), 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<Option<MapObject>> {
fn objects_from_map_data(path: PathBuf, episode: &Episode, map_variant: &MapVariant) -> Vec<Option<MapObject>> {
let mut cursor = File::open(path.clone()).unwrap(); let mut cursor = File::open(path.clone()).unwrap();
let mut object_data = Vec::new(); let mut object_data = Vec::new();
while let Ok(raw_object) = RawMapObject::from_byte_stream(&mut cursor) { 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()); object_data.push(object.ok());
} }
@ -631,6 +635,7 @@ fn enemy_data_from_map_data(map_variant: &MapVariant, episode: &Episode) -> Vec<
#[error("")] #[error("")]
pub enum MapsError { pub enum MapsError {
InvalidMonsterId(usize), InvalidMonsterId(usize),
InvalidObjectId(usize),
} }
#[derive(Debug)] #[derive(Debug)]
@ -670,7 +675,7 @@ impl Maps {
enemy_data enemy_data
}), }),
object_data: map_variants.iter().map(|map_variant| { 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(), }).flatten().collect(),
map_variants: map_variants, map_variants: map_variants,
}; };
@ -682,6 +687,10 @@ impl Maps {
self.enemy_data[id].ok_or(MapsError::InvalidMonsterId(id)) self.enemy_data[id].ok_or(MapsError::InvalidMonsterId(id))
} }
pub fn object_by_id(&self, id: usize) -> Result<MapObject, MapsError> {
self.object_data[id].ok_or(MapsError::InvalidObjectId(id))
}
pub fn map_headers(&self) -> [u32; 0x20] { pub fn map_headers(&self) -> [u32; 0x20] {
self.map_variants.iter() self.map_variants.iter()
.enumerate() .enumerate()

52
src/ship/packet/handler/direct_message.rs

@ -139,3 +139,55 @@ where
} }
} }
pub fn request_box_item<EG>(id: ClientId,
box_drop_request: &BoxDropRequest,
entity_gateway: &mut EG,
client_location: &ClientLocation,
clients: &mut Clients,
rooms: &mut Rooms,
item_manager: &mut ItemManager)
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + 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::<Vec<_>>(); // TODO: can EntityGateway be Sync?
Ok(Box::new(item_drop_packets.into_iter()))
}

4
src/ship/ship.rs

@ -50,6 +50,7 @@ pub enum ShipError {
DropInvalidItemId(u32), DropInvalidItemId(u32),
ItemManagerError(#[from] items::ItemManagerError), ItemManagerError(#[from] items::ItemManagerError),
ItemDropLocationNotSet, ItemDropLocationNotSet,
BoxAlreadyDroppedItem(ClientId, u16),
} }
#[derive(Debug)] #[derive(Debug)]
@ -247,6 +248,9 @@ impl<EG: EntityGateway> ShipServerState<EG> {
GameMessage::PickupItem(pickup_item) => { 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() 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(); let cmsg = msg.clone();
Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter() Box::new(self.client_location.get_all_clients_by_client(id).unwrap().into_iter()

Loading…
Cancel
Save