Merge pull request 'sranks' (#206) from sranks into master
Reviewed-by: jake <jake@sharnoth.com>
This commit is contained in:
commit
525ac1a08d
308
src/entity/item/esweapon.rs
Normal file
308
src/entity/item/esweapon.rs
Normal file
@ -0,0 +1,308 @@
|
|||||||
|
// TODO: actually use this
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum ItemParseError {
|
||||||
|
InvalidESWeaponBytes,
|
||||||
|
InvalidESWeaponType,
|
||||||
|
InvalidESWeaponGrind,
|
||||||
|
InvalidESWeaponSpecial,
|
||||||
|
InvalidESWeaponName,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||||
|
pub enum ESWeaponType {
|
||||||
|
Saber = 0,
|
||||||
|
Sword,
|
||||||
|
Blade,
|
||||||
|
Partisan,
|
||||||
|
Slicer,
|
||||||
|
Gun,
|
||||||
|
Rifle,
|
||||||
|
Mechgun,
|
||||||
|
Shot,
|
||||||
|
Can,
|
||||||
|
Rod,
|
||||||
|
Wand,
|
||||||
|
Twin,
|
||||||
|
Claw,
|
||||||
|
Bazooka,
|
||||||
|
Needle,
|
||||||
|
Scythe,
|
||||||
|
Hammer,
|
||||||
|
Moon,
|
||||||
|
Psychogun,
|
||||||
|
Punch,
|
||||||
|
Windmill,
|
||||||
|
Harisen,
|
||||||
|
Katana,
|
||||||
|
JCutter,
|
||||||
|
Swords = 0x35,
|
||||||
|
Launcher,
|
||||||
|
Cards,
|
||||||
|
Knuckle,
|
||||||
|
Axe,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ESWeaponType {
|
||||||
|
pub fn to_value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_value(value: u8) -> Result<ESWeaponType, ItemParseError> {
|
||||||
|
match value {
|
||||||
|
0 => Ok(ESWeaponType::Saber),
|
||||||
|
1 => Ok(ESWeaponType::Sword),
|
||||||
|
2 => Ok(ESWeaponType::Blade),
|
||||||
|
3 => Ok(ESWeaponType::Partisan),
|
||||||
|
4 => Ok(ESWeaponType::Slicer),
|
||||||
|
5 => Ok(ESWeaponType::Gun),
|
||||||
|
6 => Ok(ESWeaponType::Rifle),
|
||||||
|
7 => Ok(ESWeaponType::Mechgun),
|
||||||
|
8 => Ok(ESWeaponType::Shot),
|
||||||
|
9 => Ok(ESWeaponType::Can),
|
||||||
|
10 => Ok(ESWeaponType::Rod),
|
||||||
|
11 => Ok(ESWeaponType::Wand),
|
||||||
|
12 => Ok(ESWeaponType::Twin),
|
||||||
|
13 => Ok(ESWeaponType::Claw),
|
||||||
|
14 => Ok(ESWeaponType::Bazooka),
|
||||||
|
15 => Ok(ESWeaponType::Needle),
|
||||||
|
16 => Ok(ESWeaponType::Scythe),
|
||||||
|
17 => Ok(ESWeaponType::Hammer),
|
||||||
|
18 => Ok(ESWeaponType::Moon),
|
||||||
|
19 => Ok(ESWeaponType::Psychogun),
|
||||||
|
20 => Ok(ESWeaponType::Punch),
|
||||||
|
21 => Ok(ESWeaponType::Windmill),
|
||||||
|
22 => Ok(ESWeaponType::Harisen),
|
||||||
|
23 => Ok(ESWeaponType::Katana),
|
||||||
|
24 => Ok(ESWeaponType::JCutter),
|
||||||
|
53 => Ok(ESWeaponType::Swords),
|
||||||
|
54 => Ok(ESWeaponType::Launcher),
|
||||||
|
55 => Ok(ESWeaponType::Cards),
|
||||||
|
56 => Ok(ESWeaponType::Knuckle),
|
||||||
|
57 => Ok(ESWeaponType::Axe),
|
||||||
|
_ => Err(ItemParseError::InvalidESWeaponType),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_type(data: [u8; 3]) -> Result<ESWeaponType, ItemParseError> {
|
||||||
|
match data {
|
||||||
|
[0x00, 0x70, 0x00] => Ok(ESWeaponType::Saber),
|
||||||
|
[0x00, 0x71, 0x00] => Ok(ESWeaponType::Sword),
|
||||||
|
[0x00, 0x72, 0x00] => Ok(ESWeaponType::Blade),
|
||||||
|
[0x00, 0x73, 0x00] => Ok(ESWeaponType::Partisan),
|
||||||
|
[0x00, 0x74, 0x00] => Ok(ESWeaponType::Slicer),
|
||||||
|
[0x00, 0x75, 0x00] => Ok(ESWeaponType::Gun),
|
||||||
|
[0x00, 0x76, 0x00] => Ok(ESWeaponType::Rifle),
|
||||||
|
[0x00, 0x77, 0x00] => Ok(ESWeaponType::Mechgun),
|
||||||
|
[0x00, 0x78, 0x00] => Ok(ESWeaponType::Shot),
|
||||||
|
[0x00, 0x79, 0x00] => Ok(ESWeaponType::Can),
|
||||||
|
[0x00, 0x7A, 0x00] => Ok(ESWeaponType::Rod),
|
||||||
|
[0x00, 0x7B, 0x00] => Ok(ESWeaponType::Wand),
|
||||||
|
[0x00, 0x7C, 0x00] => Ok(ESWeaponType::Twin),
|
||||||
|
[0x00, 0x7D, 0x00] => Ok(ESWeaponType::Claw),
|
||||||
|
[0x00, 0x7E, 0x00] => Ok(ESWeaponType::Bazooka),
|
||||||
|
[0x00, 0x7F, 0x00] => Ok(ESWeaponType::Needle),
|
||||||
|
[0x00, 0x80, 0x00] => Ok(ESWeaponType::Scythe),
|
||||||
|
[0x00, 0x81, 0x00] => Ok(ESWeaponType::Hammer),
|
||||||
|
[0x00, 0x82, 0x00] => Ok(ESWeaponType::Moon),
|
||||||
|
[0x00, 0x83, 0x00] => Ok(ESWeaponType::Psychogun),
|
||||||
|
[0x00, 0x84, 0x00] => Ok(ESWeaponType::Punch),
|
||||||
|
[0x00, 0x85, 0x00] => Ok(ESWeaponType::Windmill),
|
||||||
|
[0x00, 0x86, 0x00] => Ok(ESWeaponType::Harisen),
|
||||||
|
[0x00, 0x87, 0x00] => Ok(ESWeaponType::Katana),
|
||||||
|
[0x00, 0x88, 0x00] => Ok(ESWeaponType::JCutter),
|
||||||
|
[0x00, 0xA5, 0x00] => Ok(ESWeaponType::Swords),
|
||||||
|
[0x00, 0xA6, 0x00] => Ok(ESWeaponType::Launcher),
|
||||||
|
[0x00, 0xA7, 0x00] => Ok(ESWeaponType::Cards),
|
||||||
|
[0x00, 0xA8, 0x00] => Ok(ESWeaponType::Knuckle),
|
||||||
|
[0x00, 0xA9, 0x00] => Ok(ESWeaponType::Axe),
|
||||||
|
_ => Err(ItemParseError::InvalidESWeaponBytes),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, PartialEq)]
|
||||||
|
pub enum ESWeaponSpecial {
|
||||||
|
Jellen = 1,
|
||||||
|
Zalure,
|
||||||
|
HPRegen,
|
||||||
|
TPRegen,
|
||||||
|
Burning,
|
||||||
|
Tempest,
|
||||||
|
Blizzard,
|
||||||
|
Arrest,
|
||||||
|
Chaos,
|
||||||
|
Hell,
|
||||||
|
Spirit,
|
||||||
|
Berserk,
|
||||||
|
Demons,
|
||||||
|
Gush,
|
||||||
|
Geist,
|
||||||
|
Kings,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ESWeaponSpecial {
|
||||||
|
pub fn to_value(&self) -> u8 {
|
||||||
|
*self as u8
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_value(value: u8) -> Result<ESWeaponSpecial, ItemParseError> {
|
||||||
|
match value{
|
||||||
|
1 => Ok(ESWeaponSpecial::Jellen),
|
||||||
|
2 => Ok(ESWeaponSpecial::Zalure),
|
||||||
|
3 => Ok(ESWeaponSpecial::HPRegen),
|
||||||
|
4 => Ok(ESWeaponSpecial::TPRegen),
|
||||||
|
5 => Ok(ESWeaponSpecial::Burning),
|
||||||
|
6 => Ok(ESWeaponSpecial::Tempest),
|
||||||
|
7 => Ok(ESWeaponSpecial::Blizzard),
|
||||||
|
8 => Ok(ESWeaponSpecial::Arrest),
|
||||||
|
9 => Ok(ESWeaponSpecial::Chaos),
|
||||||
|
10 => Ok(ESWeaponSpecial::Hell),
|
||||||
|
11 => Ok(ESWeaponSpecial::Spirit),
|
||||||
|
12 => Ok(ESWeaponSpecial::Berserk),
|
||||||
|
13 => Ok(ESWeaponSpecial::Demons),
|
||||||
|
14 => Ok(ESWeaponSpecial::Gush),
|
||||||
|
15 => Ok(ESWeaponSpecial::Geist),
|
||||||
|
16 => Ok(ESWeaponSpecial::Kings),
|
||||||
|
_ => Err(ItemParseError::InvalidESWeaponSpecial),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
|
pub struct ESWeapon {
|
||||||
|
pub esweapon: ESWeaponType,
|
||||||
|
pub special: Option<ESWeaponSpecial>,
|
||||||
|
pub name: String,
|
||||||
|
pub grind: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ESWeapon {
|
||||||
|
pub fn new(t: ESWeaponType) -> ESWeapon {
|
||||||
|
ESWeapon {
|
||||||
|
esweapon: t,
|
||||||
|
special: None,
|
||||||
|
name: "".to_owned(),
|
||||||
|
grind: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn bytes_from_name(&self) -> [u8; 6] {
|
||||||
|
let mut result = [0u16; 3];
|
||||||
|
let mut letters = [0u8; 8];
|
||||||
|
letters[0..self.name.len()].clone_from_slice(&self.name.to_uppercase().clone().into_bytes());
|
||||||
|
|
||||||
|
for letter in letters.iter_mut() {
|
||||||
|
*letter = *letter & 0x3F;
|
||||||
|
}
|
||||||
|
|
||||||
|
result[0] = 0x8000 + (0x20 * letters[0] as u16) + (letters[1] as u16);
|
||||||
|
result[1] = 0x8000 + (0x400 * letters[2] as u16) + (0x20 * letters[3] as u16) + (letters[4] as u16);
|
||||||
|
result[2] = 0x8000 + (0x400 * letters[5] as u16) + (0x20 * letters[6] as u16) + (letters[7] as u16);
|
||||||
|
|
||||||
|
[result[0].to_be_bytes()[0], result[0].to_be_bytes()[1],
|
||||||
|
result[1].to_be_bytes()[0], result[1].to_be_bytes()[1],
|
||||||
|
result[2].to_be_bytes()[0], result[2].to_be_bytes()[1]]
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: error handling, ensure name is never more than 8
|
||||||
|
pub fn name_from_bytes(namebytes: &[u8]) -> String {
|
||||||
|
let mut name: Vec<u8> = Vec::with_capacity(8);
|
||||||
|
name.extend_from_slice(namebytes);
|
||||||
|
|
||||||
|
for _ in name.len()..name.capacity() {
|
||||||
|
name.push(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let buf: [u16; 3] = [
|
||||||
|
u16::from_be_bytes([namebytes[0], namebytes[1]]),
|
||||||
|
u16::from_be_bytes([namebytes[2], namebytes[3]]),
|
||||||
|
u16::from_be_bytes([namebytes[4], namebytes[5]]),
|
||||||
|
];
|
||||||
|
|
||||||
|
name[0] = ((buf[0] - 0x8000) / 0x20 + 0x40) as u8;
|
||||||
|
name[1] = ((buf[0] - 0x8000) % 0x20 + 0x40) as u8;
|
||||||
|
|
||||||
|
name[2] = ((buf[1] - 0x8000) / 0x400 + 0x40) as u8;
|
||||||
|
name[3] = (((buf[1] - 0x8000) % 0x400) / 0x20 + 0x40) as u8;
|
||||||
|
name[4] = (((buf[1] - 0x8000) % 0x400) % 0x20 + 0x40) as u8;
|
||||||
|
|
||||||
|
name[5] = ((buf[2] - 0x8000) / 0x400 + 0x40) as u8;
|
||||||
|
name[6] = (((buf[2] - 0x8000) % 0x400) / 0x20 + 0x40) as u8;
|
||||||
|
name[7] = (((buf[2] - 0x8000) % 0x400) % 0x20 + 0x40) as u8;
|
||||||
|
|
||||||
|
name.retain(|&x| x > 0x40 && x < 0x5B);
|
||||||
|
|
||||||
|
String::from_utf8(name).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_bytes(&self) -> [u8; 16] {
|
||||||
|
let mut result = [0u8; 16];
|
||||||
|
result[1] = 0x70 + self.esweapon.to_value();
|
||||||
|
result[2] = self.special.map(|s| s.to_value()).unwrap_or(0);
|
||||||
|
result[3] = self.grind;
|
||||||
|
//result[4] = tekked/untekked flag
|
||||||
|
result[6..12].clone_from_slice(&self.bytes_from_name());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: return Result<ESWeapon, ESWeaponError>
|
||||||
|
pub fn from_bytes(bytes: [u8; 16]) -> ESWeapon {
|
||||||
|
let esweapon = ESWeaponType::from_value(bytes[1] - 0x70).unwrap();
|
||||||
|
let special = ESWeaponSpecial::from_value(bytes[2]);
|
||||||
|
let grind = bytes[3];
|
||||||
|
let name = ESWeapon::name_from_bytes(&bytes[6..12]);
|
||||||
|
|
||||||
|
ESWeapon {
|
||||||
|
esweapon: esweapon,
|
||||||
|
special: special.ok(),
|
||||||
|
grind: grind,
|
||||||
|
name: name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use super::*;
|
||||||
|
#[test]
|
||||||
|
fn test_create_esweapon_from_bytes() {
|
||||||
|
// JAKESERV BAZOOKA + 137 (Berserk)
|
||||||
|
let weapon_bytes = [0x00, 0x7E, 0x0C, 0x89, 0x00, 0x00, 0x81, 0x41, 0xAC, 0xB3, 0x96, 0x56, 0x00, 0x00, 0x00, 0x00];
|
||||||
|
|
||||||
|
let testweapon = ESWeapon::from_bytes(weapon_bytes);
|
||||||
|
assert_eq!(testweapon, ESWeapon {
|
||||||
|
esweapon: ESWeaponType::Bazooka,
|
||||||
|
special: Some(ESWeaponSpecial::Berserk),
|
||||||
|
grind: 137u8,
|
||||||
|
name: "JAKESERV".to_owned(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_bytes_from_esweapon() {
|
||||||
|
// PSYCHO WAND + 72 (Chaos)
|
||||||
|
let testweapon = ESWeapon {
|
||||||
|
esweapon: ESWeaponType::Wand,
|
||||||
|
special: Some(ESWeaponSpecial::Chaos),
|
||||||
|
grind: 72u8,
|
||||||
|
name: "PSYCHO".to_owned(),
|
||||||
|
};
|
||||||
|
let bytes = testweapon.as_bytes();
|
||||||
|
assert_eq!(bytes, [0x00, 0x7B, 0x09, 0x48, 0x00, 0x00, 0x82, 0x13, 0xE4, 0x68, 0xBC, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_create_bytes_from_higher_esweapon_type() {
|
||||||
|
// YUGIOH CARDS + 105 (Spirit)
|
||||||
|
let testweapon = ESWeapon {
|
||||||
|
esweapon: ESWeaponType::Cards,
|
||||||
|
special: Some(ESWeaponSpecial::Spirit),
|
||||||
|
grind: 105u8,
|
||||||
|
name: "YUGIOH".to_owned(),
|
||||||
|
};
|
||||||
|
let bytes = testweapon.as_bytes();
|
||||||
|
assert_eq!(bytes, [0x00, 0xA7, 0x0B, 0x69, 0x00, 0x00, 0x83, 0x35, 0x9D, 0x2F, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x00]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -6,6 +6,7 @@ pub mod tool;
|
|||||||
pub mod tech;
|
pub mod tech;
|
||||||
pub mod unit;
|
pub mod unit;
|
||||||
pub mod mag;
|
pub mod mag;
|
||||||
|
pub mod esweapon;
|
||||||
|
|
||||||
use crate::entity::character::CharacterEntityId;
|
use crate::entity::character::CharacterEntityId;
|
||||||
use crate::ship::map::MapArea;
|
use crate::ship::map::MapArea;
|
||||||
@ -75,6 +76,7 @@ pub enum ItemType {
|
|||||||
Tool(tool::ToolType),
|
Tool(tool::ToolType),
|
||||||
TechniqueDisk(tech::Technique),
|
TechniqueDisk(tech::Technique),
|
||||||
Mag(mag::MagType),
|
Mag(mag::MagType),
|
||||||
|
ESWeapon(esweapon::ESWeaponType),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
@ -91,6 +93,7 @@ pub enum ItemDetail {
|
|||||||
Tool(tool::Tool),
|
Tool(tool::Tool),
|
||||||
TechniqueDisk(tech::TechniqueDisk),
|
TechniqueDisk(tech::TechniqueDisk),
|
||||||
Mag(mag::Mag),
|
Mag(mag::Mag),
|
||||||
|
ESWeapon(esweapon::ESWeapon),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ItemDetail {
|
impl ItemDetail {
|
||||||
@ -110,6 +113,7 @@ impl ItemDetail {
|
|||||||
ItemDetail::Tool(t) => ItemType::Tool(t.tool),
|
ItemDetail::Tool(t) => ItemType::Tool(t.tool),
|
||||||
ItemDetail::TechniqueDisk(d) => ItemType::TechniqueDisk(d.tech),
|
ItemDetail::TechniqueDisk(d) => ItemType::TechniqueDisk(d.tech),
|
||||||
ItemDetail::Mag(m) => ItemType::Mag(m.mag),
|
ItemDetail::Mag(m) => ItemType::Mag(m.mag),
|
||||||
|
ItemDetail::ESWeapon(e) => ItemType::ESWeapon(e.esweapon),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +123,8 @@ impl ItemDetail {
|
|||||||
.or(shield::ShieldType::parse_type([data[0],data[1],data[2]]).map(|s| ItemType::Shield(s)))
|
.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(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(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()?;
|
.or(tool::ToolType::parse_type([data[0],data[1],data[2]]).map(|t| ItemType::Tool(t)))
|
||||||
|
.or(esweapon::ESWeaponType::parse_type([data[0],data[1],data[2]]).map(|e| ItemType::ESWeapon(e))).ok()?;
|
||||||
|
|
||||||
match item_type {
|
match item_type {
|
||||||
ItemType::Weapon(_w) => Some(ItemDropType::Weapon(weapon::Weapon::from_bytes(data).ok()?)),
|
ItemType::Weapon(_w) => Some(ItemDropType::Weapon(weapon::Weapon::from_bytes(data).ok()?)),
|
||||||
@ -141,6 +146,7 @@ impl ItemDetail {
|
|||||||
ItemDetail::Tool(t) => t.as_individual_bytes(),
|
ItemDetail::Tool(t) => t.as_individual_bytes(),
|
||||||
ItemDetail::TechniqueDisk(d) => d.as_bytes(),
|
ItemDetail::TechniqueDisk(d) => d.as_bytes(),
|
||||||
ItemDetail::Mag(m) => m.as_bytes(),
|
ItemDetail::Mag(m) => m.as_bytes(),
|
||||||
|
ItemDetail::ESWeapon(e) => e.as_bytes(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,6 +126,7 @@ impl BankItem {
|
|||||||
ItemDetail::Tool(t) => t.as_individual_bytes(),
|
ItemDetail::Tool(t) => t.as_individual_bytes(),
|
||||||
ItemDetail::TechniqueDisk(d) => d.as_bytes(),
|
ItemDetail::TechniqueDisk(d) => d.as_bytes(),
|
||||||
ItemDetail::Mag(m) => m.as_bytes(),
|
ItemDetail::Mag(m) => m.as_bytes(),
|
||||||
|
ItemDetail::ESWeapon(e) => e.as_bytes(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
BankItem::Stacked(item) => {
|
BankItem::Stacked(item) => {
|
||||||
|
@ -147,6 +147,7 @@ impl InventoryItem {
|
|||||||
ItemDetail::Tool(t) => t.as_individual_bytes(),
|
ItemDetail::Tool(t) => t.as_individual_bytes(),
|
||||||
ItemDetail::TechniqueDisk(d) => d.as_bytes(),
|
ItemDetail::TechniqueDisk(d) => d.as_bytes(),
|
||||||
ItemDetail::Mag(m) => m.as_bytes(),
|
ItemDetail::Mag(m) => m.as_bytes(),
|
||||||
|
ItemDetail::ESWeapon(e) => e.as_bytes(),
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
InventoryItem::Stacked(item) => {
|
InventoryItem::Stacked(item) => {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user