227 lines
7.0 KiB
Rust
227 lines
7.0 KiB
Rust
use libpso::packet::messages::*;
|
|
use libpso::packet::ship::*;
|
|
use crate::entity::item;
|
|
use crate::common::leveltable::CharacterStats;
|
|
use crate::ship::ship::{ShipError};
|
|
use crate::ship::items::{ClientItemId, InventoryItem, StackedFloorItem, FloorItem, CharacterBank};
|
|
use crate::ship::items::state::FloorItem as FloorItem2;
|
|
use crate::ship::items::state::InventoryItem as InventoryItem2;
|
|
use crate::ship::items::state::{BankState};
|
|
use crate::ship::location::AreaClient;
|
|
use std::convert::TryInto;
|
|
use crate::ship::shops::ShopItem;
|
|
|
|
|
|
pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem) -> Result<ItemDrop, ShipError> {
|
|
let item_bytes = item_drop.as_client_bytes();
|
|
Ok(ItemDrop {
|
|
client,
|
|
target,
|
|
map_area: item_drop.map_area().area_value(),
|
|
variety: 0,
|
|
unknown: 0,
|
|
x: item_drop.x(),
|
|
z: item_drop.z(),
|
|
y: item_drop.y(),
|
|
item_bytes: item_bytes[0..12].try_into()?,
|
|
item_id: item_drop.item_id().0,
|
|
item_bytes2: item_bytes[12..16].try_into()?,
|
|
unknown2: 0,
|
|
})
|
|
}
|
|
|
|
// TODO: this doesn't need to be a Result, just unwrap try_intos they are guaranteed to succeed
|
|
pub fn create_individual_item(area_client: AreaClient, item_id: ClientItemId, item: &item::ItemDetail) -> Result<CreateItem, ShipError> {
|
|
let bytes = item.as_client_bytes();
|
|
Ok(CreateItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_data: bytes[0..12].try_into()?,
|
|
item_id: item_id.0,
|
|
item_data2: bytes[12..16].try_into()?,
|
|
unknown: 0,
|
|
})
|
|
}
|
|
|
|
// TODO: this doesn't need to be a Result, just unwrap try_intos they are guaranteed to succeed
|
|
pub fn create_stacked_item(area_client: AreaClient, item_id: ClientItemId, tool: &item::tool::Tool, amount: usize) -> Result<CreateItem, ShipError> {
|
|
let bytes = tool.as_stacked_bytes(amount);
|
|
Ok(CreateItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_data: bytes[0..12].try_into()?,
|
|
item_id: item_id.0,
|
|
item_data2: bytes[12..16].try_into()?,
|
|
unknown: 0,
|
|
})
|
|
}
|
|
|
|
pub fn create_meseta(area_client: AreaClient, amount: usize) -> CreateItem {
|
|
let bytes: [u8; 12] = [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
CreateItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_data: bytes,
|
|
item_id: 0xFFFFFFFF,
|
|
item_data2: u32::to_le_bytes(amount as u32),
|
|
unknown: 0,
|
|
}
|
|
}
|
|
|
|
pub fn create_withdrawn_inventory_item(area_client: AreaClient, item: &InventoryItem) -> Result<CreateItem, ShipError> {
|
|
let bytes = item.as_client_bytes();
|
|
Ok(CreateItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_data: bytes[0..12].try_into()?,
|
|
item_id: item.item_id().0,
|
|
item_data2: bytes[12..16].try_into()?,
|
|
unknown: 0,
|
|
})
|
|
}
|
|
|
|
pub fn create_withdrawn_inventory_item2(area_client: AreaClient, item: &InventoryItem2) -> Result<CreateItem, ShipError> {
|
|
let bytes = item.item.as_client_bytes();
|
|
Ok(CreateItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_data: bytes[0..12].try_into()?,
|
|
item_id: item.item_id.0,
|
|
item_data2: bytes[12..16].try_into()?,
|
|
unknown: 0,
|
|
})
|
|
}
|
|
|
|
pub fn remove_item_from_floor(area_client: AreaClient, item: &FloorItem2) -> Result<RemoveItemFromFloor, ShipError> {
|
|
Ok(RemoveItemFromFloor {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
client_id: area_client.local_client.id(),
|
|
unknown: 0,
|
|
map_area: item.map_area.area_value(),
|
|
unknown2: 0,
|
|
item_id: item.item_id.0,
|
|
})
|
|
}
|
|
|
|
pub fn drop_split_stack(area_client: AreaClient, item: &FloorItem2) -> Result<DropSplitStack, ShipError> {
|
|
let item_bytes = item.as_client_bytes();
|
|
Ok(DropSplitStack {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
variety: 0,
|
|
unknown1: 0,
|
|
map_area: item.map_area.area_value(),
|
|
x: item.x,
|
|
z: item.z,
|
|
item_bytes: item_bytes[0..12].try_into()?,
|
|
item_id: item.item_id.0,
|
|
item_bytes2: item_bytes[12..16].try_into()?,
|
|
unknown2: 0,
|
|
})
|
|
}
|
|
|
|
pub fn drop_split_meseta_stack(area_client: AreaClient, item: &FloorItem2) -> Result<DropSplitStack, ShipError> {
|
|
let item_bytes = item.as_client_bytes();
|
|
Ok(DropSplitStack {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
variety: 0,
|
|
unknown1: 0,
|
|
map_area: item.map_area.area_value(),
|
|
x: item.x,
|
|
z: item.z,
|
|
item_bytes: item_bytes[0..12].try_into()?,
|
|
item_id: item.item_id.0,
|
|
item_bytes2: item_bytes[12..16].try_into()?,
|
|
unknown2: 0,
|
|
})
|
|
}
|
|
|
|
pub fn character_gained_exp(area_client: AreaClient, exp: u32) -> GiveCharacterExp {
|
|
GiveCharacterExp {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
exp,
|
|
}
|
|
}
|
|
|
|
pub fn character_leveled_up(area_client: AreaClient, level: u32, before_stats: CharacterStats, after_stats: CharacterStats) -> PlayerLevelUp {
|
|
PlayerLevelUp {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
atp: after_stats.atp - before_stats.atp,
|
|
mst: after_stats.mst - before_stats.mst,
|
|
evp: after_stats.evp - before_stats.evp,
|
|
hp: after_stats. hp - before_stats. hp,
|
|
dfp: after_stats.dfp - before_stats.dfp,
|
|
ata: after_stats.ata - before_stats.ata,
|
|
lvl: level,
|
|
}
|
|
}
|
|
|
|
// TOOD: checksum?
|
|
pub fn bank_item_list(bank: &BankState) -> BankItemList {
|
|
BankItemList {
|
|
aflag: 0,
|
|
cmd: 0xBC,
|
|
unknown: [0; 3],
|
|
size: bank.count() as u32 * 0x18 + 0x14,
|
|
checksum: 0x123434,
|
|
item_count: bank.count() as u32,
|
|
meseta: bank.meseta.0,
|
|
items: bank.as_client_bank_request()
|
|
}
|
|
}
|
|
|
|
pub fn player_no_longer_has_item(area_client: AreaClient, item_id: ClientItemId, amount: u32) -> PlayerNoLongerHasItem {
|
|
PlayerNoLongerHasItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_id: item_id.0,
|
|
amount,
|
|
}
|
|
}
|
|
|
|
pub fn player_no_longer_has_meseta(area_client: AreaClient, amount: u32) -> PlayerNoLongerHasItem {
|
|
PlayerNoLongerHasItem {
|
|
client: area_client.local_client.id(),
|
|
target: 0,
|
|
item_id: 0xFFFFFFFF,
|
|
amount,
|
|
}
|
|
}
|
|
|
|
pub fn shop_list<I: ShopItem>(shop_type: u8, items: &[I]) -> ShopList {
|
|
let items = items.iter()
|
|
.enumerate()
|
|
.map(|(i, item)| {
|
|
ShopListItem {
|
|
item_bytes: item.as_bytes(),
|
|
unknown: i as u32 + 23,
|
|
price: item.price() as u32,
|
|
}
|
|
})
|
|
.collect();
|
|
|
|
ShopList {
|
|
client: 0,
|
|
target: 0,
|
|
shop_type,
|
|
num_items: 0,
|
|
unused: 0,
|
|
items,
|
|
}
|
|
}
|
|
|
|
pub fn tek_preview(id: ClientItemId, weapon: &item::weapon::Weapon) -> Result<TekPreview, ShipError> {
|
|
let bytes = weapon.as_bytes();
|
|
Ok(TekPreview {
|
|
client: 0x79,
|
|
target: 0,
|
|
item_bytes: bytes[0..12].try_into()?,
|
|
item_id: id.0,
|
|
item_bytes2: bytes[12..16].try_into()?,
|
|
})
|
|
}
|