diff --git a/src/entity/item/weapon.rs b/src/entity/item/weapon.rs index 8e9db4b..29a9357 100644 --- a/src/entity/item/weapon.rs +++ b/src/entity/item/weapon.rs @@ -1479,44 +1479,52 @@ impl Weapon { } pub fn apply_modifier(&mut self, modifier: &WeaponModifier) { - if let WeaponModifier::Tekked{special, percent, grind} = modifier { - 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 => { + 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 - }); + attr + }); + } + self.grind = std::cmp::max(self.grind as i32 + grind, 0) as u8; + self.tekked = true; + }, + WeaponModifier::AddGrind {amount, ..} => { + self.grind += *amount as u8; + }, + WeaponModifier::AddPercents {..} => { + // TODO } - self.grind = std::cmp::max(self.grind as i32 + grind, 0) as u8; - self.tekked = true; } } diff --git a/src/ship/items/apply_item.rs b/src/ship/items/apply_item.rs index 9820226..ad2f27d 100644 --- a/src/ship/items/apply_item.rs +++ b/src/ship/items/apply_item.rs @@ -10,6 +10,7 @@ use crate::entity::item::mag::{MagCell, MagCellError}; use crate::entity::item::tool::{Tool, ToolType}; use crate::entity::item::tech::TechniqueDisk; use crate::entity::item::{ItemDetail, ItemEntityId}; +use crate::entity::item::weapon::WeaponModifier; use crate::ship::items::state::ItemStateProxy; use crate::ship::items::inventory::{InventoryItem, InventoryItemDetail}; @@ -34,7 +35,7 @@ pub enum ApplyItemError { pub enum ApplyItemAction { UpdateCharacter(Box), CreateItem(ItemDetail), - //TransformItem, + //TransformItem(ItemDetail), //RemoveItem, } @@ -241,6 +242,30 @@ fn jack_o_lantern() -> Result, anyhow::Error> Ok(vec![ApplyItemAction::CreateItem(ItemDetail::Tool(Tool {tool: mag_type}))]) } +async fn weapon_grind<'a, EG>(item_state: &mut ItemStateProxy, + entity_gateway: &mut EG, + character: &mut CharacterEntity, + entity_id: ItemEntityId, + grind: u32,) + -> Result, anyhow::Error> +where + EG: EntityGateway + ?Sized, +{ + let modifier = WeaponModifier::AddGrind { + amount: grind, + grinder: entity_id, + }; + + let mut inventory = item_state.inventory(&character.id).await?; + let (weapon_entity_id, weapon) = inventory.equipped_weapon_mut() + .ok_or(ApplyItemError::ItemNotEquipped)?; + weapon.apply_modifier(&modifier); + entity_gateway.add_weapon_modifier(&weapon_entity_id, &modifier).await?; + item_state.set_inventory(inventory).await; + + Ok(Vec::new()) +} + async fn apply_tool<'a, EG>(item_state: &mut ItemStateProxy, entity_gateway: &mut EG, character: &mut CharacterEntity, @@ -271,6 +296,9 @@ where ToolType::Antidote => Ok(Vec::new()), ToolType::Antiparalysis => Ok(Vec::new()), ToolType::TrapVision => Ok(Vec::new()), + ToolType::Monogrinder => weapon_grind(item_state, entity_gateway, character, entity_id, 1).await, + ToolType::Digrinder => weapon_grind(item_state, entity_gateway, character, entity_id, 2).await, + ToolType::Trigrinder => weapon_grind(item_state, entity_gateway, character, entity_id, 3).await, ToolType::HuntersReport => Ok(Vec::new()), ToolType::CellOfMag502 | ToolType::CellOfMag213 diff --git a/src/ship/items/inventory.rs b/src/ship/items/inventory.rs index bfd709b..d7e74fd 100644 --- a/src/ship/items/inventory.rs +++ b/src/ship/items/inventory.rs @@ -7,6 +7,7 @@ use std::future::Future; use crate::entity::character::CharacterEntityId; use crate::entity::item::tool::ToolType; use crate::entity::item::mag::Mag; +use crate::entity::item::weapon::Weapon; use crate::ship::shops::{ShopItem, ArmorShopItem, ToolShopItem, WeaponShopItem}; use crate::ship::items::state::ItemStateError; use crate::ship::items::state::{IndividualItemDetail, StackedItemDetail, AddItemResult}; @@ -453,6 +454,18 @@ impl InventoryState { .find(|(entity_id, _)| *entity_id == mag_id) } + pub fn equipped_weapon_mut(&mut self) -> Option<(ItemEntityId, &mut Weapon)> { + let weapon_id = self.equipped.weapon?; + self.inventory.0 + .iter_mut() + .filter_map(|i| { + let individual = i.item.as_individual_mut()?; + let entity_id = individual.entity_id; + Some((entity_id, individual.as_weapon_mut()?)) + }) + .find(|(entity_id, _)| *entity_id == weapon_id) + } + pub fn sort(&mut self, item_ids: &[ClientItemId]) { self.inventory.0.sort_by(|a, b| { let a_index = item_ids.iter().position(|item_id| *item_id == a.item_id); diff --git a/src/ship/items/state.rs b/src/ship/items/state.rs index a166d8b..79f24eb 100644 --- a/src/ship/items/state.rs +++ b/src/ship/items/state.rs @@ -91,6 +91,14 @@ impl IndividualItemDetail { } } + pub fn as_weapon_mut(&mut self) -> Option<&mut Weapon> { + match &mut self.item { + ItemDetail::Weapon(weapon) => Some(weapon), + _ => None + } + } + + pub fn as_client_bytes(&self) -> [u8; 16] { match &self.item { ItemDetail::Weapon(w) => w.as_bytes(), diff --git a/tests/test_item_use.rs b/tests/test_item_use.rs index f9a9b67..6474e6f 100644 --- a/tests/test_item_use.rs +++ b/tests/test_item_use.rs @@ -312,22 +312,6 @@ async fn test_use_barta_1() { let (user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await; - /* - let mut p1_inv = Vec::new(); - for tool in vec![item::tool::ToolType::PowerMaterial, item::tool::ToolType::].into_iter() { - let mut item = Vec::new(); - for _ in 0..5usize { - item.push(entity_gateway.create_item( - item::NewItemEntity { - item: item::ItemDetail::Tool( - item::tool::Tool { - tool: tool - } - ), - }).await.unwrap()); - } - p1_inv.push(item::InventoryItemEntity::Stacked(item)); -}*/ let inv = vec![ entity_gateway.create_item( item::NewItemEntity { @@ -391,6 +375,76 @@ async fn test_use_barta_1() { assert!(char.techs.techs.get(&item::tech::Technique::Barta).is_none()); } + +#[async_std::test] +async fn test_use_monogrinder() { + let mut entity_gateway = InMemoryGateway::default(); + + let (_user1, char1) = new_user_character(&mut entity_gateway, "a1", "a", 1).await; + + let saber = entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Weapon( + item::weapon::Weapon { + weapon: item::weapon::WeaponType::Saber, + grind: 0, + special: None, + attrs: [None, None, None], + tekked: true, + } + ), + }).await.unwrap(); + + let mut grinders = Vec::new(); + for _ in 0..3usize { + grinders.push(entity_gateway.create_item( + item::NewItemEntity { + item: item::ItemDetail::Tool( + item::tool::Tool { + tool: item::tool::ToolType::Monogrinder, + } + ), + }).await.unwrap()); + } + + let equipped = item::EquippedEntity { + weapon: Some(saber.id), + armor: None, + shield: None, + unit: [None; 4], + mag: None, + }; + entity_gateway.set_character_equips(&char1.id, &equipped).await.unwrap(); + entity_gateway.set_character_inventory(&char1.id, &item::InventoryEntity::new(vec![item::InventoryItemEntity::Individual(saber), + item::InventoryItemEntity::Stacked(grinders)])).await.unwrap(); + + let mut ship = Box::new(ShipServerState::builder() + .gateway(entity_gateway.clone()) + .build()); + log_in_char(&mut ship, ClientId(1), "a1", "a").await; + join_lobby(&mut ship, ClientId(1)).await; + create_room(&mut ship, ClientId(1), "room", "").await; + + ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem { + client: 0, + target: 0, + item_id: 0x10001, + })))).await.unwrap(); + + ship.handle(ClientId(1), RecvShipPacket::Message(Message::new(GameMessage::PlayerUseItem(PlayerUseItem { + client: 0, + target: 0, + item_id: 0x10001, + })))).await.unwrap(); + + let inventory_items = entity_gateway.get_character_inventory(&char1.id).await.unwrap(); + assert_eq!(inventory_items.items.len(), 2); + + assert!(matches!(inventory_items.items[0], item::InventoryItemEntity::Individual(item::ItemEntity{ item: item::ItemDetail::Weapon(item::weapon::Weapon {grind: 2, ..}), ..}))); +} + + + // TODO: tests for ALL ITEMS WOW /*