Merge pull request 'tekking!' (#271) from andy_is_unable_to_tek_properly into master
This commit is contained in:
commit
03aa41ef6a
@ -84,7 +84,6 @@ fn main() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -119,8 +118,7 @@ fn main() {
|
|||||||
attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 40}),
|
attrs: [Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Hit, value: 40}),
|
||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
|
||||||
None,],
|
None,],
|
||||||
tekked: true,
|
tekked: false,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
@ -138,7 +136,6 @@ fn main() {
|
|||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 30}),
|
||||||
None,],
|
None,],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
@ -156,7 +153,6 @@ fn main() {
|
|||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
||||||
None,],
|
None,],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
@ -174,7 +170,6 @@ fn main() {
|
|||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
||||||
None,],
|
None,],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
@ -192,7 +187,6 @@ fn main() {
|
|||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 100}),
|
||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),],
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Native, value: 100}),],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
@ -257,7 +251,6 @@ fn main() {
|
|||||||
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 80}),
|
Some(item::weapon::WeaponAttribute{attr: item::weapon::Attribute::Dark, value: 80}),
|
||||||
None,],
|
None,],
|
||||||
tekked: false,
|
tekked: false,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Bank {
|
location: ItemLocation::Bank {
|
||||||
@ -273,7 +266,6 @@ fn main() {
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 4,
|
slots: 4,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
|
@ -65,11 +65,6 @@ pub trait EntityGateway: Send + Sync + Clone {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: remove
|
|
||||||
async fn change_item(&mut self, _id: &ItemEntityId, _item: &ItemDetail) -> Result<(), GatewayError> {
|
|
||||||
unimplemented!();
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) -> Result<(), GatewayError> {
|
async fn change_item_location(&mut self, _item_id: &ItemEntityId, _item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
@ -86,6 +81,11 @@ pub trait EntityGateway: Send + Sync + Clone {
|
|||||||
unimplemented!();
|
unimplemented!();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn add_weapon_modifier(&mut self, _item_id: &ItemEntityId, _modifier: weapon::WeaponModifier) -> Result<(), GatewayError> {
|
||||||
|
unimplemented!();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
async fn get_items_by_character(&self, _char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
unimplemented!();
|
unimplemented!();
|
||||||
|
@ -18,6 +18,7 @@ pub struct InMemoryGateway {
|
|||||||
banks: Arc<Mutex<BTreeMap<CharacterEntityId, BankEntity>>>,
|
banks: Arc<Mutex<BTreeMap<CharacterEntityId, BankEntity>>>,
|
||||||
equips: Arc<Mutex<BTreeMap<CharacterEntityId, EquippedEntity>>>,
|
equips: Arc<Mutex<BTreeMap<CharacterEntityId, EquippedEntity>>>,
|
||||||
mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>,
|
mag_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<mag::MagModifier>>>>,
|
||||||
|
weapon_modifiers: Arc<Mutex<BTreeMap<ItemEntityId, Vec<weapon::WeaponModifier>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InMemoryGateway {
|
impl InMemoryGateway {
|
||||||
@ -31,6 +32,7 @@ impl InMemoryGateway {
|
|||||||
banks: Arc::new(Mutex::new(BTreeMap::new())),
|
banks: Arc::new(Mutex::new(BTreeMap::new())),
|
||||||
equips: Arc::new(Mutex::new(BTreeMap::new())),
|
equips: Arc::new(Mutex::new(BTreeMap::new())),
|
||||||
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
|
mag_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
|
||||||
|
weapon_modifiers: Arc::new(Mutex::new(BTreeMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -42,9 +44,16 @@ impl InMemoryGateway {
|
|||||||
.map(|item| {
|
.map(|item| {
|
||||||
item.map_individual(|mut item| {
|
item.map_individual(|mut item| {
|
||||||
item.item = match item.item {
|
item.item = match item.item {
|
||||||
|
ItemDetail::Weapon(mut weapon) => {
|
||||||
|
if let Some(weapon_modifiers) = self.weapon_modifiers.lock().unwrap().get(&item.id) {
|
||||||
|
for weapon_modifier in weapon_modifiers.iter() {
|
||||||
|
weapon.apply_modifier(&weapon_modifier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ItemDetail::Weapon(weapon)
|
||||||
|
},
|
||||||
ItemDetail::Mag(mag) => {
|
ItemDetail::Mag(mag) => {
|
||||||
let mut mag = mag::Mag::baby_mag(mag.color as u16);
|
let mut mag = mag::Mag::baby_mag(mag.color as u16);
|
||||||
println!("mag! {:?}", mag);
|
|
||||||
if let Some(mag_modifiers) = self.mag_modifiers.lock().unwrap().get(&item.id) {
|
if let Some(mag_modifiers) = self.mag_modifiers.lock().unwrap().get(&item.id) {
|
||||||
for mag_modifier in mag_modifiers.iter() {
|
for mag_modifier in mag_modifiers.iter() {
|
||||||
match mag_modifier {
|
match mag_modifier {
|
||||||
@ -69,7 +78,6 @@ impl InMemoryGateway {
|
|||||||
},
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
println!("{:?} -> {:?}", mag_modifier, mag);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ItemDetail::Mag(mag)
|
ItemDetail::Mag(mag)
|
||||||
@ -223,15 +231,6 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
Ok(new_item)
|
Ok(new_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item(&mut self, id: &ItemEntityId, item: &ItemDetail) -> Result<(), GatewayError> {
|
|
||||||
let mut items = self.items.lock().unwrap();
|
|
||||||
if let Some((_, ref mut old_item)) = items.iter_mut().find(|(existing_id, _)| **existing_id == *id) {
|
|
||||||
old_item.item = item.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
self.items.lock().unwrap().get_mut(&item_id)
|
self.items.lock().unwrap().get_mut(&item_id)
|
||||||
.map(|item_entity| {
|
.map(|item_entity| {
|
||||||
@ -266,6 +265,14 @@ impl EntityGateway for InMemoryGateway {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn add_weapon_modifier(&mut self, item_id: &ItemEntityId, modifier: weapon::WeaponModifier) -> Result<(), GatewayError> {
|
||||||
|
self.weapon_modifiers.lock().unwrap()
|
||||||
|
.entry(*item_id)
|
||||||
|
.or_insert(Vec::new())
|
||||||
|
.push(modifier);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
|
async fn get_character_inventory(&mut self, char_id: &CharacterEntityId) -> Result<InventoryEntity, GatewayError> {
|
||||||
println!("getting inv");
|
println!("getting inv");
|
||||||
let inventories = self.inventories.lock().unwrap();
|
let inventories = self.inventories.lock().unwrap();
|
||||||
|
@ -316,11 +316,16 @@ impl Into<weapon::Weapon> for PgWeapon {
|
|||||||
grind: self.grind,
|
grind: self.grind,
|
||||||
attrs: attrs,
|
attrs: attrs,
|
||||||
tekked: self.tekked,
|
tekked: self.tekked,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, sqlx::FromRow)]
|
||||||
|
pub struct PgWeaponModifier {
|
||||||
|
pub weapon: i32,
|
||||||
|
pub modifier: sqlx::types::Json<weapon::WeaponModifier>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
pub struct PgArmor {
|
pub struct PgArmor {
|
||||||
armor: armor::ArmorType,
|
armor: armor::ArmorType,
|
||||||
@ -347,7 +352,6 @@ impl Into<armor::Armor> for PgArmor {
|
|||||||
dfp: self.dfp,
|
dfp: self.dfp,
|
||||||
evp: self.evp,
|
evp: self.evp,
|
||||||
slots: self.slots,
|
slots: self.slots,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,23 @@ impl PostgresGateway {
|
|||||||
let ItemEntity {id, item, location} = item;
|
let ItemEntity {id, item, location} = item;
|
||||||
|
|
||||||
let item = match item {
|
let item = match item {
|
||||||
|
ItemDetail::Weapon(mut weapon) => {
|
||||||
|
let q = r#"select weapon, modifier
|
||||||
|
from weapon_modifier
|
||||||
|
where weapon = $1
|
||||||
|
order by created_at"#;
|
||||||
|
let weapon_modifiers = sqlx::query_as::<_, PgWeaponModifier>(q)
|
||||||
|
.bind(id.0 as i32)
|
||||||
|
.fetch(&self.pool);
|
||||||
|
|
||||||
|
weapon_modifiers.for_each(|modifier| {
|
||||||
|
if let Ok(modifier) = modifier {
|
||||||
|
weapon.apply_modifier(&modifier.modifier);
|
||||||
|
}
|
||||||
|
}).await;
|
||||||
|
|
||||||
|
ItemDetail::Weapon(weapon)
|
||||||
|
},
|
||||||
ItemDetail::Mag(mut mag) => {
|
ItemDetail::Mag(mut mag) => {
|
||||||
let q = r#"select mag, modifier, item.item -> 'Tool' as feed, item2.item -> 'Tool' as cell
|
let q = r#"select mag, modifier, item.item -> 'Tool' as feed, item2.item -> 'Tool' as cell
|
||||||
from mag_modifier
|
from mag_modifier
|
||||||
@ -331,14 +348,6 @@ impl EntityGateway for PostgresGateway {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn change_item(&mut self, id: &ItemEntityId, item: &ItemDetail) -> Result<(), GatewayError> {
|
|
||||||
sqlx::query("update item set item = $1 where id = $2")
|
|
||||||
.bind(sqlx::types::Json(PgItemDetail::from(item.clone())))
|
|
||||||
.bind(id.0)
|
|
||||||
.execute(&self.pool).await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
async fn change_item_location(&mut self, item_id: &ItemEntityId, item_location: ItemLocation) -> Result<(), GatewayError> {
|
||||||
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
sqlx::query("insert into item_location (item, location) values ($1, $2)")
|
||||||
.bind(item_id.0)
|
.bind(item_id.0)
|
||||||
@ -398,6 +407,15 @@ impl EntityGateway for PostgresGateway {
|
|||||||
.execute(&self.pool).await?;
|
.execute(&self.pool).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn add_weapon_modifier(&mut self, item_id: &ItemEntityId, modifier: weapon::WeaponModifier) -> Result<(), GatewayError> {
|
||||||
|
sqlx::query("insert into weapon_modifier (weapon, modifier) values ($1, $2);")
|
||||||
|
.bind(item_id.0)
|
||||||
|
.bind(sqlx::types::Json(modifier))
|
||||||
|
.execute(&self.pool).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
async fn get_items_by_character(&self, char_id: &CharacterEntityId) -> Result<Vec<ItemEntity>, GatewayError> {
|
||||||
let q = r#"select * from (
|
let q = r#"select * from (
|
||||||
|
@ -303,7 +303,6 @@ pub struct Armor {
|
|||||||
pub dfp: u8,
|
pub dfp: u8,
|
||||||
pub evp: u8,
|
pub evp: u8,
|
||||||
pub slots: u8,
|
pub slots: u8,
|
||||||
pub modifiers: Vec<ArmorModifier>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Armor {
|
impl Armor {
|
||||||
@ -324,7 +323,6 @@ impl Armor {
|
|||||||
dfp: data[6],
|
dfp: data[6],
|
||||||
evp: data[8],
|
evp: data[8],
|
||||||
slots: data[5],
|
slots: data[5],
|
||||||
modifiers: Vec::new(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -93,6 +93,95 @@ impl WeaponSpecial {
|
|||||||
pub fn value(&self) -> u8 {
|
pub fn value(&self) -> u8 {
|
||||||
*self as u8
|
*self as u8
|
||||||
}
|
}
|
||||||
|
pub fn rank_up(&self) -> WeaponSpecial {
|
||||||
|
match self {
|
||||||
|
WeaponSpecial::Draw => WeaponSpecial::Drain,
|
||||||
|
WeaponSpecial::Drain => WeaponSpecial::Fill,
|
||||||
|
WeaponSpecial::Fill => WeaponSpecial::Gush,
|
||||||
|
WeaponSpecial::Gush => WeaponSpecial::Gush,
|
||||||
|
WeaponSpecial::Heart => WeaponSpecial::Mind,
|
||||||
|
WeaponSpecial::Mind => WeaponSpecial::Soul,
|
||||||
|
WeaponSpecial::Soul => WeaponSpecial::Geist,
|
||||||
|
WeaponSpecial::Geist => WeaponSpecial::Geist,
|
||||||
|
WeaponSpecial::Masters => WeaponSpecial::Lords,
|
||||||
|
WeaponSpecial::Lords => WeaponSpecial::Kings,
|
||||||
|
WeaponSpecial::Kings => WeaponSpecial::Kings,
|
||||||
|
WeaponSpecial::Charge => WeaponSpecial::Charge,
|
||||||
|
WeaponSpecial::Spirit => WeaponSpecial::Spirit,
|
||||||
|
WeaponSpecial::Berserk => WeaponSpecial::Berserk,
|
||||||
|
WeaponSpecial::Ice => WeaponSpecial::Frost,
|
||||||
|
WeaponSpecial::Frost => WeaponSpecial::Freeze,
|
||||||
|
WeaponSpecial::Freeze => WeaponSpecial::Blizzard,
|
||||||
|
WeaponSpecial::Blizzard => WeaponSpecial::Blizzard,
|
||||||
|
WeaponSpecial::Bind => WeaponSpecial::Hold,
|
||||||
|
WeaponSpecial::Hold => WeaponSpecial::Seize,
|
||||||
|
WeaponSpecial::Seize => WeaponSpecial::Arrest,
|
||||||
|
WeaponSpecial::Arrest => WeaponSpecial::Arrest,
|
||||||
|
WeaponSpecial::Heat => WeaponSpecial::Fire,
|
||||||
|
WeaponSpecial::Fire => WeaponSpecial::Flame,
|
||||||
|
WeaponSpecial::Flame => WeaponSpecial::Burning,
|
||||||
|
WeaponSpecial::Burning => WeaponSpecial::Burning,
|
||||||
|
WeaponSpecial::Shock => WeaponSpecial::Thunder,
|
||||||
|
WeaponSpecial::Thunder => WeaponSpecial::Storm,
|
||||||
|
WeaponSpecial::Storm => WeaponSpecial::Tempest,
|
||||||
|
WeaponSpecial::Tempest => WeaponSpecial::Tempest,
|
||||||
|
WeaponSpecial::Dim => WeaponSpecial::Shadow,
|
||||||
|
WeaponSpecial::Shadow => WeaponSpecial::Dark,
|
||||||
|
WeaponSpecial::Dark => WeaponSpecial::Hell,
|
||||||
|
WeaponSpecial::Hell => WeaponSpecial::Hell,
|
||||||
|
WeaponSpecial::Panic => WeaponSpecial::Riot,
|
||||||
|
WeaponSpecial::Riot => WeaponSpecial::Havoc,
|
||||||
|
WeaponSpecial::Havoc => WeaponSpecial::Chaos,
|
||||||
|
WeaponSpecial::Chaos => WeaponSpecial::Chaos,
|
||||||
|
WeaponSpecial::Devils => WeaponSpecial::Demons,
|
||||||
|
WeaponSpecial::Demons => WeaponSpecial::Demons,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn rank_down(&self) -> WeaponSpecial {
|
||||||
|
match self {
|
||||||
|
WeaponSpecial::Draw => WeaponSpecial::Draw,
|
||||||
|
WeaponSpecial::Drain => WeaponSpecial::Draw,
|
||||||
|
WeaponSpecial::Fill => WeaponSpecial::Drain,
|
||||||
|
WeaponSpecial::Gush => WeaponSpecial::Fill,
|
||||||
|
WeaponSpecial::Heart => WeaponSpecial::Heart,
|
||||||
|
WeaponSpecial::Mind => WeaponSpecial::Heart,
|
||||||
|
WeaponSpecial::Soul => WeaponSpecial::Mind,
|
||||||
|
WeaponSpecial::Geist => WeaponSpecial::Soul,
|
||||||
|
WeaponSpecial::Masters => WeaponSpecial::Masters,
|
||||||
|
WeaponSpecial::Lords => WeaponSpecial::Masters,
|
||||||
|
WeaponSpecial::Kings => WeaponSpecial::Lords,
|
||||||
|
WeaponSpecial::Charge => WeaponSpecial::Charge,
|
||||||
|
WeaponSpecial::Spirit => WeaponSpecial::Spirit,
|
||||||
|
WeaponSpecial::Berserk => WeaponSpecial::Berserk,
|
||||||
|
WeaponSpecial::Ice => WeaponSpecial::Ice,
|
||||||
|
WeaponSpecial::Frost => WeaponSpecial::Ice,
|
||||||
|
WeaponSpecial::Freeze => WeaponSpecial::Frost,
|
||||||
|
WeaponSpecial::Blizzard => WeaponSpecial::Freeze,
|
||||||
|
WeaponSpecial::Bind => WeaponSpecial::Bind,
|
||||||
|
WeaponSpecial::Hold => WeaponSpecial::Bind,
|
||||||
|
WeaponSpecial::Seize => WeaponSpecial::Hold,
|
||||||
|
WeaponSpecial::Arrest => WeaponSpecial::Seize,
|
||||||
|
WeaponSpecial::Heat => WeaponSpecial::Heat,
|
||||||
|
WeaponSpecial::Fire => WeaponSpecial::Heat,
|
||||||
|
WeaponSpecial::Flame => WeaponSpecial::Fire,
|
||||||
|
WeaponSpecial::Burning => WeaponSpecial::Flame,
|
||||||
|
WeaponSpecial::Shock => WeaponSpecial::Shock,
|
||||||
|
WeaponSpecial::Thunder => WeaponSpecial::Shock,
|
||||||
|
WeaponSpecial::Storm => WeaponSpecial::Thunder,
|
||||||
|
WeaponSpecial::Tempest => WeaponSpecial::Storm,
|
||||||
|
WeaponSpecial::Dim => WeaponSpecial::Dim,
|
||||||
|
WeaponSpecial::Shadow => WeaponSpecial::Dim,
|
||||||
|
WeaponSpecial::Dark => WeaponSpecial::Shadow,
|
||||||
|
WeaponSpecial::Hell => WeaponSpecial::Dark,
|
||||||
|
WeaponSpecial::Panic => WeaponSpecial::Panic,
|
||||||
|
WeaponSpecial::Riot => WeaponSpecial::Panic,
|
||||||
|
WeaponSpecial::Havoc => WeaponSpecial::Riot,
|
||||||
|
WeaponSpecial::Chaos => WeaponSpecial::Havoc,
|
||||||
|
WeaponSpecial::Devils => WeaponSpecial::Devils,
|
||||||
|
WeaponSpecial::Demons => WeaponSpecial::Devils,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn from(data: u8) -> Option<WeaponSpecial> {
|
pub fn from(data: u8) -> Option<WeaponSpecial> {
|
||||||
match data {
|
match data {
|
||||||
@ -1360,7 +1449,8 @@ pub enum WeaponModifier {
|
|||||||
},
|
},
|
||||||
Tekked {
|
Tekked {
|
||||||
special: TekSpecialModifier,
|
special: TekSpecialModifier,
|
||||||
percents: TekPercentModifier,
|
percent: TekPercentModifier,
|
||||||
|
grind: i32,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1371,7 +1461,6 @@ pub struct Weapon {
|
|||||||
pub grind: u8,
|
pub grind: u8,
|
||||||
pub attrs: [Option<WeaponAttribute>; 3],
|
pub attrs: [Option<WeaponAttribute>; 3],
|
||||||
pub tekked: bool,
|
pub tekked: bool,
|
||||||
pub modifiers: Vec<WeaponModifier>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1383,7 +1472,51 @@ impl Weapon {
|
|||||||
grind: 0,
|
grind: 0,
|
||||||
attrs: [None; 3],
|
attrs: [None; 3],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn apply_modifier(&mut self, modifier: &WeaponModifier) {
|
||||||
|
match modifier {
|
||||||
|
WeaponModifier::Tekked{special, percent, grind} => {
|
||||||
|
match special {
|
||||||
|
TekSpecialModifier::Plus => {
|
||||||
|
self.special = self.special.map(|special| {
|
||||||
|
special.rank_up()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
TekSpecialModifier::Minus => {
|
||||||
|
self.special = self.special.map(|special| {
|
||||||
|
special.rank_down()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
TekSpecialModifier::Neutral => {
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for i in 0..3 {
|
||||||
|
self.attrs[i] = self.attrs[i].map(|mut attr| {
|
||||||
|
match percent {
|
||||||
|
TekPercentModifier::PlusPlus => {
|
||||||
|
attr.value += 10;
|
||||||
|
},
|
||||||
|
TekPercentModifier::Plus => {
|
||||||
|
attr.value += 5;
|
||||||
|
},
|
||||||
|
TekPercentModifier::MinusMinus => {
|
||||||
|
attr.value -= 10;
|
||||||
|
},
|
||||||
|
TekPercentModifier::Minus => {
|
||||||
|
attr.value -= 5;
|
||||||
|
},
|
||||||
|
TekPercentModifier::Neutral => {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
attr
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.grind = std::cmp::max(self.grind as i32 + grind, 0) as u8;
|
||||||
|
self.tekked = true;
|
||||||
|
},
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1452,7 +1585,6 @@ impl Weapon {
|
|||||||
a[2],
|
a[2],
|
||||||
],
|
],
|
||||||
tekked: t,
|
tekked: t,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -220,7 +220,6 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None; 3],
|
attrs: [None; 3],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}),
|
}),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
@ -234,7 +233,6 @@ async fn new_character<EG: EntityGateway>(entity_gateway: &mut EG, user: &UserAc
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 0,
|
slots: 0,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}),
|
}),
|
||||||
location: ItemLocation::Inventory {
|
location: ItemLocation::Inventory {
|
||||||
character_id: character.id,
|
character_id: character.id,
|
||||||
|
@ -107,7 +107,6 @@ impl GenericArmorTable {
|
|||||||
dfp: dfp_modifier as u8,
|
dfp: dfp_modifier as u8,
|
||||||
evp: evp_modifier as u8,
|
evp: evp_modifier as u8,
|
||||||
slots: slots as u8,
|
slots: slots as u8,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -127,28 +126,24 @@ mod test {
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 1,
|
slots: 1,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
assert!(gat.get_drop(&MapArea::Caves3, &mut rng) == Some(ItemDropType::Armor(Armor {
|
assert!(gat.get_drop(&MapArea::Caves3, &mut rng) == Some(ItemDropType::Armor(Armor {
|
||||||
armor: ArmorType::AbsorbArmor,
|
armor: ArmorType::AbsorbArmor,
|
||||||
dfp: 1,
|
dfp: 1,
|
||||||
evp: 1,
|
evp: 1,
|
||||||
slots: 1,
|
slots: 1,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
assert!(gat.get_drop(&MapArea::Forest2, &mut rng) == Some(ItemDropType::Armor(Armor {
|
assert!(gat.get_drop(&MapArea::Forest2, &mut rng) == Some(ItemDropType::Armor(Armor {
|
||||||
armor: ArmorType::HyperFrame,
|
armor: ArmorType::HyperFrame,
|
||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 0,
|
slots: 0,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
assert!(gat.get_drop(&MapArea::DarkFalz, &mut rng) == Some(ItemDropType::Armor(Armor {
|
assert!(gat.get_drop(&MapArea::DarkFalz, &mut rng) == Some(ItemDropType::Armor(Armor {
|
||||||
armor: ArmorType::ImperialArmor,
|
armor: ArmorType::ImperialArmor,
|
||||||
dfp: 2,
|
dfp: 2,
|
||||||
evp: 1,
|
evp: 1,
|
||||||
slots: 0,
|
slots: 0,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,6 @@ impl GenericWeaponTable {
|
|||||||
grind: weapon_grind as u8,
|
grind: weapon_grind as u8,
|
||||||
attrs: weapon_attributes,
|
attrs: weapon_attributes,
|
||||||
tekked: weapon_special.is_none(),
|
tekked: weapon_special.is_none(),
|
||||||
modifiers: Vec::new(),
|
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,7 +524,6 @@ mod test {
|
|||||||
grind: 0,
|
grind: 0,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
|
|
||||||
let gwt = GenericWeaponTable::new(Episode::One, Difficulty::Hard, SectionID::Skyly);
|
let gwt = GenericWeaponTable::new(Episode::One, Difficulty::Hard, SectionID::Skyly);
|
||||||
@ -535,7 +533,6 @@ mod test {
|
|||||||
grind: 2,
|
grind: 2,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
|
|
||||||
let gwt = GenericWeaponTable::new(Episode::One, Difficulty::VeryHard, SectionID::Skyly);
|
let gwt = GenericWeaponTable::new(Episode::One, Difficulty::VeryHard, SectionID::Skyly);
|
||||||
@ -545,7 +542,6 @@ mod test {
|
|||||||
grind: 0,
|
grind: 0,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: false,
|
tekked: false,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
|
|
||||||
let gwt = GenericWeaponTable::new(Episode::One, Difficulty::Ultimate, SectionID::Skyly);
|
let gwt = GenericWeaponTable::new(Episode::One, Difficulty::Ultimate, SectionID::Skyly);
|
||||||
@ -555,7 +551,6 @@ mod test {
|
|||||||
grind: 0,
|
grind: 0,
|
||||||
attrs: [Some(WeaponAttribute {attr: Attribute::ABeast, value: 30}), Some(WeaponAttribute {attr: Attribute::Dark, value: 30}), None],
|
attrs: [Some(WeaponAttribute {attr: Attribute::ABeast, value: 30}), Some(WeaponAttribute {attr: Attribute::Dark, value: 30}), None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,6 @@ impl RareDropTable {
|
|||||||
grind: 0,
|
grind: 0,
|
||||||
attrs: self.attribute_table.generate_rare_attributes(map_area, rng),
|
attrs: self.attribute_table.generate_rare_attributes(map_area, rng),
|
||||||
tekked: false,
|
tekked: false,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
@ -114,7 +113,6 @@ impl RareDropTable {
|
|||||||
dfp: self.armor_stats.dfp_modifier(&armor, rng) as u8,
|
dfp: self.armor_stats.dfp_modifier(&armor, rng) as u8,
|
||||||
evp: self.armor_stats.evp_modifier(&armor, rng) as u8,
|
evp: self.armor_stats.evp_modifier(&armor, rng) as u8,
|
||||||
slots: self.armor_stats.slots(map_area, rng) as u8,
|
slots: self.armor_stats.slots(map_area, rng) as u8,
|
||||||
modifiers: Vec::new(),
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
RareDropItem::Shield(shield) => {
|
RareDropItem::Shield(shield) => {
|
||||||
|
@ -5,6 +5,7 @@ use crate::entity::character::CharacterEntityId;
|
|||||||
use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLocation, InventoryEntity, InventoryItemEntity, EquippedEntity};
|
use crate::entity::item::{ItemEntityId, ItemDetail, ItemEntity, ItemType, ItemLocation, InventoryEntity, InventoryItemEntity, EquippedEntity};
|
||||||
use crate::entity::item::tool::Tool;
|
use crate::entity::item::tool::Tool;
|
||||||
use crate::entity::item::mag::Mag;
|
use crate::entity::item::mag::Mag;
|
||||||
|
use crate::entity::item::weapon::Weapon;
|
||||||
use crate::ship::items::{ClientItemId, BankItem, BankItemHandle};
|
use crate::ship::items::{ClientItemId, BankItem, BankItemHandle};
|
||||||
use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem};
|
use crate::ship::items::floor::{IndividualFloorItem, StackedFloorItem};
|
||||||
|
|
||||||
@ -30,6 +31,13 @@ impl IndividualInventoryItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn weapon(&self) -> Option<&Weapon> {
|
||||||
|
match self.item {
|
||||||
|
ItemDetail::Weapon(ref weapon) => Some(weapon),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn mag_mut(&mut self) -> Option<&mut Mag> {
|
pub fn mag_mut(&mut self) -> Option<&mut Mag> {
|
||||||
match self.item {
|
match self.item {
|
||||||
ItemDetail::Mag(ref mut mag) => Some(mag),
|
ItemDetail::Mag(ref mut mag) => Some(mag),
|
||||||
@ -198,7 +206,14 @@ impl InventoryItem {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn individual(&mut self) -> Option<&mut IndividualInventoryItem> {
|
pub fn individual(&self) -> Option<&IndividualInventoryItem> {
|
||||||
|
match self {
|
||||||
|
InventoryItem::Individual(ref individual_inventory_item) => Some(individual_inventory_item),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn individual_mut(&mut self) -> Option<&mut IndividualInventoryItem> {
|
||||||
match self {
|
match self {
|
||||||
InventoryItem::Individual(ref mut individual_inventory_item) => Some(individual_inventory_item),
|
InventoryItem::Individual(ref mut individual_inventory_item) => Some(individual_inventory_item),
|
||||||
_ => None
|
_ => None
|
||||||
@ -640,6 +655,14 @@ impl CharacterInventory {
|
|||||||
self.items = sorted_items;
|
self.items = sorted_items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn remove_by_id(&mut self, id: ClientItemId) -> Option<InventoryItem> {
|
||||||
|
self.items.iter()
|
||||||
|
.position(|i| i.item_id() == id)
|
||||||
|
.map(|position| {
|
||||||
|
self.items.remove(position)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn equip(&mut self, id: &ClientItemId, equip_slot: u8) {
|
pub fn equip(&mut self, id: &ClientItemId, equip_slot: u8) {
|
||||||
for item in &self.items {
|
for item in &self.items {
|
||||||
if let InventoryItem::Individual(inventory_item) = item {
|
if let InventoryItem::Individual(inventory_item) = item {
|
||||||
|
@ -7,6 +7,7 @@ use crate::entity::item::{ItemDetail, ItemLocation, BankName};
|
|||||||
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, InventoryItemEntity, EquippedEntity, InventoryEntity, BankItemEntity, BankEntity};
|
use crate::entity::item::{Meseta, NewItemEntity, ItemEntity, InventoryItemEntity, EquippedEntity, InventoryEntity, BankItemEntity, BankEntity};
|
||||||
use crate::entity::item::tool::{Tool, ToolType};
|
use crate::entity::item::tool::{Tool, ToolType};
|
||||||
use crate::entity::item::unit;
|
use crate::entity::item::unit;
|
||||||
|
use crate::entity::item::weapon;
|
||||||
use crate::ship::map::MapArea;
|
use crate::ship::map::MapArea;
|
||||||
use crate::ship::ship::ItemDropLocation;
|
use crate::ship::ship::ItemDropLocation;
|
||||||
use crate::ship::drops::{ItemDrop, ItemDropType};
|
use crate::ship::drops::{ItemDrop, ItemDropType};
|
||||||
@ -611,7 +612,7 @@ impl ItemManager {
|
|||||||
|
|
||||||
let individual_item = mag_handle.item_mut()
|
let individual_item = mag_handle.item_mut()
|
||||||
.ok_or(ItemManagerError::NoSuchItemId(mag_id))?
|
.ok_or(ItemManagerError::NoSuchItemId(mag_id))?
|
||||||
.individual()
|
.individual_mut()
|
||||||
.ok_or(ItemManagerError::WrongItemType(mag_id))?;
|
.ok_or(ItemManagerError::WrongItemType(mag_id))?;
|
||||||
let mag = individual_item
|
let mag = individual_item
|
||||||
.mag_mut()
|
.mag_mut()
|
||||||
@ -888,4 +889,38 @@ impl ItemManager {
|
|||||||
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn replace_item_with_tekked<EG: EntityGateway>(&mut self,
|
||||||
|
entity_gateway: &mut EG,
|
||||||
|
character: &CharacterEntity,
|
||||||
|
item_id: ClientItemId,
|
||||||
|
tek: weapon::WeaponModifier)
|
||||||
|
-> Result<weapon::Weapon, anyhow::Error> {
|
||||||
|
let inventory = self.character_inventory.get_mut(&character.id).ok_or(ItemManagerError::NoCharacter(character.id))?;
|
||||||
|
|
||||||
|
let item = inventory.remove_by_id(item_id)
|
||||||
|
.ok_or(ItemManagerError::NoSuchItemId(item_id))?;
|
||||||
|
let individual = item
|
||||||
|
.individual()
|
||||||
|
.ok_or(ItemManagerError::WrongItemType(item_id))?;
|
||||||
|
|
||||||
|
let entity_id = individual.entity_id;
|
||||||
|
let mut weapon = individual
|
||||||
|
.weapon()
|
||||||
|
.ok_or(ItemManagerError::WrongItemType(item_id))?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
weapon.apply_modifier(&tek);
|
||||||
|
entity_gateway.add_weapon_modifier(&entity_id, tek).await?;
|
||||||
|
|
||||||
|
inventory.add_item(InventoryItem::Individual(IndividualInventoryItem {
|
||||||
|
entity_id: entity_id,
|
||||||
|
item_id: item_id,
|
||||||
|
item: ItemDetail::Weapon(weapon.clone()),
|
||||||
|
}));
|
||||||
|
|
||||||
|
entity_gateway.set_character_inventory(&character.id, &inventory.as_inventory_entity(&character.id)).await?;
|
||||||
|
|
||||||
|
Ok(weapon)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ async fn mag_cell<EG: EntityGateway>(entity_gateway: &mut EG, used_cell: &Consum
|
|||||||
let mag_item = mag_handle.item_mut()
|
let mag_item = mag_handle.item_mut()
|
||||||
.ok_or(UseItemError::InvalidItem)?;
|
.ok_or(UseItemError::InvalidItem)?;
|
||||||
let actual_mag = mag_item
|
let actual_mag = mag_item
|
||||||
.individual()
|
.individual_mut()
|
||||||
.ok_or(UseItemError::InvalidItem)?
|
.ok_or(UseItemError::InvalidItem)?
|
||||||
.mag_mut()
|
.mag_mut()
|
||||||
.ok_or(UseItemError::InvalidItem)?;
|
.ok_or(UseItemError::InvalidItem)?;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
use libpso::packet::messages::*;
|
use libpso::packet::messages::*;
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
|
use crate::entity::item;
|
||||||
use crate::common::leveltable::CharacterStats;
|
use crate::common::leveltable::CharacterStats;
|
||||||
use crate::ship::ship::{ShipError};
|
use crate::ship::ship::{ShipError};
|
||||||
use crate::ship::items::{ClientItemId, InventoryItem, StackedFloorItem, FloorItem, CharacterBank};
|
use crate::ship::items::{ClientItemId, InventoryItem, StackedFloorItem, FloorItem, CharacterBank};
|
||||||
@ -26,13 +27,13 @@ pub fn item_drop(client: u8, target: u8, item_drop: &FloorItem) -> Result<ItemDr
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_item(area_client: AreaClient, item: &FloorItem) -> Result<CreateItem, ShipError> {
|
pub fn create_item(area_client: AreaClient, item_id: ClientItemId, item: &item::ItemDetail) -> Result<CreateItem, ShipError> {
|
||||||
let bytes = item.as_client_bytes();
|
let bytes = item.as_client_bytes();
|
||||||
Ok(CreateItem {
|
Ok(CreateItem {
|
||||||
client: area_client.local_client.id(),
|
client: area_client.local_client.id(),
|
||||||
target: 0,
|
target: 0,
|
||||||
item_data: bytes[0..12].try_into()?,
|
item_data: bytes[0..12].try_into()?,
|
||||||
item_id: item.item_id().0,
|
item_id: item_id.0,
|
||||||
item_data2: bytes[12..16].try_into()?,
|
item_data2: bytes[12..16].try_into()?,
|
||||||
unknown: 0,
|
unknown: 0,
|
||||||
})
|
})
|
||||||
@ -162,3 +163,14 @@ pub fn shop_list<I: ShopItem>(shop_type: u8, items: &Vec<I>) -> ShopList {
|
|||||||
items: items,
|
items: 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()?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
|
use rand::Rng;
|
||||||
|
use rand::seq::SliceRandom;
|
||||||
use libpso::packet::ship::*;
|
use libpso::packet::ship::*;
|
||||||
use libpso::packet::messages::*;
|
use libpso::packet::messages::*;
|
||||||
use crate::common::leveltable::CharacterLevelTable;
|
use crate::common::leveltable::CharacterLevelTable;
|
||||||
@ -6,8 +8,9 @@ use crate::common::serverstate::ClientId;
|
|||||||
use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms, ItemShops};
|
use crate::ship::ship::{SendShipPacket, ShipError, Clients, Rooms, ItemShops};
|
||||||
use crate::ship::location::{ClientLocation, ClientLocationError};
|
use crate::ship::location::{ClientLocation, ClientLocationError};
|
||||||
use crate::ship::drops::ItemDrop;
|
use crate::ship::drops::ItemDrop;
|
||||||
use crate::ship::items::{ItemManager, ClientItemId, TriggerCreateItem, FloorItem, FloorType};
|
use crate::ship::items::{ItemManager, ItemManagerError, ClientItemId, TriggerCreateItem, FloorItem, FloorType};
|
||||||
use crate::entity::gateway::EntityGateway;
|
use crate::entity::gateway::EntityGateway;
|
||||||
|
use crate::entity::item;
|
||||||
use libpso::utf8_to_utf16_array;
|
use libpso::utf8_to_utf16_array;
|
||||||
use crate::ship::packet::builder;
|
use crate::ship::packet::builder;
|
||||||
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
use crate::ship::shops::{ShopItem, ToolShopItem, ArmorShopItem};
|
||||||
@ -24,6 +27,13 @@ const BANK_MESETA_CAPACITY: u32 = 999999;
|
|||||||
|
|
||||||
//const BANK_ACTION_: u8 = 1;
|
//const BANK_ACTION_: u8 = 1;
|
||||||
|
|
||||||
|
#[derive(thiserror::Error, Debug)]
|
||||||
|
#[error("")]
|
||||||
|
pub enum MessageError {
|
||||||
|
InvalidTek(ClientItemId),
|
||||||
|
MismatchedTekIds(ClientItemId, ClientItemId),
|
||||||
|
}
|
||||||
|
|
||||||
fn send_to_client(id: ClientId, target: u8, msg: DirectMessage, client_location: &ClientLocation)
|
fn send_to_client(id: ClientId, target: u8, msg: DirectMessage, client_location: &ClientLocation)
|
||||||
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
-> Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send> {
|
||||||
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
Box::new(client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
||||||
@ -127,8 +137,10 @@ where
|
|||||||
let (item, floor_type) = item_manager.get_floor_item_by_id(&client.character, ClientItemId(pickup_item.item_id))?;
|
let (item, floor_type) = item_manager.get_floor_item_by_id(&client.character, ClientItemId(pickup_item.item_id))?;
|
||||||
let remove_item = builder::message::remove_item_from_floor(area_client, &item)?;
|
let remove_item = builder::message::remove_item_from_floor(area_client, &item)?;
|
||||||
let create_item = match item {
|
let create_item = match item {
|
||||||
|
FloorItem::Individual(individual_floor_item) => Some(builder::message::create_item(area_client, item.item_id(), &individual_floor_item.item)?),
|
||||||
|
FloorItem::Stacked(stacked_floor_item) => Some(builder::message::create_item(area_client, item.item_id(), &item::ItemDetail::Tool(stacked_floor_item.tool))?),
|
||||||
FloorItem::Meseta(_) => None,
|
FloorItem::Meseta(_) => None,
|
||||||
_ => Some(builder::message::create_item(area_client, &item)?),
|
//_ => Some(builder::message::create_item(area_client, &item)?),
|
||||||
};
|
};
|
||||||
|
|
||||||
match item_manager.character_picks_up_item(entity_gateway, &mut client.character, ClientItemId(pickup_item.item_id)).await {
|
match item_manager.character_picks_up_item(entity_gateway, &mut client.character, ClientItemId(pickup_item.item_id)).await {
|
||||||
@ -393,3 +405,96 @@ where
|
|||||||
})))
|
})))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const TEK_SPECIAL_MODIFIER: [item::weapon::TekSpecialModifier; 3] = [item::weapon::TekSpecialModifier::Plus,
|
||||||
|
item::weapon::TekSpecialModifier::Neutral,
|
||||||
|
item::weapon::TekSpecialModifier::Minus];
|
||||||
|
const TEK_PERCENT_MODIFIER: [item::weapon::TekPercentModifier; 5] = [item::weapon::TekPercentModifier::PlusPlus,
|
||||||
|
item::weapon::TekPercentModifier::Plus,
|
||||||
|
item::weapon::TekPercentModifier::Neutral,
|
||||||
|
item::weapon::TekPercentModifier::Minus,
|
||||||
|
item::weapon::TekPercentModifier::MinusMinus];
|
||||||
|
|
||||||
|
pub async fn request_tek_item<EG>(id: ClientId,
|
||||||
|
tek_request: &TekRequest,
|
||||||
|
entity_gateway: &mut EG,
|
||||||
|
clients: &mut Clients,
|
||||||
|
item_manager: &mut ItemManager)
|
||||||
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
|
where
|
||||||
|
EG: EntityGateway
|
||||||
|
{
|
||||||
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
|
|
||||||
|
let (grind_mod, special_mod, percent_mod) = {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
|
||||||
|
let grind_mod = rng.gen_range(-4, 4);
|
||||||
|
let special_mod = TEK_SPECIAL_MODIFIER.choose(&mut rng).cloned().unwrap();
|
||||||
|
let percent_mod = TEK_PERCENT_MODIFIER.choose(&mut rng).cloned().unwrap();
|
||||||
|
(grind_mod, special_mod, percent_mod)
|
||||||
|
};
|
||||||
|
|
||||||
|
client.tek = Some((ClientItemId(tek_request.item_id), special_mod, percent_mod, grind_mod));
|
||||||
|
|
||||||
|
let inventory = item_manager.get_character_inventory(&client.character)?;
|
||||||
|
let item = inventory.get_item_by_id(ClientItemId(tek_request.item_id))
|
||||||
|
.ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?;
|
||||||
|
let mut weapon = item.individual()
|
||||||
|
.ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?
|
||||||
|
.weapon()
|
||||||
|
.ok_or(ItemManagerError::WrongItemType(ClientItemId(tek_request.item_id)))?
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
weapon.apply_modifier(&item::weapon::WeaponModifier::Tekked {
|
||||||
|
special: special_mod,
|
||||||
|
percent: percent_mod,
|
||||||
|
grind: grind_mod,
|
||||||
|
});
|
||||||
|
|
||||||
|
client.character.meseta -= 100;
|
||||||
|
entity_gateway.save_character(&client.character).await?;
|
||||||
|
|
||||||
|
let preview_pkt = builder::message::tek_preview(ClientItemId(tek_request.item_id), &weapon)?;
|
||||||
|
|
||||||
|
Ok(Box::new(vec![(id, SendShipPacket::Message(Message::new(GameMessage::TekPreview(preview_pkt))))].into_iter()))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn accept_tek_item<EG>(id: ClientId,
|
||||||
|
tek_accept: &TekAccept,
|
||||||
|
entity_gateway: &mut EG,
|
||||||
|
client_location: &ClientLocation,
|
||||||
|
clients: &mut Clients,
|
||||||
|
item_manager: &mut ItemManager)
|
||||||
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
|
where
|
||||||
|
EG: EntityGateway
|
||||||
|
{
|
||||||
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
|
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
|
||||||
|
if let Some((item_id, special_mod, percent_mod, grind_mod)) = client.tek {
|
||||||
|
if item_id.0 != tek_accept.item_id {
|
||||||
|
return Err(MessageError::MismatchedTekIds(item_id, ClientItemId(tek_accept.item_id)).into());
|
||||||
|
}
|
||||||
|
|
||||||
|
let modifier = item::weapon::WeaponModifier::Tekked {
|
||||||
|
special: special_mod,
|
||||||
|
percent: percent_mod,
|
||||||
|
grind: grind_mod,
|
||||||
|
};
|
||||||
|
let weapon = item_manager.replace_item_with_tekked(entity_gateway, &client.character, item_id, modifier).await?;
|
||||||
|
|
||||||
|
let create_item_pkt = builder::message::create_item(area_client, item_id, &item::ItemDetail::Weapon(weapon))?;
|
||||||
|
|
||||||
|
let neighbors = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
Ok(Box::new(neighbors.into_iter()
|
||||||
|
.map(move |c| {
|
||||||
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::CreateItem(create_item_pkt.clone()))))
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Err(MessageError::InvalidTek(ClientItemId(tek_accept.item_id)).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -114,48 +114,59 @@ pub fn drop_coordinates(id: ClientId,
|
|||||||
Ok(Box::new(None.into_iter()))
|
Ok(Box::new(None.into_iter()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn split_item_stack<EG>(id: ClientId,
|
pub async fn no_longer_has_item<EG>(id: ClientId,
|
||||||
no_longer_has_item: &PlayerNoLongerHasItem,
|
no_longer_has_item: &PlayerNoLongerHasItem,
|
||||||
entity_gateway: &mut EG,
|
entity_gateway: &mut EG,
|
||||||
client_location: &ClientLocation,
|
client_location: &ClientLocation,
|
||||||
clients: &mut Clients,
|
clients: &mut Clients,
|
||||||
item_manager: &mut ItemManager)
|
item_manager: &mut ItemManager)
|
||||||
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
-> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error>
|
||||||
where
|
where
|
||||||
EG: EntityGateway
|
EG: EntityGateway
|
||||||
{
|
{
|
||||||
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
let client = clients.get_mut(&id).ok_or(ShipError::ClientNotFound(id))?;
|
||||||
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let area_client = client_location.get_local_client(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
let room_id = client_location.get_room(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let drop_location = client.item_drop_location.ok_or(ShipError::ItemDropLocationNotSet)?;
|
if let Some(drop_location) = client.item_drop_location {
|
||||||
|
if drop_location.item_id.0 != no_longer_has_item.item_id {
|
||||||
|
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id).into());
|
||||||
|
}
|
||||||
|
|
||||||
if drop_location.item_id.0 != no_longer_has_item.item_id {
|
if no_longer_has_item.item_id == 0xFFFFFFFF {
|
||||||
return Err(ShipError::DropInvalidItemId(no_longer_has_item.item_id).into());
|
let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, no_longer_has_item.amount as u32).await?;
|
||||||
|
|
||||||
|
let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?;
|
||||||
|
client.item_drop_location = None;
|
||||||
|
|
||||||
|
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
Ok(Box::new(clients_in_area.into_iter()
|
||||||
|
.map(move |c| {
|
||||||
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_meseta_pkt.clone()))))
|
||||||
|
})))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, drop_location.item_id, drop_location, no_longer_has_item.amount as usize).await?;
|
||||||
|
|
||||||
|
let dropped_item_pkt = builder::message::drop_split_stack(area_client, dropped_item)?;
|
||||||
|
client.item_drop_location = None;
|
||||||
|
|
||||||
|
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
|
Ok(Box::new(clients_in_area.into_iter()
|
||||||
|
.map(move |c| {
|
||||||
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_item_pkt.clone()))))
|
||||||
|
})))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if let Some(_tek) = client.tek {
|
||||||
if no_longer_has_item.item_id == 0xFFFFFFFF {
|
let neighbors = client_location.get_client_neighbors(id).map_err(|err| -> ClientLocationError { err.into() })?;
|
||||||
let dropped_meseta = item_manager.player_drops_meseta_on_shared_floor(entity_gateway, &mut client.character, drop_location, no_longer_has_item.amount as u32).await?;
|
let no_longer_has_item = no_longer_has_item.clone();
|
||||||
|
Ok(Box::new(neighbors.into_iter()
|
||||||
let dropped_meseta_pkt = builder::message::drop_split_meseta_stack(area_client, &dropped_meseta)?;
|
|
||||||
client.item_drop_location = None;
|
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
|
||||||
Ok(Box::new(clients_in_area.into_iter()
|
|
||||||
.map(move |c| {
|
.map(move |c| {
|
||||||
(c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_meseta_pkt.clone()))))
|
(c.client, SendShipPacket::Message(Message::new(GameMessage::PlayerNoLongerHasItem(no_longer_has_item.clone()))))
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let dropped_item = item_manager.player_drops_partial_stack_on_shared_floor(entity_gateway, &client.character, drop_location.item_id, drop_location, no_longer_has_item.amount as usize).await?;
|
Err(ShipError::InvalidItem(ClientItemId(no_longer_has_item.item_id)).into())
|
||||||
|
|
||||||
let dropped_item_pkt = builder::message::drop_split_stack(area_client, dropped_item)?;
|
|
||||||
client.item_drop_location = None;
|
|
||||||
|
|
||||||
let clients_in_area = client_location.get_clients_in_room(room_id).map_err(|err| -> ClientLocationError { err.into() })?;
|
|
||||||
Ok(Box::new(clients_in_area.into_iter()
|
|
||||||
.map(move |c| {
|
|
||||||
(c.client, SendShipPacket::Message(Message::new(GameMessage::DropSplitStack(dropped_item_pkt.clone()))))
|
|
||||||
})))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ use crate::login::character::SHIP_MENU_ID;
|
|||||||
use crate::entity::gateway::{EntityGateway, GatewayError};
|
use crate::entity::gateway::{EntityGateway, GatewayError};
|
||||||
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
use crate::entity::account::{UserAccountEntity, UserSettingsEntity};
|
||||||
use crate::entity::character::{CharacterEntity, SectionID};
|
use crate::entity::character::{CharacterEntity, SectionID};
|
||||||
|
use crate::entity::item;
|
||||||
|
|
||||||
use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError};
|
use crate::ship::location::{ClientLocation, RoomLobby, MAX_ROOMS, ClientLocationError, GetNeighborError, GetClientsError, GetAreaError};
|
||||||
|
|
||||||
@ -71,6 +72,7 @@ pub enum ShipError {
|
|||||||
UnknownMonster(crate::ship::monster::MonsterType),
|
UnknownMonster(crate::ship::monster::MonsterType),
|
||||||
InvalidShip(usize),
|
InvalidShip(usize),
|
||||||
InvalidBlock(usize),
|
InvalidBlock(usize),
|
||||||
|
InvalidItem(items::ClientItemId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -254,6 +256,7 @@ pub struct ClientState {
|
|||||||
pub weapon_shop: Vec<WeaponShopItem>,
|
pub weapon_shop: Vec<WeaponShopItem>,
|
||||||
pub tool_shop: Vec<ToolShopItem>,
|
pub tool_shop: Vec<ToolShopItem>,
|
||||||
pub armor_shop: Vec<ArmorShopItem>,
|
pub armor_shop: Vec<ArmorShopItem>,
|
||||||
|
pub tek: Option<(items::ClientItemId, item::weapon::TekSpecialModifier, item::weapon::TekPercentModifier, i32)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientState {
|
impl ClientState {
|
||||||
@ -273,6 +276,7 @@ impl ClientState {
|
|||||||
weapon_shop: Vec::new(),
|
weapon_shop: Vec::new(),
|
||||||
tool_shop: Vec::new(),
|
tool_shop: Vec::new(),
|
||||||
armor_shop: Vec::new(),
|
armor_shop: Vec::new(),
|
||||||
|
tek: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -445,7 +449,7 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
},
|
},
|
||||||
GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
|
GameMessage::PlayerNoLongerHasItem(no_longer_has_item) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
handler::message::split_item_stack(id, no_longer_has_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await?
|
handler::message::no_longer_has_item(id, no_longer_has_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
|
GameMessage::PlayerChangedMap(_) | GameMessage::PlayerChangedMap2(_) | GameMessage::TellOtherPlayerMyLocation(_) |
|
||||||
GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
|
GameMessage::PlayerWarpingToFloor(_) | GameMessage::PlayerTeleported(_) | GameMessage::PlayerStopped(_) |
|
||||||
@ -490,41 +494,40 @@ impl<EG: EntityGateway> ShipServerState<EG> {
|
|||||||
|
|
||||||
async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
async fn direct_message(&mut self, id: ClientId, msg: &DirectMessage) -> Result<Box<dyn Iterator<Item = (ClientId, SendShipPacket)> + Send>, anyhow::Error> {
|
||||||
let target = msg.flag;
|
let target = msg.flag;
|
||||||
|
let block = self.blocks.with_client(id, &self.clients)?;
|
||||||
Ok(match &msg.msg {
|
Ok(match &msg.msg {
|
||||||
GameMessage::GuildcardSend(guildcard_send) => {
|
GameMessage::GuildcardSend(guildcard_send) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients)
|
handler::direct_message::guildcard_send(id, guildcard_send, target, &block.client_location, &self.clients)
|
||||||
},
|
},
|
||||||
GameMessage::RequestItem(request_item) => {
|
GameMessage::RequestItem(request_item) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
|
handler::direct_message::request_item(id, request_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
GameMessage::PickupItem(pickup_item) => {
|
GameMessage::PickupItem(pickup_item) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await?
|
handler::direct_message::pickup_item(id, pickup_item, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
GameMessage::BoxDropRequest(box_drop_request) => {
|
GameMessage::BoxDropRequest(box_drop_request) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
|
handler::direct_message::request_box_item(id, box_drop_request, &mut self.entity_gateway, &mut block.client_location, &mut self.clients, &mut block.rooms, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
GameMessage::BankRequest(_bank_request) => {
|
GameMessage::BankRequest(_bank_request) => {
|
||||||
handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await?
|
handler::direct_message::send_bank_list(id, &self.clients, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
GameMessage::BankInteraction(bank_interaction) => {
|
GameMessage::BankInteraction(bank_interaction) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
|
handler::direct_message::bank_interaction(id, bank_interaction, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
GameMessage::ShopRequest(shop_request) => {
|
GameMessage::ShopRequest(shop_request) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await?
|
handler::direct_message::shop_request(id, shop_request, &block.client_location, &mut self.clients, &block.rooms, &self.level_table, &mut self.shops).await?
|
||||||
},
|
},
|
||||||
GameMessage::BuyItem(buy_item) => {
|
GameMessage::BuyItem(buy_item) => {
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
|
handler::direct_message::buy_item(id, buy_item, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
|
||||||
},
|
},
|
||||||
|
GameMessage::TekRequest(tek_request) => {
|
||||||
|
handler::direct_message::request_tek_item(id, tek_request, &mut self.entity_gateway, &mut self.clients, &mut self.item_manager).await?
|
||||||
|
},
|
||||||
|
GameMessage::TekAccept(tek_accept) => {
|
||||||
|
handler::direct_message::accept_tek_item(id, tek_accept, &mut self.entity_gateway, &block.client_location, &mut self.clients, &mut self.item_manager).await?
|
||||||
|
},
|
||||||
_ => {
|
_ => {
|
||||||
let cmsg = msg.clone();
|
let cmsg = msg.clone();
|
||||||
let block = self.blocks.with_client(id, &self.clients)?;
|
|
||||||
Box::new(block.client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
Box::new(block.client_location.get_all_clients_by_client(id).unwrap().into_iter()
|
||||||
.filter(move |client| client.local_client.id() == target as u8)
|
.filter(move |client| client.local_client.id() == target as u8)
|
||||||
.map(move |client| {
|
.map(move |client| {
|
||||||
|
@ -71,7 +71,6 @@ impl ShopItem for ArmorShopItem {
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: *slot as u8,
|
slots: *slot as u8,
|
||||||
modifiers: Vec::new()
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
ArmorShopItem::Barrier(barrier) => {
|
ArmorShopItem::Barrier(barrier) => {
|
||||||
|
@ -142,7 +142,6 @@ impl ShopItem for WeaponShopItem {
|
|||||||
grind: self.grind as u8,
|
grind: self.grind as u8,
|
||||||
attrs: [self.attributes[0], self.attributes[1], None],
|
attrs: [self.attributes[0], self.attributes[1], None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,6 @@ async fn test_bank_items_sent_in_character_login() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -69,7 +68,6 @@ async fn test_request_bank_items() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -167,7 +165,6 @@ async fn test_request_bank_items_sorted() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -196,7 +193,6 @@ async fn test_request_bank_items_sorted() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -247,7 +243,6 @@ async fn test_deposit_individual_item() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -263,7 +258,6 @@ async fn test_deposit_individual_item() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -623,7 +617,6 @@ async fn test_deposit_individual_item_in_full_bank() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -642,7 +635,6 @@ async fn test_deposit_individual_item_in_full_bank() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -722,7 +714,6 @@ async fn test_deposit_stacked_item_in_full_bank() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -819,7 +810,6 @@ async fn test_deposit_stacked_item_in_full_bank_with_partial_stack() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -998,7 +988,6 @@ async fn test_withdraw_individual_item() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -1358,7 +1347,6 @@ async fn test_withdraw_individual_item_in_full_inventory() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Bank {
|
location: item::ItemLocation::Bank {
|
||||||
@ -1378,7 +1366,6 @@ async fn test_withdraw_individual_item_in_full_inventory() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -1454,7 +1441,6 @@ async fn test_withdraw_stacked_item_in_full_inventory() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -1537,7 +1523,6 @@ async fn test_withdraw_stacked_item_in_full_inventory_with_partial_stack() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
|
@ -25,7 +25,6 @@ async fn test_equip_unit_from_equip_menu() {
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 4,
|
slots: 4,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}),
|
}),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
@ -112,7 +111,6 @@ async fn test_unequip_armor_with_units() {
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 4,
|
slots: 4,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}),
|
}),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
@ -190,7 +188,6 @@ async fn test_sort_items() {
|
|||||||
dfp: 0,
|
dfp: 0,
|
||||||
evp: 0,
|
evp: 0,
|
||||||
slots: 4,
|
slots: 4,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}),
|
}),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
character_id: char1.id,
|
character_id: char1.id,
|
||||||
|
@ -172,7 +172,6 @@ async fn test_pick_up_meseta_when_inventory_full() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -252,7 +251,6 @@ async fn test_pick_up_partial_stacked_item_when_inventory_is_otherwise_full() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -345,7 +343,6 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -364,7 +361,6 @@ async fn test_can_not_pick_up_item_when_inventory_full() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
|
@ -29,7 +29,6 @@ async fn test_item_ids_reset_when_rejoining_rooms() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
@ -49,7 +48,6 @@ async fn test_item_ids_reset_when_rejoining_rooms() {
|
|||||||
special: None,
|
special: None,
|
||||||
attrs: [None, None, None],
|
attrs: [None, None, None],
|
||||||
tekked: true,
|
tekked: true,
|
||||||
modifiers: Vec::new(),
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
location: item::ItemLocation::Inventory {
|
location: item::ItemLocation::Inventory {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user